<commit_before>extern crate winapi;
extern crate user32;

use self::user32::*;
use self::winapi::*;

use super::{KeyboardControllable, MouseControllable};
use std::mem::*;

/// The main struct for handling the event emitting
pub struct Enigo {
    current_x: i32,
    current_y: i32,
}

impl Enigo {
    // TODO(dustin): to the right initialisation

    /// Constructs a new `Enigo` instance.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// ```
    pub fn new() -> Self {
        Enigo {
            current_x: 0,
            current_y: 0,
        }
    }
}

impl MouseControllable for Enigo {
    fn mouse_move_to(&mut self, x: i32, y: i32) {
        // TODO(dustin): use interior mutability
        self.current_x = x;
        self.current_y = y;
        unsafe { SetCursorPos(self.current_x, self.current_y) };
    }

    fn mouse_move_relative(&mut self, x: i32, y: i32) {
        // TODO(dustin): use interior mutability
        self.current_x += x;
        self.current_y += y;
        unsafe { SetCursorPos(self.current_x, self.current_y) };
    }

    // TODO(dustin): use button parameter, current implementation
    // is using the left mouse button every time
    fn mouse_down(&mut self, button: u32) {
        unsafe {
            let mut input = INPUT {
                type_: INPUT_MOUSE,
                u: transmute_copy(&MOUSEINPUT {
                                      dx: 0,
                                      dy: 0,
                                      mouseData: 0,
                                      dwFlags: MOUSEEVENTF_LEFTDOWN,
                                      time: 0,
                                      dwExtraInfo: 0,
                                  }),
            };

            SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
        }
    }

    // TODO(dustin): use button parameter, current implementation
    // is using the left mouse button every time
    fn mouse_up(&mut self, button: u32) {
        unsafe {
            let mut input = INPUT {
                type_: INPUT_MOUSE,
                u: transmute_copy(&MOUSEINPUT {
                                      dx: 0,
                                      dy: 0,
                                      mouseData: 0,
                                      dwFlags: MOUSEEVENTF_LEFTUP,
                                      time: 0,
                                      dwExtraInfo: 0,
                                  }),
            };

            SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
        }
    }

    fn mouse_click(&mut self, button: u32) {
        self.mouse_down(button);
        self.mouse_up(button);
    }

    fn mouse_scroll_x(&mut self, length: i32) {
        let mut scroll_direction = 1 * 50; // 1 left -1 right
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mut input = INPUT {
                    type_: INPUT_MOUSE,
                    u: transmute_copy(&MOUSEINPUT {
                                          dx: 0,
                                          dy: 0,
                                          mouseData: transmute_copy(&scroll_direction),
                                          dwFlags: MOUSEEVENTF_HWHEEL,
                                          time: 0,
                                          dwExtraInfo: 0,
                                      }),
                };

                SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
            }
        }
    }

    fn mouse_scroll_y(&mut self, length: i32) {
        let mut scroll_direction = -1 * 50; // 1 left -1 right
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mut input = INPUT {
                    type_: INPUT_MOUSE,
                    u: transmute_copy(&MOUSEINPUT {
                                          dx: 0,
                                          dy: 0,
                                          mouseData: transmute_copy(&scroll_direction),
                                          dwFlags: MOUSEEVENTF_WHEEL,
                                          time: 0,
                                          dwExtraInfo: 0,
                                      }),
                };

                SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
            }
        }
    }
}

impl KeyboardControllable for Enigo {
    fn key_sequence(&mut self, sequence: &str) {
        //unimplemented!()

        for c in sequence.chars() {
            let mut buffer = [0; 2];
            let result = c.encode_utf16(&mut buffer);
            //Note(dustin): this is wrong utf16 is variable length
            //but i don't know how to feed that properly into SendInput
            let single_u16_result = result[0];
            self.keyclick(single_u16_result);
        }
    }
}

impl Enigo {
    fn keyclick(&self, unicode_char: u16) {
        use std::{thread, time};
        thread::sleep(time::Duration::from_millis(20));
        self.keydown(unicode_char);
        self.keyup(unicode_char);
        thread::sleep(time::Duration::from_millis(20));
    }

    fn keydown(&self, unicode_char: u16) {
        unsafe {
            let mut input = INPUT {
                type_: INPUT_KEYBOARD,
                u: transmute_copy(&KEYBDINPUT {
                                      wVk: 0,
                                      wScan: unicode_char,
                                      dwFlags: KEYEVENTF_UNICODE,
                                      time: 0,
                                      dwExtraInfo: 0,
                                  }),
            };

            SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
        }
    }

    fn keyup(&self, unicode_char: u16) {
        unsafe {
            let mut input = INPUT {
                type_: INPUT_MOUSE,
                u: transmute_copy(&KEYBDINPUT {
                                      wVk: 0,
                                      wScan: unicode_char,
                                      dwFlags: KEYEVENTF_UNICODE | KEYEVENTF_KEYUP,
                                      time: 0,
                                      dwExtraInfo: 0,
                                  }),
            };

            SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
        }
    }
}
<commit_msg>implemented the win key_sequence in a correct way<commit_after>extern crate winapi;
extern crate user32;

use self::user32::*;
use self::winapi::*;

use super::{KeyboardControllable, MouseControllable};
use std::mem::*;

/// The main struct for handling the event emitting
pub struct Enigo {
    current_x: i32,
    current_y: i32,
}

impl Enigo {
    // TODO(dustin): do the right initialisation

    /// Constructs a new `Enigo` instance.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use enigo::*;
    /// let mut enigo = Enigo::new();
    /// ```
    pub fn new() -> Self {
        Enigo {
            current_x: 0,
            current_y: 0,
        }
    }
}

impl MouseControllable for Enigo {
    fn mouse_move_to(&mut self, x: i32, y: i32) {
        // TODO(dustin): use interior mutability
        self.current_x = x;
        self.current_y = y;
        unsafe { SetCursorPos(self.current_x, self.current_y) };
    }

    fn mouse_move_relative(&mut self, x: i32, y: i32) {
        // TODO(dustin): use interior mutability
        self.current_x += x;
        self.current_y += y;
        unsafe { SetCursorPos(self.current_x, self.current_y) };
    }

    // TODO(dustin): use button parameter, current implementation
    // is using the left mouse button every time
    fn mouse_down(&mut self, button: u32) {
        unsafe {
            let mut input = INPUT {
                type_: INPUT_MOUSE,
                u: transmute_copy(&MOUSEINPUT {
                                      dx: 0,
                                      dy: 0,
                                      mouseData: 0,
                                      dwFlags: MOUSEEVENTF_LEFTDOWN,
                                      time: 0,
                                      dwExtraInfo: 0,
                                  }),
            };

            SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
        }
    }

    // TODO(dustin): use button parameter, current implementation
    // is using the left mouse button every time
    fn mouse_up(&mut self, button: u32) {
        unsafe {
            let mut input = INPUT {
                type_: INPUT_MOUSE,
                u: transmute_copy(&MOUSEINPUT {
                                      dx: 0,
                                      dy: 0,
                                      mouseData: 0,
                                      dwFlags: MOUSEEVENTF_LEFTUP,
                                      time: 0,
                                      dwExtraInfo: 0,
                                  }),
            };

            SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
        }
    }

    fn mouse_click(&mut self, button: u32) {
        self.mouse_down(button);
        self.mouse_up(button);
    }

    fn mouse_scroll_x(&mut self, length: i32) {
        let mut scroll_direction = 1 * 50; // 1 left -1 right
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mut input = INPUT {
                    type_: INPUT_MOUSE,
                    u: transmute_copy(&MOUSEINPUT {
                                          dx: 0,
                                          dy: 0,
                                          mouseData: transmute_copy(&scroll_direction),
                                          dwFlags: MOUSEEVENTF_HWHEEL,
                                          time: 0,
                                          dwExtraInfo: 0,
                                      }),
                };

                SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
            }
        }
    }

    fn mouse_scroll_y(&mut self, length: i32) {
        let mut scroll_direction = -1 * 50; // 1 left -1 right
        let mut length = length;

        if length < 0 {
            length *= -1;
            scroll_direction *= -1;
        }

        for _ in 0..length {
            unsafe {
                let mut input = INPUT {
                    type_: INPUT_MOUSE,
                    u: transmute_copy(&MOUSEINPUT {
                                          dx: 0,
                                          dy: 0,
                                          mouseData: transmute_copy(&scroll_direction),
                                          dwFlags: MOUSEEVENTF_WHEEL,
                                          time: 0,
                                          dwExtraInfo: 0,
                                      }),
                };

                SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
            }
        }
    }
}

impl KeyboardControllable for Enigo {
    fn key_sequence(&mut self, sequence: &str) {
        let mut buffer = [0; 2];

        for c in sequence.chars() {
            //Windows uses uft-16 encoding. We need to check
            //for variable length characters. As such some
            //characters can be 32 bit long and those are
            //encoded in such called hight and low surrogates
            //each 16 bit wide that needs to be send after
            //another to the SendInput function without
            //being interrupted by "keyup"
            let result = c.encode_utf16(&mut buffer);
            if result.len() == 1 {
                self.keyclick(result[0]);
            } else {
                for utf16_surrogate in result {
                    self.keydown(utf16_surrogate.clone());
                }
                self.keyup(0);
            }
        }
    }
}

impl Enigo {
    fn keyclick(&self, unicode_char: u16) {
        use std::{thread, time};
        thread::sleep(time::Duration::from_millis(20));
        self.keydown(unicode_char);
        self.keyup(unicode_char);
        thread::sleep(time::Duration::from_millis(20));
    }

    fn keydown(&self, unicode_char: u16) {
        unsafe {
            let mut input = INPUT {
                type_: INPUT_KEYBOARD,
                u: transmute_copy(&KEYBDINPUT {
                                      wVk: 0,
                                      wScan: unicode_char,
                                      dwFlags: KEYEVENTF_UNICODE,
                                      time: 0,
                                      dwExtraInfo: 0,
                                  }),
            };

            SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
        }
    }

    fn keyup(&self, unicode_char: u16) {
        unsafe {
            let mut input = INPUT {
                type_: INPUT_MOUSE,
                u: transmute_copy(&KEYBDINPUT {
                                      wVk: 0,
                                      wScan: unicode_char,
                                      dwFlags: KEYEVENTF_UNICODE | KEYEVENTF_KEYUP,
                                      time: 0,
                                      dwExtraInfo: 0,
                                  }),
            };

            SendInput(1, &mut input as LPINPUT, size_of::<INPUT>() as c_int);
        }
    }
}
<|endoftext|>


<commit_before>#![feature(convert)]
use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
	        match *self {
				Error::InvalidValue => write!(f, "Invalid value."),
				Error::InvalidType => write!(f, "Invalid type."),
				Error::Io(ref err) => err.fmt(f),
			}
	}
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidValue => "Invalid value.",
            Error::InvalidType => "Invalid type.",
            Error::Io(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidValue => None,
            Error::InvalidType => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

pub struct XdrReader<'a> {
	reader : io::Cursor<&'a [u8]>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn get_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

	pub fn pack<T:XdrPrimitive>(&mut self, x:T) {
		XdrPrimitive::write_to_xdr(self, x)
	}

}
impl<'a> XdrReader<'a> {
	pub fn new(x:&'a Vec<u8>) -> XdrReader<'a> {
		XdrReader{ reader : io::Cursor::new(x.as_slice()) }
	}

	pub fn from_array(x: &'a [u8]) -> XdrReader<'a> {
		XdrReader{ reader: io::Cursor::new(x) }
	}

	pub fn unpack<T: XdrPrimitive>(&mut self) -> Result<T,Error> {
		T::read_from_xdr(self)
	}
}

pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl<T:XdrPrimitive> XdrPrimitive for Vec<T> {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>{
		let count = x.unpack::<u32>().unwrap() as usize;
		let mut result : Vec<T> = Vec::with_capacity(count);

		for _ in 0..count {
			result.push(x.unpack::<T>().unwrap());
		};
		Ok(result)
	}
	fn write_to_xdr(x: &mut XdrWriter, v: Self) {
		x.pack( v.len() as u32 );
		for t in v {
			x.pack(t);
		};
	}
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i64::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u64::<byteorder::BigEndian>(v).unwrap();
	}

}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f64::<byteorder::BigEndian>(v).unwrap();
	}
}

impl XdrPrimitive for bool {
	fn read_from_xdr(x: &mut XdrReader) -> Result<bool, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(0) => Ok(false),
			Ok(1) => Ok(true),
			Ok(_) => Err(Error::InvalidValue),
			Err(v) => Err(Error::Io(v))
		}
	}

	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		match v {
			true => x.writer.write_u32::<byteorder::BigEndian>(1).unwrap(),
			false => x.writer.write_u32::<byteorder::BigEndian>(0).unwrap(),
		}
	}
}
<commit_msg>remove feature(convert) from xdr module<commit_after>use std::io;
use std::fmt;
use std::error;
use std::vec::Vec;
use byteorder;
use byteorder::{BigEndian,ReadBytesExt,WriteBytesExt};

#[derive(Debug)]
pub enum Error {
	Io(byteorder::Error),
	InvalidValue,
	InvalidType
}

impl From<byteorder::Error> for Error {
	fn from(err: byteorder::Error) -> Error { Error::Io(err) }
}

impl From<Error> for byteorder::Error {
	fn from(err: Error) -> byteorder::Error {
		match err {
			Error::Io(err) => err,
			Error::InvalidValue => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid value")),
			Error::InvalidType => byteorder::Error::Io(io::Error::new(io::ErrorKind::Other, "Invalid type")),
		}
	}
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
	        match *self {
				Error::InvalidValue => write!(f, "Invalid value."),
				Error::InvalidType => write!(f, "Invalid type."),
				Error::Io(ref err) => err.fmt(f),
			}
	}
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::InvalidValue => "Invalid value.",
            Error::InvalidType => "Invalid type.",
            Error::Io(ref err) => error::Error::description(err),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::InvalidValue => None,
            Error::InvalidType => None,
            Error::Io(ref err) => err.cause(),
        }
    }
}

pub struct XdrReader<'a> {
	reader : io::Cursor<&'a [u8]>
}

pub struct XdrWriter {
	writer : io::Cursor<Vec<u8>>
}

impl XdrWriter {
	pub fn new() -> XdrWriter {
		let v : Vec<u8>= Vec::new();
		XdrWriter{ writer: io::Cursor::new(v)}
	}

	pub fn get_buffer(self) -> Vec<u8> {
		self.writer.into_inner()
	}

	pub fn pack<T:XdrPrimitive>(&mut self, x:T) {
		XdrPrimitive::write_to_xdr(self, x)
	}

}
impl<'a> XdrReader<'a> {
	pub fn new(x:&'a Vec<u8>) -> XdrReader<'a> {
		XdrReader{ reader : io::Cursor::new(x.as_slice()) }
	}

	pub fn from_array(x: &'a [u8]) -> XdrReader<'a> {
		XdrReader{ reader: io::Cursor::new(x) }
	}

	pub fn unpack<T: XdrPrimitive>(&mut self) -> Result<T,Error> {
		T::read_from_xdr(self)
	}
}

pub trait XdrPrimitive {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>;
	fn write_to_xdr(x: &mut XdrWriter, v: Self);
}

impl<T:XdrPrimitive> XdrPrimitive for Vec<T> {
	fn read_from_xdr(x: &mut XdrReader) -> Result<Self, Error>{
		let count = x.unpack::<u32>().unwrap() as usize;
		let mut result : Vec<T> = Vec::with_capacity(count);

		for _ in 0..count {
			result.push(x.unpack::<T>().unwrap());
		};
		Ok(result)
	}
	fn write_to_xdr(x: &mut XdrWriter, v: Self) {
		x.pack( v.len() as u32 );
		for t in v {
			x.pack(t);
		};
	}
}

impl XdrPrimitive for u32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u32, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u16, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for u8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u8, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as u8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u32::<byteorder::BigEndian>(v as u32).unwrap();
	}
}
impl XdrPrimitive for i8 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i8, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i8),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i16 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i16, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v as i16),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v as i32).unwrap();
	}
}
impl XdrPrimitive for i32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i32, Error>{
		match x.reader.read_i32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for i64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<i64, Error>{
		match x.reader.read_i64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_i64::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for u64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<u64, Error>{
		match x.reader.read_u64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_u64::<byteorder::BigEndian>(v).unwrap();
	}

}

impl XdrPrimitive for f32 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f32, Error>{
		match x.reader.read_f32::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f32::<byteorder::BigEndian>(v).unwrap();
	}
}
impl XdrPrimitive for f64 {
	fn read_from_xdr(x: &mut XdrReader) -> Result<f64, Error>{
		match x.reader.read_f64::<byteorder::BigEndian>() {
			Ok(v) => Ok(v),
			Err(v) => Err(Error::Io(v))
		}

	}
	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		x.writer.write_f64::<byteorder::BigEndian>(v).unwrap();
	}
}

impl XdrPrimitive for bool {
	fn read_from_xdr(x: &mut XdrReader) -> Result<bool, Error>{
		match x.reader.read_u32::<byteorder::BigEndian>() {
			Ok(0) => Ok(false),
			Ok(1) => Ok(true),
			Ok(_) => Err(Error::InvalidValue),
			Err(v) => Err(Error::Io(v))
		}
	}

	fn write_to_xdr(x: &mut XdrWriter, v:Self) {
		match v {
			true => x.writer.write_u32::<byteorder::BigEndian>(1).unwrap(),
			false => x.writer.write_u32::<byteorder::BigEndian>(0).unwrap(),
		}
	}
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A cell that with volatile setter and getter.

#![feature(core, no_std, core_intrinsics)]
#![no_std]

extern crate core;

#[cfg(feature="replayer")] #[macro_use(expect)] extern crate expectest;
#[cfg(feature="replayer")] #[macro_use] extern crate std;

#[cfg(feature="replayer")] use std::vec::Vec;
#[cfg(feature="replayer")] use expectest::prelude::*;
#[cfg(feature="replayer")] use std::string::String;
#[cfg(feature="replayer")] use std::fmt;
#[cfg(feature="replayer")] use core::cmp::PartialEq;
#[cfg(feature="replayer")] use core::clone::Clone;
#[cfg(feature="replayer")] use core::cell::RefCell;

#[cfg(not(feature="replayer"))] use core::intrinsics::{volatile_load, volatile_store};
#[cfg(feature="replayer")] use core::intrinsics::transmute;

// TODO(farcaller): why this needs copy/clone?
/// This structure is used to represent a hardware register.
/// It is mostly used by the ioreg family of macros.
#[derive(Copy, Clone)]
pub struct VolatileCell<T> {
  value: T,
}

impl<T> VolatileCell<T> {
  /// Create a cell with initial value.
  pub fn new(value: T) -> VolatileCell<T> {
    VolatileCell {
      value: value,
    }
  }

  /// Get register value.
  #[cfg(not(feature="replayer"))]
  #[inline]
  pub fn get(&self) -> T {
    unsafe {
      volatile_load(&self.value)
    }
  }

  /// Set register value.
  #[cfg(not(feature="replayer"))]
  #[inline]
  pub fn set(&self, value: T) {
    unsafe {
      volatile_store(&self.value as *const T as *mut T, value)
    }
  }
}

#[cfg(feature="replayer")]
impl VolatileCell<u32> {
  pub fn get(&self) -> u32 {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().get_cell(transmute(&self.value)) })
    }
  }

  pub fn set(&self, value: u32) {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().set_cell(transmute(&self.value), value) })
    }
  }
}

#[cfg(feature="replayer")]
impl VolatileCell<u16> {
  pub fn get(&self) -> u16 {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().get_cell(transmute(&self.value)) }) as u16
    }
  }

  pub fn set(&self, value: u16) {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().set_cell(transmute(&self.value), value as u32) })
    }
  }
}

#[cfg(feature="replayer")]
impl VolatileCell<u8> {
  pub fn get(&self) -> u8 {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().get_cell(transmute(&self.value)) }) as u8
    }
  }

  pub fn set(&self, value: u8) {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().set_cell(transmute(&self.value), value as u32) })
    }
  }
}

#[cfg(feature="replayer")]
struct ReplayRecord {
  is_read: bool,
  address: usize,
  value: u32,

  replayed: bool,
  did_read: bool,
  actual_address: usize,
  actual_value: u32,

  loc: expectest::core::SourceLocation,
}

#[cfg(feature="replayer")]
impl core::fmt::Display for ReplayRecord {
  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
    match self.is_read {
      true  => write!(f, "read 0x{:x} from 0x{:x}", self.value, self.address),
      false => write!(f, "write 0x{:x} to 0x{:x}", self.value, self.address),
    }
  }
}

#[cfg(feature="replayer")]
pub struct VolatileCellReplayer {
  replays: Vec<ReplayRecord>,
  current_replay: usize,
}

#[cfg(feature="replayer")]
impl VolatileCellReplayer {
  pub fn new() -> VolatileCellReplayer {
    VolatileCellReplayer {
      replays: Vec::new(),
      current_replay: 0,
    }
  }

  pub fn expect_read(&mut self, address: usize, value: u32,
      loc: expectest::core::SourceLocation) {
    self.replays.push(ReplayRecord {
      is_read: true,
      address: address,
      value: value,
      replayed: false,
      did_read: false,
      actual_address: 0,
      actual_value: 0,
      loc: loc,
    });
  }

  pub fn expect_write(&mut self, address: usize, value: u32,
      loc: expectest::core::SourceLocation) {
    self.replays.push(ReplayRecord {
      is_read: false,
      address: address,
      value: value,
      replayed: false,
      did_read: false,
      actual_address: 0,
      actual_value: 0,
      loc: loc,
    });
  }

  pub fn verify(&self, loc: expectest::core::SourceLocation) {
    expect(self.current_replay).location(loc).to(
      be_equal_to_with_context(
          self.replays.len(),
          format!("expected {} replays, performed {}",
              self.replays.len(), self.current_replay)));

    for ref replay in &*self.replays {
      expect(replay.replayed).location(replay.loc).to(be_equal_to_with_context(true,
        format!("expected replay {} to be performed, was not", replay)));
      expect(replay.is_read).location(replay.loc).to(be_equal_to_with_context(replay.did_read,
        format!("expected replay to be {} replay, was {} replay",
          if replay.is_read {"read"} else {"write"},
          if replay.is_read {"write"} else {"read"})));
      expect(replay.address).location(replay.loc).to(be_equal_to_with_context(replay.actual_address,
        format!("expected replay address 0x{:x}, was 0x{:x}", replay.address, replay.actual_address)));
      if !replay.is_read {
        expect(replay.value).location(replay.loc).to(be_equal_to_with_context(replay.actual_value,
          format!("expected replay to write 0x{:x}, written 0x{:x}", replay.value, replay.actual_value)));
      }
    }
  }

  pub fn get_cell(&mut self, address: usize) -> u32 {
    if self.current_replay >= self.replays.len() {
      panic!("get_cell(0x{:x}) faled, current replay: {}, total replays: {}",
        address, self.current_replay+1, self.replays.len());
    }
    let replay: &mut ReplayRecord = &mut self.replays[self.current_replay];
    replay.replayed = true;
    replay.did_read = true;
    replay.actual_address = address;

    self.current_replay += 1;

    replay.value
  }

  pub fn set_cell(&mut self, address: usize, value: u32) {
    if self.current_replay >= self.replays.len() {
      panic!("set_cell(0x{:x}, 0x{:x}) faled, current replay: {}, total replays: {}",
        address, value, self.current_replay+1, self.replays.len());
    }
    let replay: &mut ReplayRecord = &mut self.replays[self.current_replay];
    replay.replayed = true;
    replay.did_read = false;
    replay.actual_address = address;
    replay.actual_value = value;

    self.current_replay += 1;
  }
}

#[cfg(feature="replayer")]
thread_local!(static GLOBAL_REPLAYER: RefCell<VolatileCellReplayer> = RefCell::new(VolatileCellReplayer::new()));

#[cfg(feature="replayer")]
pub fn set_replayer(replayer: VolatileCellReplayer) {
  GLOBAL_REPLAYER.with(|gr| {
    let mut bm = gr.borrow_mut();
    *bm = replayer;
  });
}

#[cfg(feature="replayer")]
pub fn with_mut_replayer<F>(f: F) where F: core::ops::FnOnce(&mut VolatileCellReplayer) {
  GLOBAL_REPLAYER.with(|gr| {
    let mut bm = gr.borrow_mut();
    f(&mut *bm);
  });
}

struct BeEqualToWithContext<E> {
    expected: E,
    context: String,
}

fn be_equal_to_with_context<E>(expected: E, context: String) -> BeEqualToWithContext<E> {
    BeEqualToWithContext {
        expected: expected,
        context: context,
    }
}

impl<A, E> Matcher<A, E> for BeEqualToWithContext<E>
    where
        A: PartialEq<E> + fmt::Debug,
        E: fmt::Debug {

    fn failure_message(&self, _: expectest::core::Join, _: &A) -> String {
        self.context.clone()
    }

    fn matches(&self, actual: &A) -> bool {
        *actual == self.expected
    }
}

#[macro_export]
macro_rules! expect_volatile_read {
  ($addr: expr, $val: expr) => (
    $crate::with_mut_replayer(|r| {
      r.expect_read($addr, $val, expectest::core::SourceLocation::new(file!(), line!()));
    })
  );
}

#[macro_export]
macro_rules! expect_volatile_write {
  ($addr: expr, $val: expr) => (
    $crate::with_mut_replayer(|r| {
      r.expect_write($addr, $val, expectest::core::SourceLocation::new(file!(), line!()));
    })
  );
}

#[macro_export]
macro_rules! expect_replayer_valid {
  () => (
    $crate::with_mut_replayer(|r| {
      r.verify(expectest::core::SourceLocation::new(file!(), line!()));
    })
  );
}

#[macro_export]
macro_rules! init_replayer {
  () => (
    set_replayer(VolatileCellReplayer::new());
  );
}
<commit_msg>Test code in volatile_cell is feature=replayer now<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! A cell that with volatile setter and getter.

#![feature(core, no_std, core_intrinsics)]
#![no_std]

extern crate core;

#[cfg(feature="replayer")] #[macro_use(expect)] extern crate expectest;
#[cfg(feature="replayer")] #[macro_use] extern crate std;

#[cfg(feature="replayer")] use std::vec::Vec;
#[cfg(feature="replayer")] use expectest::prelude::*;
#[cfg(feature="replayer")] use std::string::String;
#[cfg(feature="replayer")] use std::fmt;
#[cfg(feature="replayer")] use core::cmp::PartialEq;
#[cfg(feature="replayer")] use core::clone::Clone;
#[cfg(feature="replayer")] use core::cell::RefCell;

#[cfg(not(feature="replayer"))] use core::intrinsics::{volatile_load, volatile_store};
#[cfg(feature="replayer")] use core::intrinsics::transmute;

// TODO(farcaller): why this needs copy/clone?
/// This structure is used to represent a hardware register.
/// It is mostly used by the ioreg family of macros.
#[derive(Copy, Clone)]
pub struct VolatileCell<T> {
  value: T,
}

impl<T> VolatileCell<T> {
  /// Create a cell with initial value.
  pub fn new(value: T) -> VolatileCell<T> {
    VolatileCell {
      value: value,
    }
  }

  /// Get register value.
  #[cfg(not(feature="replayer"))]
  #[inline]
  pub fn get(&self) -> T {
    unsafe {
      volatile_load(&self.value)
    }
  }

  /// Set register value.
  #[cfg(not(feature="replayer"))]
  #[inline]
  pub fn set(&self, value: T) {
    unsafe {
      volatile_store(&self.value as *const T as *mut T, value)
    }
  }
}

#[cfg(feature="replayer")]
impl VolatileCell<u32> {
  pub fn get(&self) -> u32 {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().get_cell(transmute(&self.value)) })
    }
  }

  pub fn set(&self, value: u32) {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().set_cell(transmute(&self.value), value) })
    }
  }
}

#[cfg(feature="replayer")]
impl VolatileCell<u16> {
  pub fn get(&self) -> u16 {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().get_cell(transmute(&self.value)) }) as u16
    }
  }

  pub fn set(&self, value: u16) {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().set_cell(transmute(&self.value), value as u32) })
    }
  }
}

#[cfg(feature="replayer")]
impl VolatileCell<u8> {
  pub fn get(&self) -> u8 {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().get_cell(transmute(&self.value)) }) as u8
    }
  }

  pub fn set(&self, value: u8) {
    unsafe {
      GLOBAL_REPLAYER.with(|gr| { gr.borrow_mut().set_cell(transmute(&self.value), value as u32) })
    }
  }
}

#[cfg(feature="replayer")]
struct ReplayRecord {
  is_read: bool,
  address: usize,
  value: u32,

  replayed: bool,
  did_read: bool,
  actual_address: usize,
  actual_value: u32,

  loc: expectest::core::SourceLocation,
}

#[cfg(feature="replayer")]
impl core::fmt::Display for ReplayRecord {
  fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
    match self.is_read {
      true  => write!(f, "read 0x{:x} from 0x{:x}", self.value, self.address),
      false => write!(f, "write 0x{:x} to 0x{:x}", self.value, self.address),
    }
  }
}

#[cfg(feature="replayer")]
pub struct VolatileCellReplayer {
  replays: Vec<ReplayRecord>,
  current_replay: usize,
}

#[cfg(feature="replayer")]
impl VolatileCellReplayer {
  pub fn new() -> VolatileCellReplayer {
    VolatileCellReplayer {
      replays: Vec::new(),
      current_replay: 0,
    }
  }

  pub fn expect_read(&mut self, address: usize, value: u32,
      loc: expectest::core::SourceLocation) {
    self.replays.push(ReplayRecord {
      is_read: true,
      address: address,
      value: value,
      replayed: false,
      did_read: false,
      actual_address: 0,
      actual_value: 0,
      loc: loc,
    });
  }

  pub fn expect_write(&mut self, address: usize, value: u32,
      loc: expectest::core::SourceLocation) {
    self.replays.push(ReplayRecord {
      is_read: false,
      address: address,
      value: value,
      replayed: false,
      did_read: false,
      actual_address: 0,
      actual_value: 0,
      loc: loc,
    });
  }

  pub fn verify(&self, loc: expectest::core::SourceLocation) {
    expect(self.current_replay).location(loc).to(
      be_equal_to_with_context(
          self.replays.len(),
          format!("expected {} replays, performed {}",
              self.replays.len(), self.current_replay)));

    for ref replay in &*self.replays {
      expect(replay.replayed).location(replay.loc).to(be_equal_to_with_context(true,
        format!("expected replay {} to be performed, was not", replay)));
      expect(replay.is_read).location(replay.loc).to(be_equal_to_with_context(replay.did_read,
        format!("expected replay to be {} replay, was {} replay",
          if replay.is_read {"read"} else {"write"},
          if replay.is_read {"write"} else {"read"})));
      expect(replay.address).location(replay.loc).to(be_equal_to_with_context(replay.actual_address,
        format!("expected replay address 0x{:x}, was 0x{:x}", replay.address, replay.actual_address)));
      if !replay.is_read {
        expect(replay.value).location(replay.loc).to(be_equal_to_with_context(replay.actual_value,
          format!("expected replay to write 0x{:x}, written 0x{:x}", replay.value, replay.actual_value)));
      }
    }
  }

  pub fn get_cell(&mut self, address: usize) -> u32 {
    if self.current_replay >= self.replays.len() {
      panic!("get_cell(0x{:x}) faled, current replay: {}, total replays: {}",
        address, self.current_replay+1, self.replays.len());
    }
    let replay: &mut ReplayRecord = &mut self.replays[self.current_replay];
    replay.replayed = true;
    replay.did_read = true;
    replay.actual_address = address;

    self.current_replay += 1;

    replay.value
  }

  pub fn set_cell(&mut self, address: usize, value: u32) {
    if self.current_replay >= self.replays.len() {
      panic!("set_cell(0x{:x}, 0x{:x}) faled, current replay: {}, total replays: {}",
        address, value, self.current_replay+1, self.replays.len());
    }
    let replay: &mut ReplayRecord = &mut self.replays[self.current_replay];
    replay.replayed = true;
    replay.did_read = false;
    replay.actual_address = address;
    replay.actual_value = value;

    self.current_replay += 1;
  }
}

#[cfg(feature="replayer")]
thread_local!(static GLOBAL_REPLAYER: RefCell<VolatileCellReplayer> = RefCell::new(VolatileCellReplayer::new()));

#[cfg(feature="replayer")]
pub fn set_replayer(replayer: VolatileCellReplayer) {
  GLOBAL_REPLAYER.with(|gr| {
    let mut bm = gr.borrow_mut();
    *bm = replayer;
  });
}

#[cfg(feature="replayer")]
pub fn with_mut_replayer<F>(f: F) where F: core::ops::FnOnce(&mut VolatileCellReplayer) {
  GLOBAL_REPLAYER.with(|gr| {
    let mut bm = gr.borrow_mut();
    f(&mut *bm);
  });
}

#[cfg(feature="replayer")]
struct BeEqualToWithContext<E> {
    expected: E,
    context: String,
}

#[cfg(feature="replayer")]
fn be_equal_to_with_context<E>(expected: E, context: String) -> BeEqualToWithContext<E> {
    BeEqualToWithContext {
        expected: expected,
        context: context,
    }
}

#[cfg(feature="replayer")]
impl<A, E> Matcher<A, E> for BeEqualToWithContext<E>
    where
        A: PartialEq<E> + fmt::Debug,
        E: fmt::Debug {

    fn failure_message(&self, _: expectest::core::Join, _: &A) -> String {
        self.context.clone()
    }

    fn matches(&self, actual: &A) -> bool {
        *actual == self.expected
    }
}

#[macro_export]
macro_rules! expect_volatile_read {
  ($addr: expr, $val: expr) => (
    $crate::with_mut_replayer(|r| {
      r.expect_read($addr, $val, expectest::core::SourceLocation::new(file!(), line!()));
    })
  );
}

#[macro_export]
macro_rules! expect_volatile_write {
  ($addr: expr, $val: expr) => (
    $crate::with_mut_replayer(|r| {
      r.expect_write($addr, $val, expectest::core::SourceLocation::new(file!(), line!()));
    })
  );
}

#[macro_export]
macro_rules! expect_replayer_valid {
  () => (
    $crate::with_mut_replayer(|r| {
      r.verify(expectest::core::SourceLocation::new(file!(), line!()));
    })
  );
}

#[macro_export]
macro_rules! init_replayer {
  () => (
    set_replayer(VolatileCellReplayer::new());
  );
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::path::PathBuf;
use std::result::Result as RResult;
use std::ops::Deref;

use toml::{Parser, Value};

generate_error_module!(
    generate_error_types!(ConfigError, ConfigErrorKind,
        NoConfigFileFound   => "No config file found",

        ConfigOverrideError => "Config override error",
        ConfigOverrideKeyNotAvailable => "Key not available",
        ConfigOverrideTypeNotMatching => "Configuration Type not matching"

    );
);

use self::error::{ConfigError, ConfigErrorKind};

/**
 * Result type of this module. Either `T` or `ConfigError`
 */
pub type Result<T> = RResult<T, ConfigError>;

/// `Configuration` object
///
/// Holds all config variables which are globally available plus the configuration object from the
/// config parser, which can be accessed.
#[derive(Debug)]
pub struct Configuration {

    /// The plain configuration object for direct access if necessary
    config: Value,

    /// The verbosity the program should run with
    verbosity: bool,

    /// The editor which should be used
    editor: Option<String>,

    ///The options the editor should get when opening some file
    editor_opts: String,
}

impl Configuration {

    /// Get a new configuration object.
    ///
    /// The passed runtimepath is used for searching the configuration file, whereas several file
    /// names are tested. If that does not work, the home directory and the XDG basedir are tested
    /// with all variants.
    ///
    /// If that doesn't work either, an error is returned.
    pub fn new(rtp: &PathBuf) -> Result<Configuration> {
        fetch_config(&rtp).map(|cfg| {
            let verbosity   = get_verbosity(&cfg);
            let editor      = get_editor(&cfg);
            let editor_opts = get_editor_opts(&cfg);

            debug!("Building configuration");
            debug!("  - verbosity  : {:?}", verbosity);
            debug!("  - editor     : {:?}", editor);
            debug!("  - editor-opts: {}", editor_opts);

            Configuration {
                config: cfg,
                verbosity: verbosity,
                editor: editor,
                editor_opts: editor_opts,
            }
        })
    }

    pub fn editor(&self) -> Option<&String> {
        self.editor.as_ref()
    }

    #[allow(dead_code)] // Why do I actually need this annotation on a pub function?
    pub fn config(&self) -> &Value {
        &self.config
    }

    pub fn store_config(&self) -> Option<&Value> {
        match self.config {
            Value::Table(ref tabl) => tabl.get("store"),
            _ => None,
        }
    }

    /// Override the configuration.
    /// The `v` parameter is expected to contain 'key=value' pairs where the key is a path in the
    /// TOML tree, the value to be an appropriate value.
    ///
    /// The override fails if the configuration which is about to be overridden does not exist or
    /// the `value` part cannot be converted to the type of the configuration value.
    ///
    /// If `v` is empty, this is considered to be a successful `override_config()` call.
    pub fn override_config(&mut self, v: Vec<String>) -> Result<()> {
        use libimagutil::key_value_split::*;
        use libimagutil::iter::*;
        use self::error::ConfigErrorKind as CEK;
        use libimagerror::into::IntoError;

        v.into_iter()
            .map(|s| { debug!("Trying to process '{}'", s); s })
            .filter_map(|s| {
                match s.into_kv() {
                    Some(kv) => Some(kv.into()),
                    None => {
                        warn!("Could split at '=' - will be ignore override");
                        None
                    }
                }
            })
            .map(|(k, v)| {
                match self.config.lookup_mut(&k[..]) {
                    Some(value) => {
                        match into_value(value, v) {
                            Some(v) => {
                                *value = v;
                                info!("Successfully overridden: {} = {}", k, value);
                                Ok(())
                            },
                            None => Err(CEK::ConfigOverrideTypeNotMatching.into_error()),
                        }
                    },
                    None => Err(CEK::ConfigOverrideKeyNotAvailable.into_error()),
                }
            })
            .fold_defresult(|i| i)
            .map_err(Box::new)
            .map_err(|e| CEK::ConfigOverrideError.into_error_with_cause(e))
    }
}

/// Tries to convert the String `s` into the same type as `value`.
///
/// Returns None if string cannot be converted.
///
/// Arrays and Tables are not supported and will yield `None`.
fn into_value(value: &Value, s: String) -> Option<Value> {
    use std::str::FromStr;

    match value {
        &Value::String(_) => Some(Value::String(s)),
        &Value::Integer(_) => FromStr::from_str(&s[..]).ok().map(|i| Value::Integer(i)),
        &Value::Float(_) => FromStr::from_str(&s[..]).ok().map(|f| Value::Float(f)),
        &Value::Boolean(_) => {
            if s == "true" { Some(Value::Boolean(true)) }
            else if s == "false" { Some(Value::Boolean(false)) }
            else { None }
        }
        &Value::Datetime(_) => Some(Value::Datetime(s)),
        _ => None,
    }
}

impl Deref for Configuration {
    type Target = Value;

    fn deref(&self) -> &Value {
        &self.config
    }

}

fn get_verbosity(v: &Value) -> bool {
    match *v {
        Value::Table(ref t) => t.get("verbose")
                .map_or(false, |v| match *v { Value::Boolean(b) => b, _ => false, }),
        _ => false,
    }
}

fn get_editor(v: &Value) -> Option<String> {
    match *v {
        Value::Table(ref t) => t.get("editor")
                .and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, }),
        _ => None,
    }
}

fn get_editor_opts(v: &Value) -> String {
    match *v {
        Value::Table(ref t) => t.get("editor-opts")
                .and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, })
                .unwrap_or_default(),
        _ => String::new(),
    }
}

/**
 * Helper to fetch the config file
 *
 * Tests several variants for the config file path and uses the first one which works.
 */
fn fetch_config(rtp: &PathBuf) -> Result<Value> {
    use std::env;
    use std::fs::File;
    use std::io::Read;
    use std::io::Write;
    use std::io::stderr;

    use xdg_basedir;
    use itertools::Itertools;

    use libimagutil::variants::generate_variants as gen_vars;

    let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
    let modifier = |base: &PathBuf, v: &'static str| {
        let mut base = base.clone();
        base.push(String::from(v));
        base
    };

    vec![
        vec![rtp.clone()],
        gen_vars(rtp.clone(), variants.clone(), &modifier),

        env::var("HOME").map(|home| gen_vars(PathBuf::from(home), variants.clone(), &modifier))
                        .unwrap_or(vec![]),

        xdg_basedir::get_data_home().map(|data_dir| gen_vars(data_dir, variants.clone(), &modifier))
                                    .unwrap_or(vec![]),
    ].iter()
        .flatten()
        .filter(|path| path.exists() && path.is_file())
        .map(|path| {
            let content = {
                let mut s = String::new();
                let f = File::open(path);
                if f.is_err() {
                    return None
                }
                let mut f = f.unwrap();
                f.read_to_string(&mut s).ok();
                s
            };

            let mut parser = Parser::new(&content[..]);
            let res = parser.parse();

            if res.is_none() {
                write!(stderr(), "Config file parser error:").ok();
                for error in parser.errors {
                    write!(stderr(), "At [{}][{}] <> {}", error.lo, error.hi, error).ok();
                    write!(stderr(), "in: '{}'", &content[error.lo..error.hi]).ok();
                }
                None
            } else {
                res
            }
        })
        .filter(|loaded| loaded.is_some())
        .nth(0)
        .map(|inner| Value::Table(inner.unwrap()))
        .ok_or(ConfigErrorKind::NoConfigFileFound.into())
}

<commit_msg>Make error types public<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::path::PathBuf;
use std::result::Result as RResult;
use std::ops::Deref;

use toml::{Parser, Value};

generate_error_module!(
    generate_error_types!(ConfigError, ConfigErrorKind,
        NoConfigFileFound   => "No config file found",

        ConfigOverrideError => "Config override error",
        ConfigOverrideKeyNotAvailable => "Key not available",
        ConfigOverrideTypeNotMatching => "Configuration Type not matching"

    );
);

pub use self::error::{ConfigError, ConfigErrorKind};

/**
 * Result type of this module. Either `T` or `ConfigError`
 */
pub type Result<T> = RResult<T, ConfigError>;

/// `Configuration` object
///
/// Holds all config variables which are globally available plus the configuration object from the
/// config parser, which can be accessed.
#[derive(Debug)]
pub struct Configuration {

    /// The plain configuration object for direct access if necessary
    config: Value,

    /// The verbosity the program should run with
    verbosity: bool,

    /// The editor which should be used
    editor: Option<String>,

    ///The options the editor should get when opening some file
    editor_opts: String,
}

impl Configuration {

    /// Get a new configuration object.
    ///
    /// The passed runtimepath is used for searching the configuration file, whereas several file
    /// names are tested. If that does not work, the home directory and the XDG basedir are tested
    /// with all variants.
    ///
    /// If that doesn't work either, an error is returned.
    pub fn new(rtp: &PathBuf) -> Result<Configuration> {
        fetch_config(&rtp).map(|cfg| {
            let verbosity   = get_verbosity(&cfg);
            let editor      = get_editor(&cfg);
            let editor_opts = get_editor_opts(&cfg);

            debug!("Building configuration");
            debug!("  - verbosity  : {:?}", verbosity);
            debug!("  - editor     : {:?}", editor);
            debug!("  - editor-opts: {}", editor_opts);

            Configuration {
                config: cfg,
                verbosity: verbosity,
                editor: editor,
                editor_opts: editor_opts,
            }
        })
    }

    pub fn editor(&self) -> Option<&String> {
        self.editor.as_ref()
    }

    #[allow(dead_code)] // Why do I actually need this annotation on a pub function?
    pub fn config(&self) -> &Value {
        &self.config
    }

    pub fn store_config(&self) -> Option<&Value> {
        match self.config {
            Value::Table(ref tabl) => tabl.get("store"),
            _ => None,
        }
    }

    /// Override the configuration.
    /// The `v` parameter is expected to contain 'key=value' pairs where the key is a path in the
    /// TOML tree, the value to be an appropriate value.
    ///
    /// The override fails if the configuration which is about to be overridden does not exist or
    /// the `value` part cannot be converted to the type of the configuration value.
    ///
    /// If `v` is empty, this is considered to be a successful `override_config()` call.
    pub fn override_config(&mut self, v: Vec<String>) -> Result<()> {
        use libimagutil::key_value_split::*;
        use libimagutil::iter::*;
        use self::error::ConfigErrorKind as CEK;
        use libimagerror::into::IntoError;

        v.into_iter()
            .map(|s| { debug!("Trying to process '{}'", s); s })
            .filter_map(|s| {
                match s.into_kv() {
                    Some(kv) => Some(kv.into()),
                    None => {
                        warn!("Could split at '=' - will be ignore override");
                        None
                    }
                }
            })
            .map(|(k, v)| {
                match self.config.lookup_mut(&k[..]) {
                    Some(value) => {
                        match into_value(value, v) {
                            Some(v) => {
                                *value = v;
                                info!("Successfully overridden: {} = {}", k, value);
                                Ok(())
                            },
                            None => Err(CEK::ConfigOverrideTypeNotMatching.into_error()),
                        }
                    },
                    None => Err(CEK::ConfigOverrideKeyNotAvailable.into_error()),
                }
            })
            .fold_defresult(|i| i)
            .map_err(Box::new)
            .map_err(|e| CEK::ConfigOverrideError.into_error_with_cause(e))
    }
}

/// Tries to convert the String `s` into the same type as `value`.
///
/// Returns None if string cannot be converted.
///
/// Arrays and Tables are not supported and will yield `None`.
fn into_value(value: &Value, s: String) -> Option<Value> {
    use std::str::FromStr;

    match value {
        &Value::String(_) => Some(Value::String(s)),
        &Value::Integer(_) => FromStr::from_str(&s[..]).ok().map(|i| Value::Integer(i)),
        &Value::Float(_) => FromStr::from_str(&s[..]).ok().map(|f| Value::Float(f)),
        &Value::Boolean(_) => {
            if s == "true" { Some(Value::Boolean(true)) }
            else if s == "false" { Some(Value::Boolean(false)) }
            else { None }
        }
        &Value::Datetime(_) => Some(Value::Datetime(s)),
        _ => None,
    }
}

impl Deref for Configuration {
    type Target = Value;

    fn deref(&self) -> &Value {
        &self.config
    }

}

fn get_verbosity(v: &Value) -> bool {
    match *v {
        Value::Table(ref t) => t.get("verbose")
                .map_or(false, |v| match *v { Value::Boolean(b) => b, _ => false, }),
        _ => false,
    }
}

fn get_editor(v: &Value) -> Option<String> {
    match *v {
        Value::Table(ref t) => t.get("editor")
                .and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, }),
        _ => None,
    }
}

fn get_editor_opts(v: &Value) -> String {
    match *v {
        Value::Table(ref t) => t.get("editor-opts")
                .and_then(|v| match *v { Value::String(ref s) => Some(s.clone()), _ => None, })
                .unwrap_or_default(),
        _ => String::new(),
    }
}

/**
 * Helper to fetch the config file
 *
 * Tests several variants for the config file path and uses the first one which works.
 */
fn fetch_config(rtp: &PathBuf) -> Result<Value> {
    use std::env;
    use std::fs::File;
    use std::io::Read;
    use std::io::Write;
    use std::io::stderr;

    use xdg_basedir;
    use itertools::Itertools;

    use libimagutil::variants::generate_variants as gen_vars;

    let variants = vec!["config", "config.toml", "imagrc", "imagrc.toml"];
    let modifier = |base: &PathBuf, v: &'static str| {
        let mut base = base.clone();
        base.push(String::from(v));
        base
    };

    vec![
        vec![rtp.clone()],
        gen_vars(rtp.clone(), variants.clone(), &modifier),

        env::var("HOME").map(|home| gen_vars(PathBuf::from(home), variants.clone(), &modifier))
                        .unwrap_or(vec![]),

        xdg_basedir::get_data_home().map(|data_dir| gen_vars(data_dir, variants.clone(), &modifier))
                                    .unwrap_or(vec![]),
    ].iter()
        .flatten()
        .filter(|path| path.exists() && path.is_file())
        .map(|path| {
            let content = {
                let mut s = String::new();
                let f = File::open(path);
                if f.is_err() {
                    return None
                }
                let mut f = f.unwrap();
                f.read_to_string(&mut s).ok();
                s
            };

            let mut parser = Parser::new(&content[..]);
            let res = parser.parse();

            if res.is_none() {
                write!(stderr(), "Config file parser error:").ok();
                for error in parser.errors {
                    write!(stderr(), "At [{}][{}] <> {}", error.lo, error.hi, error).ok();
                    write!(stderr(), "in: '{}'", &content[error.lo..error.hi]).ok();
                }
                None
            } else {
                res
            }
        })
        .filter(|loaded| loaded.is_some())
        .nth(0)
        .map(|inner| Value::Table(inner.unwrap()))
        .ok_or(ConfigErrorKind::NoConfigFileFound.into())
}

<|endoftext|>


<commit_before>//! Defines the `IntoIter` owned iterator for arrays.

use crate::{
    fmt,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
    mem::{self, MaybeUninit},
    ops::Range,
    ptr,
};

/// A by-value [array] iterator.
///
/// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "65798")]
pub struct IntoIter<T, const N: usize> {
    /// This is the array we are iterating over.
    ///
    /// Elements with index `i` where `alive.start <= i < alive.end` have not
    /// been yielded yet and are valid array entries. Elements with indices `i
    /// < alive.start` or `i >= alive.end` have been yielded already and must
    /// not be accessed anymore! Those dead elements might even be in a
    /// completely uninitialized state!
    ///
    /// So the invariants are:
    /// - `data[alive]` is alive (i.e. contains valid elements)
    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
    ///   elements were already read and must not be touched anymore!)
    data: [MaybeUninit<T>; N],

    /// The elements in `data` that have not been yielded yet.
    ///
    /// Invariants:
    /// - `alive.start <= alive.end`
    /// - `alive.end <= N`
    alive: Range<usize>,
}

impl<T, const N: usize> IntoIter<T, N> {
    /// Creates a new iterator over the given `array`.
    ///
    /// *Note*: this method might never get stabilized and/or removed in the
    /// future as there will likely be another, preferred way of obtaining this
    /// iterator (either via `IntoIterator` for arrays or via another way).
    #[unstable(feature = "array_value_iter", issue = "65798")]
    pub fn new(array: [T; N]) -> Self {
        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
        // promise:
        //
        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
        // > as `T`.
        //
        // The docs even show a transmute from an array of `MaybeUninit<T>` to
        // an array of `T`.
        //
        // With that, this initialization satisfies the invariants.

        // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
        // works with const generics:
        //     `mem::transmute::<[T; N], [MaybeUninit<T>; N]>(array)`
        //
        // Until then, we can use `mem::transmute_copy` to create a bitwise copy
        // as a different type, then forget `array` so that it is not dropped.
        unsafe {
            let iter = Self { data: mem::transmute_copy(&array), alive: 0..N };
            mem::forget(array);
            iter
        }
    }

    /// Returns an immutable slice of all elements that have not been yielded
    /// yet.
    fn as_slice(&self) -> &[T] {
        // SAFETY: We know that all elements within `alive` are properly initialized.
        unsafe {
            let slice = self.data.get_unchecked(self.alive.clone());
            MaybeUninit::slice_assume_init_ref(slice)
        }
    }

    /// Returns a mutable slice of all elements that have not been yielded yet.
    fn as_mut_slice(&mut self) -> &mut [T] {
        // SAFETY: We know that all elements within `alive` are properly initialized.
        unsafe {
            let slice = self.data.get_unchecked_mut(self.alive.clone());
            MaybeUninit::slice_assume_init_mut(slice)
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, N> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        // Get the next index from the front.
        //
        // Increasing `alive.start` by 1 maintains the invariant regarding
        // `alive`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[idx..alive.end]`.
        self.alive.next().map(|idx| {
            // Read the element from the array.
            // SAFETY: `idx` is an index into the former "alive" region of the
            // array. Reading this element means that `data[idx]` is regarded as
            // dead now (i.e. do not touch). As `idx` was the start of the
            // alive-zone, the alive zone is now `data[alive]` again, restoring
            // all invariants.
            unsafe { self.data.get_unchecked(idx).assume_init_read() }
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }

    fn count(self) -> usize {
        self.len()
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
    fn next_back(&mut self) -> Option<Self::Item> {
        // Get the next index from the back.
        //
        // Decreasing `alive.end` by 1 maintains the invariant regarding
        // `alive`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`.
        self.alive.next_back().map(|idx| {
            // Read the element from the array.
            // SAFETY: `idx` is an index into the former "alive" region of the
            // array. Reading this element means that `data[idx]` is regarded as
            // dead now (i.e. do not touch). As `idx` was the end of the
            // alive-zone, the alive zone is now `data[alive]` again, restoring
            // all invariants.
            unsafe { self.data.get_unchecked(idx).assume_init_read() }
        })
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, N> {
    fn drop(&mut self) {
        // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
        // of elements that have not been moved out yet and that remain
        // to be dropped.
        unsafe { ptr::drop_in_place(self.as_mut_slice()) }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
    fn len(&self) -> usize {
        // Will never underflow due to the invariant `alive.start <=
        // alive.end`.
        self.alive.end - self.alive.start
    }
    fn is_empty(&self) -> bool {
        self.alive.is_empty()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}

// The iterator indeed reports the correct length. The number of "alive"
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
    fn clone(&self) -> Self {
        // Note, we don't really need to match the exact same alive range, so
        // we can just clone into offset 0 regardless of where `self` is.
        let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 };

        // Clone all alive elements.
        for (src, dst) in self.as_slice().iter().zip(&mut new.data) {
            // Write a clone into the new array, then update its alive range.
            // If cloning panics, we'll correctly drop the previous items.
            dst.write(src.clone());
            new.alive.end += 1;
        }

        new
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Only print the elements that were not yielded yet: we cannot
        // access the yielded elements anymore.
        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
    }
}
<commit_msg>Make as{_mut,}_slice on array::IntoIter public<commit_after>//! Defines the `IntoIter` owned iterator for arrays.

use crate::{
    fmt,
    iter::{ExactSizeIterator, FusedIterator, TrustedLen},
    mem::{self, MaybeUninit},
    ops::Range,
    ptr,
};

/// A by-value [array] iterator.
///
/// [array]: ../../std/primitive.array.html
#[unstable(feature = "array_value_iter", issue = "65798")]
pub struct IntoIter<T, const N: usize> {
    /// This is the array we are iterating over.
    ///
    /// Elements with index `i` where `alive.start <= i < alive.end` have not
    /// been yielded yet and are valid array entries. Elements with indices `i
    /// < alive.start` or `i >= alive.end` have been yielded already and must
    /// not be accessed anymore! Those dead elements might even be in a
    /// completely uninitialized state!
    ///
    /// So the invariants are:
    /// - `data[alive]` is alive (i.e. contains valid elements)
    /// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
    ///   elements were already read and must not be touched anymore!)
    data: [MaybeUninit<T>; N],

    /// The elements in `data` that have not been yielded yet.
    ///
    /// Invariants:
    /// - `alive.start <= alive.end`
    /// - `alive.end <= N`
    alive: Range<usize>,
}

impl<T, const N: usize> IntoIter<T, N> {
    /// Creates a new iterator over the given `array`.
    ///
    /// *Note*: this method might never get stabilized and/or removed in the
    /// future as there will likely be another, preferred way of obtaining this
    /// iterator (either via `IntoIterator` for arrays or via another way).
    #[unstable(feature = "array_value_iter", issue = "65798")]
    pub fn new(array: [T; N]) -> Self {
        // SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
        // promise:
        //
        // > `MaybeUninit<T>` is guaranteed to have the same size and alignment
        // > as `T`.
        //
        // The docs even show a transmute from an array of `MaybeUninit<T>` to
        // an array of `T`.
        //
        // With that, this initialization satisfies the invariants.

        // FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
        // works with const generics:
        //     `mem::transmute::<[T; N], [MaybeUninit<T>; N]>(array)`
        //
        // Until then, we can use `mem::transmute_copy` to create a bitwise copy
        // as a different type, then forget `array` so that it is not dropped.
        unsafe {
            let iter = Self { data: mem::transmute_copy(&array), alive: 0..N };
            mem::forget(array);
            iter
        }
    }

    /// Returns an immutable slice of all elements that have not been yielded
    /// yet.
    #[unstable(feature = "array_value_iter_slice", issue = "65798")]
    pub fn as_slice(&self) -> &[T] {
        // SAFETY: We know that all elements within `alive` are properly initialized.
        unsafe {
            let slice = self.data.get_unchecked(self.alive.clone());
            MaybeUninit::slice_assume_init_ref(slice)
        }
    }

    /// Returns a mutable slice of all elements that have not been yielded yet.
    #[unstable(feature = "array_value_iter_slice", issue = "65798")]
    pub fn as_mut_slice(&mut self) -> &mut [T] {
        // SAFETY: We know that all elements within `alive` are properly initialized.
        unsafe {
            let slice = self.data.get_unchecked_mut(self.alive.clone());
            MaybeUninit::slice_assume_init_mut(slice)
        }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Iterator for IntoIter<T, N> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        // Get the next index from the front.
        //
        // Increasing `alive.start` by 1 maintains the invariant regarding
        // `alive`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[idx..alive.end]`.
        self.alive.next().map(|idx| {
            // Read the element from the array.
            // SAFETY: `idx` is an index into the former "alive" region of the
            // array. Reading this element means that `data[idx]` is regarded as
            // dead now (i.e. do not touch). As `idx` was the start of the
            // alive-zone, the alive zone is now `data[alive]` again, restoring
            // all invariants.
            unsafe { self.data.get_unchecked(idx).assume_init_read() }
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.len();
        (len, Some(len))
    }

    fn count(self) -> usize {
        self.len()
    }

    fn last(mut self) -> Option<Self::Item> {
        self.next_back()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
    fn next_back(&mut self) -> Option<Self::Item> {
        // Get the next index from the back.
        //
        // Decreasing `alive.end` by 1 maintains the invariant regarding
        // `alive`. However, due to this change, for a short time, the alive
        // zone is not `data[alive]` anymore, but `data[alive.start..=idx]`.
        self.alive.next_back().map(|idx| {
            // Read the element from the array.
            // SAFETY: `idx` is an index into the former "alive" region of the
            // array. Reading this element means that `data[idx]` is regarded as
            // dead now (i.e. do not touch). As `idx` was the end of the
            // alive-zone, the alive zone is now `data[alive]` again, restoring
            // all invariants.
            unsafe { self.data.get_unchecked(idx).assume_init_read() }
        })
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> Drop for IntoIter<T, N> {
    fn drop(&mut self) {
        // SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
        // of elements that have not been moved out yet and that remain
        // to be dropped.
        unsafe { ptr::drop_in_place(self.as_mut_slice()) }
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
    fn len(&self) -> usize {
        // Will never underflow due to the invariant `alive.start <=
        // alive.end`.
        self.alive.end - self.alive.start
    }
    fn is_empty(&self) -> bool {
        self.alive.is_empty()
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}

// The iterator indeed reports the correct length. The number of "alive"
// elements (that will still be yielded) is the length of the range `alive`.
// This range is decremented in length in either `next` or `next_back`. It is
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
    fn clone(&self) -> Self {
        // Note, we don't really need to match the exact same alive range, so
        // we can just clone into offset 0 regardless of where `self` is.
        let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 };

        // Clone all alive elements.
        for (src, dst) in self.as_slice().iter().zip(&mut new.data) {
            // Write a clone into the new array, then update its alive range.
            // If cloning panics, we'll correctly drop the previous items.
            dst.write(src.clone());
            new.alive.end += 1;
        }

        new
    }
}

#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        // Only print the elements that were not yielded yet: we cannot
        // access the yielded elements anymore.
        f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
    }
}
<|endoftext|>


<commit_before>//! Implementation of Rust panics via process aborts
//!
//! When compared to the implementation via unwinding, this crate is *much*
//! simpler! That being said, it's not quite as versatile, but here goes!

#![no_std]
#![unstable(feature = "panic_abort", issue = "32837")]
#![doc(
    html_root_url = "https://doc.rust-lang.org/nightly/",
    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/"
)]
#![panic_runtime]
#![allow(unused_features)]
#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(nll)]
#![feature(panic_runtime)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![feature(asm)]

use core::any::Any;

#[rustc_std_internal_symbol]
#[allow(improper_ctypes_definitions)]
pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) {
    unreachable!()
}

// "Leak" the payload and shim to the relevant abort on the platform in question.
#[rustc_std_internal_symbol]
pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 {
    abort();

    cfg_if::cfg_if! {
        if #[cfg(any(unix, target_os = "cloudabi"))] {
            unsafe fn abort() -> ! {
                libc::abort();
            }
        } else if #[cfg(any(target_os = "hermit",
                            all(target_vendor = "fortanix", target_env = "sgx")
        ))] {
            unsafe fn abort() -> ! {
                // call std::sys::abort_internal
                extern "C" {
                    pub fn __rust_abort() -> !;
                }
                __rust_abort();
            }
        } else if #[cfg(windows)] {
            // On Windows, use the processor-specific __fastfail mechanism. In Windows 8
            // and later, this will terminate the process immediately without running any
            // in-process exception handlers. In earlier versions of Windows, this
            // sequence of instructions will be treated as an access violation,
            // terminating the process but without necessarily bypassing all exception
            // handlers.
            //
            // https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
            //
            // Note: this is the same implementation as in libstd's `abort_internal`
            unsafe fn abort() -> ! {
                const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
                cfg_if::cfg_if! {
                    if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
                        asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
                    } else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
                        asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
                    } else if #[cfg(target_arch = "aarch64")] {
                        asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
                    } else {
                        core::intrinsics::abort();
                    }
                }
                core::intrinsics::unreachable();
            }
        } else {
            unsafe fn abort() -> ! {
                core::intrinsics::abort();
            }
        }
    }
}

// This... is a bit of an oddity. The tl;dr; is that this is required to link
// correctly, the longer explanation is below.
//
// Right now the binaries of libcore/libstd that we ship are all compiled with
// `-C panic=unwind`. This is done to ensure that the binaries are maximally
// compatible with as many situations as possible. The compiler, however,
// requires a "personality function" for all functions compiled with `-C
// panic=unwind`. This personality function is hardcoded to the symbol
// `rust_eh_personality` and is defined by the `eh_personality` lang item.
//
// So... why not just define that lang item here? Good question! The way that
// panic runtimes are linked in is actually a little subtle in that they're
// "sort of" in the compiler's crate store, but only actually linked if another
// isn't actually linked. This ends up meaning that both this crate and the
// panic_unwind crate can appear in the compiler's crate store, and if both
// define the `eh_personality` lang item then that'll hit an error.
//
// To handle this the compiler only requires the `eh_personality` is defined if
// the panic runtime being linked in is the unwinding runtime, and otherwise
// it's not required to be defined (rightfully so). In this case, however, this
// library just defines this symbol so there's at least some personality
// somewhere.
//
// Essentially this symbol is just defined to get wired up to libcore/libstd
// binaries, but it should never be called as we don't link in an unwinding
// runtime at all.
pub mod personalities {
    #[rustc_std_internal_symbol]
    #[cfg(not(any(
        all(target_arch = "wasm32", not(target_os = "emscripten"),),
        all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",),
    )))]
    pub extern "C" fn rust_eh_personality() {}

    // On x86_64-pc-windows-gnu we use our own personality function that needs
    // to return `ExceptionContinueSearch` as we're passing on all our frames.
    #[rustc_std_internal_symbol]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86_64"))]
    pub extern "C" fn rust_eh_personality(
        _record: usize,
        _frame: usize,
        _context: usize,
        _dispatcher: usize,
    ) -> u32 {
        1 // `ExceptionContinueSearch`
    }

    // Similar to above, this corresponds to the `eh_catch_typeinfo` lang item
    // that's only used on Emscripten currently.
    //
    // Since panics don't generate exceptions and foreign exceptions are
    // currently UB with -C panic=abort (although this may be subject to
    // change), any catch_unwind calls will never use this typeinfo.
    #[rustc_std_internal_symbol]
    #[allow(non_upper_case_globals)]
    #[cfg(target_os = "emscripten")]
    static rust_eh_catch_typeinfo: [usize; 2] = [0; 2];

    // These two are called by our startup objects on i686-pc-windows-gnu, but
    // they don't need to do anything so the bodies are nops.
    #[rustc_std_internal_symbol]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern "C" fn rust_eh_register_frames() {}
    #[rustc_std_internal_symbol]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern "C" fn rust_eh_unregister_frames() {}
}
<commit_msg>Rollup merge of #76871 - RalfJung:miri-panic-abort, r=dtolnay<commit_after>//! Implementation of Rust panics via process aborts
//!
//! When compared to the implementation via unwinding, this crate is *much*
//! simpler! That being said, it's not quite as versatile, but here goes!

#![no_std]
#![unstable(feature = "panic_abort", issue = "32837")]
#![doc(
    html_root_url = "https://doc.rust-lang.org/nightly/",
    issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/"
)]
#![panic_runtime]
#![allow(unused_features)]
#![feature(core_intrinsics)]
#![feature(libc)]
#![feature(nll)]
#![feature(panic_runtime)]
#![feature(staged_api)]
#![feature(rustc_attrs)]
#![feature(asm)]

use core::any::Any;

#[rustc_std_internal_symbol]
#[allow(improper_ctypes_definitions)]
pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) {
    unreachable!()
}

// "Leak" the payload and shim to the relevant abort on the platform in question.
#[rustc_std_internal_symbol]
pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 {
    abort();

    cfg_if::cfg_if! {
        if #[cfg(any(unix, target_os = "cloudabi"))] {
            unsafe fn abort() -> ! {
                libc::abort();
            }
        } else if #[cfg(any(target_os = "hermit",
                            all(target_vendor = "fortanix", target_env = "sgx")
        ))] {
            unsafe fn abort() -> ! {
                // call std::sys::abort_internal
                extern "C" {
                    pub fn __rust_abort() -> !;
                }
                __rust_abort();
            }
        } else if #[cfg(all(windows, not(miri)))] {
            // On Windows, use the processor-specific __fastfail mechanism. In Windows 8
            // and later, this will terminate the process immediately without running any
            // in-process exception handlers. In earlier versions of Windows, this
            // sequence of instructions will be treated as an access violation,
            // terminating the process but without necessarily bypassing all exception
            // handlers.
            //
            // https://docs.microsoft.com/en-us/cpp/intrinsics/fastfail
            //
            // Note: this is the same implementation as in libstd's `abort_internal`
            unsafe fn abort() -> ! {
                const FAST_FAIL_FATAL_APP_EXIT: usize = 7;
                cfg_if::cfg_if! {
                    if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
                        asm!("int $$0x29", in("ecx") FAST_FAIL_FATAL_APP_EXIT);
                    } else if #[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))] {
                        asm!(".inst 0xDEFB", in("r0") FAST_FAIL_FATAL_APP_EXIT);
                    } else if #[cfg(target_arch = "aarch64")] {
                        asm!("brk 0xF003", in("x0") FAST_FAIL_FATAL_APP_EXIT);
                    } else {
                        core::intrinsics::abort();
                    }
                }
                core::intrinsics::unreachable();
            }
        } else {
            unsafe fn abort() -> ! {
                core::intrinsics::abort();
            }
        }
    }
}

// This... is a bit of an oddity. The tl;dr; is that this is required to link
// correctly, the longer explanation is below.
//
// Right now the binaries of libcore/libstd that we ship are all compiled with
// `-C panic=unwind`. This is done to ensure that the binaries are maximally
// compatible with as many situations as possible. The compiler, however,
// requires a "personality function" for all functions compiled with `-C
// panic=unwind`. This personality function is hardcoded to the symbol
// `rust_eh_personality` and is defined by the `eh_personality` lang item.
//
// So... why not just define that lang item here? Good question! The way that
// panic runtimes are linked in is actually a little subtle in that they're
// "sort of" in the compiler's crate store, but only actually linked if another
// isn't actually linked. This ends up meaning that both this crate and the
// panic_unwind crate can appear in the compiler's crate store, and if both
// define the `eh_personality` lang item then that'll hit an error.
//
// To handle this the compiler only requires the `eh_personality` is defined if
// the panic runtime being linked in is the unwinding runtime, and otherwise
// it's not required to be defined (rightfully so). In this case, however, this
// library just defines this symbol so there's at least some personality
// somewhere.
//
// Essentially this symbol is just defined to get wired up to libcore/libstd
// binaries, but it should never be called as we don't link in an unwinding
// runtime at all.
pub mod personalities {
    #[rustc_std_internal_symbol]
    #[cfg(not(any(
        all(target_arch = "wasm32", not(target_os = "emscripten"),),
        all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",),
    )))]
    pub extern "C" fn rust_eh_personality() {}

    // On x86_64-pc-windows-gnu we use our own personality function that needs
    // to return `ExceptionContinueSearch` as we're passing on all our frames.
    #[rustc_std_internal_symbol]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86_64"))]
    pub extern "C" fn rust_eh_personality(
        _record: usize,
        _frame: usize,
        _context: usize,
        _dispatcher: usize,
    ) -> u32 {
        1 // `ExceptionContinueSearch`
    }

    // Similar to above, this corresponds to the `eh_catch_typeinfo` lang item
    // that's only used on Emscripten currently.
    //
    // Since panics don't generate exceptions and foreign exceptions are
    // currently UB with -C panic=abort (although this may be subject to
    // change), any catch_unwind calls will never use this typeinfo.
    #[rustc_std_internal_symbol]
    #[allow(non_upper_case_globals)]
    #[cfg(target_os = "emscripten")]
    static rust_eh_catch_typeinfo: [usize; 2] = [0; 2];

    // These two are called by our startup objects on i686-pc-windows-gnu, but
    // they don't need to do anything so the bodies are nops.
    #[rustc_std_internal_symbol]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern "C" fn rust_eh_register_frames() {}
    #[rustc_std_internal_symbol]
    #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))]
    pub extern "C" fn rust_eh_unregister_frames() {}
}
<|endoftext|>