<commit_before>/// Deserialization

use byteorder::{BigEndian, ReadBytesExt};

use std;
use std::fmt;
use std::fmt::Display;
use std::io;
use std::io::Read;
use std::vec;
use serde::de;
use serde::de::Visitor;

enum OscArg {
    /// 32-bit signed integer
    i(i32),
    /// 32-bit float
    f(f32),
    /// String; specified as null-terminated ascii.
    /// This might also represent the message address pattern (aka path)
    s(String),
    /// 'blob' (binary) data
    b(Vec<u8>),
}

struct OscDeserializer<R> {
    read: R,
    state: State,
}

/// Which part of the OSC message is being parsed
enum State {
    /// Deserializing the address pattern.
    Address,
    /// Deserializing the typestring.
    Typestring,
    /// Deserializing the argument data.
    /// Each entry in the Vec is the typecode we parsed earlier
    /// We store this as an iterator to avoid tracking the index of the current arg.
    Arguments(vec::IntoIter<u8>),
}

#[derive(Debug)]
enum Error {
    /// User provided error message (via serde::de::Error::custom)
    Message(String),
    /// Unknown argument type (i.e. not a 'f'=f32, 'i'=i32, etc)
    UnknownType(u8),
    /// Attempt to read more arguments than were in the typestring
    ArgMiscount,
    /// OSC expects all data to be aligned to 4 bytes lengths.
    /// Likely violators of this are strings, especially those at the end of a packet.
    BadPadding,
    /// Error encountered due to std::io::Read
    Io(io::Error),
    /// We store ascii strings as UTF-8.
    /// Technically, this is safe, but if we received non-ascii data, we could have invalid UTF-8
    StrParseError(std::string::FromUtf8Error),
}

/// Alias for a 'Result' with the error type 'serde_osc::de::Error'
type ResultE<T> = Result<T, Error>;

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "serde_osc::de::Error")
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Message(ref msg) => msg,
            _ => "Unknown serde_osc::de::Error",
        }
    }
    fn cause(&self) -> Option<&std::error::Error> {
        None
    }
}

impl de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error::Message(msg.to_string())
    }
}

impl<R> OscDeserializer<R>
    where R: Read
{
    pub fn new(read: R) -> Self {
        Self {
            read: read,
            state: State::Address,
        }
    }
    /// Strings in OSC are ascii and null-terminated.
    /// Strict specification is 1-4 null terminators, to make them end on a 4-byte boundary.
    fn read_0term_bytes(&mut self) -> ResultE<Vec<u8>> {
        let mut data = Vec::new();
        // Because of the 4-byte required padding, we can process 4 characters at a time
        let mut buf: [u8; 4] = [0, 0, 0, 0];
        while true {
            self.read.read_exact(&mut buf)?;
            // Copy the NON-NULL characters to the buffer.
            let num_zeros = buf.iter().filter(|c| **c == 0).count();
            if buf[4-num_zeros..4].iter().any(|c| *c != 0) {
                // We had data after the null terminator.
                return Err(Error::BadPadding);
            }
            data.extend_from_slice(&buf[0..4-num_zeros]);
        }
        Ok(data)
    }
    fn parse_str(&mut self) -> ResultE<String> {
        // Note: although OSC specifies ascii only, we may have data >= 128 in the vector.
        // We can safely assume a UTF-8 encoding, because no byte of any multibyte UTF-8
        // contains a zero; the only zero possible in a UTF-8 string is the ASCII zero.
        // See the UTF-8 table here: https://en.wikipedia.org/wiki/UTF-8#History
        let bytes = self.read_0term_bytes()?;
        String::from_utf8(bytes).map_err(|err| {
            Error::StrParseError(err)
        })
    }
    fn parse_typetag(&mut self) -> ResultE<vec::IntoIter<u8>> {
        // The type tag is a string type, with 4-byte null padding.
        self.read_0term_bytes().map(|bytes| bytes.into_iter())
    }

    fn parse_next(&mut self) -> ResultE<OscArg> {
        let typetag = match self.state {
            State::Address => {
                let address = self.parse_str()?;
                // Successfully parsed the address component; advance to the typestring.
                self.state = State::Typestring;
                return Ok(OscArg::s(address));
            },
            State::Typestring => {
                // parse the type tag
                let mut tags = self.parse_typetag()?;
                let parsed = self.parse_arg(tags.next())?;
                self.state = State::Arguments(tags);
                return Ok(parsed);
            },
            State::Arguments(ref mut tags) => {
                // Because parse_arg borrows self as mut, we need to do this weird
                // thing where we pop the typetag here, and then call parse_arg OUTSIDE
                tags.next()
            },
        };
        let parsed = self.parse_arg(typetag)?;
        return Ok(parsed);
    }
    fn parse_arg(&mut self, typecode: Option<u8>) -> ResultE<OscArg> {
        match typecode {
            Some(b'i') => self.parse_i32().map(|i| { OscArg::i(i) }),
            Some(b'f') => self.parse_f32().map(|f| { OscArg::f(f) }),
            Some(b's') => self.parse_str().map(|s| { OscArg::s(s) }),
            Some(b'b') => self.parse_blob().map(|b| { OscArg::b(b) }),
            Some(c) => Err(Error::UnknownType(c)),
            None => Err(Error::ArgMiscount),
        }
    }
    fn parse_i32(&mut self) -> ResultE<i32> {
       Ok( self.read.read_i32::<BigEndian>()?)
    }
    fn parse_f32(&mut self) -> ResultE<f32> {
        Ok(self.read.read_f32::<BigEndian>()?)
    }
    fn parse_blob(&mut self) -> ResultE<Vec<u8>> {
        let size = self.parse_i32()?;
        // Blobs are padded to a 4-byte boundary
        let padding = ((4-size)%4) as usize;
        let padded_size = size as usize + padding;
        // Read EXACTLY this much data:
        let mut data = vec![0; padded_size];
        self.read.read_exact(&mut data)?;
        // Ensure these extra bytes where NULL (sanity check)
        if data.drain(size as usize..padded_size).any(|c| c == 0) {
            Err(Error::BadPadding)
        } else {
            Ok(data)
        }
    }
}

impl<'a, R> de::Deserializer for &'a mut OscDeserializer<R>
    where R: Read
{
    type Error = Error;
    fn deserialize<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor
    {
        let value = self.parse_next()?;
        match value {
            OscArg::i(i) => visitor.visit_i32(i),
            OscArg::f(f) => visitor.visit_f32(f),
            OscArg::s(s) => visitor.visit_string(s),
            OscArg::b(b) => unimplemented!(),
        }
    }
    fn deserialize_bool<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u8<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u16<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i8<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i16<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_f32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_f64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_char<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_str<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_string<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_bytes<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_byte_buf<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_option<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_unit<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_unit_struct<V>(
        self,
        name: &'static str,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_newtype_struct<V>(
        self,
        name: &'static str,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_seq<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_seq_fixed_size<V>(
        self,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_tuple<V>(
        self,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_tuple_struct<V>(
        self,
        name: &'static str,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_map<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_struct<V>(
        self,
        name: &'static str,
        fields: &'static [&'static str],
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_struct_field<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_enum<V>(
        self,
        name: &'static str,
        variants: &'static [&'static str],
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_ignored_any<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
}

// Conversion from io::Error for use with the `?` operator
impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}
<commit_msg>deserialize method visits byte buffers (blobs)<commit_after>/// Deserialization

use byteorder::{BigEndian, ReadBytesExt};

use std;
use std::fmt;
use std::fmt::Display;
use std::io;
use std::io::Read;
use std::vec;
use serde::de;
use serde::de::Visitor;

enum OscArg {
    /// 32-bit signed integer
    i(i32),
    /// 32-bit float
    f(f32),
    /// String; specified as null-terminated ascii.
    /// This might also represent the message address pattern (aka path)
    s(String),
    /// 'blob' (binary) data
    b(Vec<u8>),
}

struct OscDeserializer<R> {
    read: R,
    state: State,
}

/// Which part of the OSC message is being parsed
enum State {
    /// Deserializing the address pattern.
    Address,
    /// Deserializing the typestring.
    Typestring,
    /// Deserializing the argument data.
    /// Each entry in the Vec is the typecode we parsed earlier
    /// We store this as an iterator to avoid tracking the index of the current arg.
    Arguments(vec::IntoIter<u8>),
}

#[derive(Debug)]
enum Error {
    /// User provided error message (via serde::de::Error::custom)
    Message(String),
    /// Unknown argument type (i.e. not a 'f'=f32, 'i'=i32, etc)
    UnknownType(u8),
    /// Attempt to read more arguments than were in the typestring
    ArgMiscount,
    /// OSC expects all data to be aligned to 4 bytes lengths.
    /// Likely violators of this are strings, especially those at the end of a packet.
    BadPadding,
    /// Error encountered due to std::io::Read
    Io(io::Error),
    /// We store ascii strings as UTF-8.
    /// Technically, this is safe, but if we received non-ascii data, we could have invalid UTF-8
    StrParseError(std::string::FromUtf8Error),
}

/// Alias for a 'Result' with the error type 'serde_osc::de::Error'
type ResultE<T> = Result<T, Error>;

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "serde_osc::de::Error")
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Message(ref msg) => msg,
            _ => "Unknown serde_osc::de::Error",
        }
    }
    fn cause(&self) -> Option<&std::error::Error> {
        None
    }
}

impl de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error::Message(msg.to_string())
    }
}

impl<R> OscDeserializer<R>
    where R: Read
{
    pub fn new(read: R) -> Self {
        Self {
            read: read,
            state: State::Address,
        }
    }
    /// Strings in OSC are ascii and null-terminated.
    /// Strict specification is 1-4 null terminators, to make them end on a 4-byte boundary.
    fn read_0term_bytes(&mut self) -> ResultE<Vec<u8>> {
        let mut data = Vec::new();
        // Because of the 4-byte required padding, we can process 4 characters at a time
        let mut buf: [u8; 4] = [0, 0, 0, 0];
        while true {
            self.read.read_exact(&mut buf)?;
            // Copy the NON-NULL characters to the buffer.
            let num_zeros = buf.iter().filter(|c| **c == 0).count();
            if buf[4-num_zeros..4].iter().any(|c| *c != 0) {
                // We had data after the null terminator.
                return Err(Error::BadPadding);
            }
            data.extend_from_slice(&buf[0..4-num_zeros]);
        }
        Ok(data)
    }
    fn parse_str(&mut self) -> ResultE<String> {
        // Note: although OSC specifies ascii only, we may have data >= 128 in the vector.
        // We can safely assume a UTF-8 encoding, because no byte of any multibyte UTF-8
        // contains a zero; the only zero possible in a UTF-8 string is the ASCII zero.
        // See the UTF-8 table here: https://en.wikipedia.org/wiki/UTF-8#History
        let bytes = self.read_0term_bytes()?;
        String::from_utf8(bytes).map_err(|err| {
            Error::StrParseError(err)
        })
    }
    fn parse_typetag(&mut self) -> ResultE<vec::IntoIter<u8>> {
        // The type tag is a string type, with 4-byte null padding.
        self.read_0term_bytes().map(|bytes| bytes.into_iter())
    }

    fn parse_next(&mut self) -> ResultE<OscArg> {
        let typetag = match self.state {
            State::Address => {
                let address = self.parse_str()?;
                // Successfully parsed the address component; advance to the typestring.
                self.state = State::Typestring;
                return Ok(OscArg::s(address));
            },
            State::Typestring => {
                // parse the type tag
                let mut tags = self.parse_typetag()?;
                let parsed = self.parse_arg(tags.next())?;
                self.state = State::Arguments(tags);
                return Ok(parsed);
            },
            State::Arguments(ref mut tags) => {
                // Because parse_arg borrows self as mut, we need to do this weird
                // thing where we pop the typetag here, and then call parse_arg OUTSIDE
                tags.next()
            },
        };
        let parsed = self.parse_arg(typetag)?;
        return Ok(parsed);
    }
    fn parse_arg(&mut self, typecode: Option<u8>) -> ResultE<OscArg> {
        match typecode {
            Some(b'i') => self.parse_i32().map(|i| { OscArg::i(i) }),
            Some(b'f') => self.parse_f32().map(|f| { OscArg::f(f) }),
            Some(b's') => self.parse_str().map(|s| { OscArg::s(s) }),
            Some(b'b') => self.parse_blob().map(|b| { OscArg::b(b) }),
            Some(c) => Err(Error::UnknownType(c)),
            None => Err(Error::ArgMiscount),
        }
    }
    fn parse_i32(&mut self) -> ResultE<i32> {
       Ok( self.read.read_i32::<BigEndian>()?)
    }
    fn parse_f32(&mut self) -> ResultE<f32> {
        Ok(self.read.read_f32::<BigEndian>()?)
    }
    fn parse_blob(&mut self) -> ResultE<Vec<u8>> {
        let size = self.parse_i32()?;
        // Blobs are padded to a 4-byte boundary
        let padding = ((4-size)%4) as usize;
        let padded_size = size as usize + padding;
        // Read EXACTLY this much data:
        let mut data = vec![0; padded_size];
        self.read.read_exact(&mut data)?;
        // Ensure these extra bytes where NULL (sanity check)
        if data.drain(size as usize..padded_size).any(|c| c == 0) {
            Err(Error::BadPadding)
        } else {
            Ok(data)
        }
    }
}

impl<'a, R> de::Deserializer for &'a mut OscDeserializer<R>
    where R: Read
{
    type Error = Error;
    fn deserialize<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor
    {
        let value = self.parse_next()?;
        match value {
            OscArg::i(i) => visitor.visit_i32(i),
            OscArg::f(f) => visitor.visit_f32(f),
            OscArg::s(s) => visitor.visit_string(s),
            OscArg::b(b) => visitor.visit_byte_buf(b),
        }
    }
    fn deserialize_bool<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u8<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u16<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_u64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i8<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i16<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_i64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_f32<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_f64<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_char<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_str<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_string<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_bytes<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_byte_buf<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_option<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_unit<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_unit_struct<V>(
        self,
        name: &'static str,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_newtype_struct<V>(
        self,
        name: &'static str,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_seq<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_seq_fixed_size<V>(
        self,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_tuple<V>(
        self,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_tuple_struct<V>(
        self,
        name: &'static str,
        len: usize,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_map<V>(self, visitor: V) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_struct<V>(
        self,
        name: &'static str,
        fields: &'static [&'static str],
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_struct_field<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_enum<V>(
        self,
        name: &'static str,
        variants: &'static [&'static str],
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
    fn deserialize_ignored_any<V>(
        self,
        visitor: V
    ) -> ResultE<V::Value>
    where
        V: Visitor { unimplemented!() }
}

// Conversion from io::Error for use with the `?` operator
impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error::Io(e)
    }
}
<|endoftext|>


<commit_before><commit_msg>cgroup parsers<commit_after>//! Parses the proc virtual file system for cgroup (control groups) information. The `/proc/[pid]/cgroup`
//! file describes control groups to which the process belongs. For each cgroup hierarchy there is
//! an entry of the form `hierarchy-id:subsystems:cgroup-path`, for example:
//!
//!     7:cpu,cpuacct:/user.slice
//!
//! where 7 is an unique hierarchy identifier, `cpu` and `cpuacct` are the cgroup subsystems bound
//! to the hierarchy, and finally, `/user.slice` is the cgroup pathname. There is a special `name=systemd`
//! cgroup with no bounded subsystem and is used by `systemd` to track services and user sessions.

use std::path::PathBuf;
use std::str::{self, FromStr};
use nom::{alpha, IResult};
use std::io::{Error, Result, ErrorKind, Read};
use std::fs::File;
use super::parsers::{consume_until_line_ending, parse_u8};

#[derive(Serialize, Debug)]
pub struct CGroup {
    /// the unique identifier of the cgroup hierarchy
    pub id: u8,
    /// vector of cgroup subsystems
    pub controllers: Vec<String>,
    /// pathname of the control group
    pub path: String
}

// parses cgroup subsystems
named!(controller, recognize!(chain!(
                                alpha ~
                                opt!(alt!(tag!("_") | tag!("="))) ~
                                opt!(alpha),
                                || {})));

named!(parse_controllers<Vec<String> >,
       many0!(do_parse!(c: map_res!(
                            map_res!(
                                controller,
                                str::from_utf8), FromStr::from_str) >>
                        opt!(tag!(",")) >>
                        opt!(tag!(":")) >> (c))));

// parses cgroup pathname
named!(parse_path<String>,
       map_res!(map_res!(consume_until_line_ending, str::from_utf8), FromStr::from_str));

// parses a single entry from the cgroup file
named!(cgroup<CGroup>, do_parse!(id: parse_u8 >>
                                 char!(':') >>
                                 controllers: parse_controllers >>
                                 path:  parse_path >>
                                 (CGroup { id: id,
                                          controllers: controllers,
                                          path: path })
                                 ));

fn parse_cgroups(buf: &[u8]) -> IResult<&[u8], Vec<CGroup>> {
    map!(buf, many0!(cgroup), |c| {c})
}

pub fn cgroups(pid: u64, root: String) -> Result<Vec<CGroup>> {
    let mut buf = String::new();
    let mut f = try!(File::open(format!("{}/{}/cgroup", root, pid)));
    f.read_to_string(&mut buf);
    match parse_cgroups(buf.as_bytes()) {
        IResult::Done(i, o) => {
            Ok(o)
        },
        IResult::Error(e) => {
            Err(Error::new(ErrorKind::InvalidInput, "unable to parse input"))
        },
        _ => Err(Error::new(ErrorKind::InvalidInput, "unable to parse input")),
    }
}<|endoftext|>


<commit_before>// Copyright (c) 2016-2019 Fabian Schuiki

//! A mapping from node IDs to AST nodes.

use ast;
use common::NodeId;
use std::cell::RefCell;
use std::collections::HashMap;

#[derive(Default)]
pub struct AstMap<'ast> {
    map: RefCell<HashMap<NodeId, AstNode<'ast>>>,
}

impl<'ast> AstMap<'ast> {
    pub fn set(&self, id: NodeId, node: impl Into<AstNode<'ast>>) {
        let node = node.into();
        if self.map.borrow_mut().insert(id, node).is_some() {
            panic!("An AST node with ID {} already exists in the map", id);
        }
    }
}

pub enum AstNode<'ast> {
    Module(&'ast ast::ModDecl),
}
<commit_msg>svlog: impl ast map node retrieval<commit_after>// Copyright (c) 2016-2019 Fabian Schuiki

//! A mapping from node IDs to AST nodes.

use ast;
use common::NodeId;
use std::cell::RefCell;
use std::collections::HashMap;

#[derive(Default)]
pub struct AstMap<'ast> {
    map: RefCell<HashMap<NodeId, AstNode<'ast>>>,
}

impl<'ast> AstMap<'ast> {
    /// Insert an AST node into the map.
    pub fn set(&self, id: NodeId, node: impl Into<AstNode<'ast>>) {
        let node = node.into();
        if self.map.borrow_mut().insert(id, node).is_some() {
            panic!("An AST node with ID {} already exists in the map", id);
        }
    }

    /// Retrieve an AST node from the map.
    pub fn get(&self, id: NodeId) -> Option<AstNode<'ast>> {
        self.map.borrow().get(&id).cloned()
    }
}

pub enum AstNode<'ast> {
    Module(&'ast ast::ModDecl),
}
<|endoftext|>


<commit_before>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Symbol reader
//!
//! A symbol reader reads one symbol at a time from a source
//!

use std::slice::Iter;
use std::io::*;

///
/// A symbol reader reads one symbol at a time from a source
///
pub trait SymbolReader<Symbol> {
    ///
    /// Reads the next symbol from this reader
    ///
    fn next_symbol(&mut self) -> Option<Symbol>;
}

///
/// Trait that can be implemented by things that can construct a symbol reader
///
pub trait SymbolSource<'a, Symbol> {
    /// The type of symbol reader that will be generated by this call
    type SymbolReader: SymbolReader<Symbol>+'a;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader;
}

impl<'a, Symbol: Clone+'a> SymbolSource<'a, Symbol> for &'a Vec<Symbol> {
    type SymbolReader = Iter<'a, Symbol>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.iter()
    }
}

impl<'a, Symbol: Clone+'a> SymbolReader<Symbol> for Iter<'a, Symbol> {
    fn next_symbol(&mut self) -> Option<Symbol> {
        if let Some(sym) = self.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

// Can read from streams

impl<'a> SymbolSource<'a, u8> for &'a mut Read {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}

impl<'a> SymbolSource<'a, u8> for &'a mut BufRead {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}

///
/// The ByteSymbolReader turns a `std::io::Bytes` object into a symbol reader
///
pub struct ByteSymbolReader<Reader: Read> {
    bytes: Bytes<Reader>
}

impl<Reader: Read> ByteSymbolReader<Reader> {
    pub fn new(bytes: Bytes<Reader>) -> ByteSymbolReader<Reader> {
        ByteSymbolReader { bytes: bytes }
    }

    pub fn from(reader: Reader) -> ByteSymbolReader<Reader> {
        Self::new(reader.bytes())
    }
}

impl<Reader: Read> SymbolReader<u8> for ByteSymbolReader<Reader> {
    fn next_symbol(&mut self) -> Option<u8> {
        if let Some(Ok(sym)) = self.bytes.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn can_read_from_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_read_from_bytes_reader() {
        let array: [u8; 3] = [1, 2, 3];
        let slice = &array[..];
        let mut reader = ByteSymbolReader::from(slice);

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }
}
<commit_msg>Add in a symbol reader for strings<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   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.
//

//!
//! # Symbol reader
//!
//! A symbol reader reads one symbol at a time from a source
//!

use std::slice::Iter;
use std::io::Read;
use std::io::BufRead;
use std::io::Bytes;
use std::str::Chars;

///
/// A symbol reader reads one symbol at a time from a source
///
pub trait SymbolReader<Symbol> {
    ///
    /// Reads the next symbol from this reader
    ///
    fn next_symbol(&mut self) -> Option<Symbol>;
}

///
/// Trait that can be implemented by things that can construct a symbol reader
///
pub trait SymbolSource<'a, Symbol> {
    /// The type of symbol reader that will be generated by this call
    type SymbolReader: SymbolReader<Symbol>+'a;

    /// Returns a new object that can read the symbols from this one
    fn read_symbols(self) -> Self::SymbolReader;
}

impl<'a, Symbol: Clone+'a> SymbolSource<'a, Symbol> for &'a Vec<Symbol> {
    type SymbolReader = Iter<'a, Symbol>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.iter()
    }
}

impl<'a, Symbol: Clone+'a> SymbolReader<Symbol> for Iter<'a, Symbol> {
    fn next_symbol(&mut self) -> Option<Symbol> {
        if let Some(sym) = self.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

// Can read from streams

impl<'a> SymbolSource<'a, u8> for &'a mut Read {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}

impl<'a> SymbolSource<'a, u8> for &'a mut BufRead {
    type SymbolReader = ByteSymbolReader<Self>;

    fn read_symbols(self) -> Self::SymbolReader {
        ByteSymbolReader::new(self.bytes())
    }
}

///
/// The ByteSymbolReader turns a `std::io::Bytes` object into a symbol reader
///
pub struct ByteSymbolReader<Reader: Read> {
    bytes: Bytes<Reader>
}

impl<Reader: Read> ByteSymbolReader<Reader> {
    pub fn new(bytes: Bytes<Reader>) -> ByteSymbolReader<Reader> {
        ByteSymbolReader { bytes: bytes }
    }

    pub fn from(reader: Reader) -> ByteSymbolReader<Reader> {
        Self::new(reader.bytes())
    }
}

impl<Reader: Read> SymbolReader<u8> for ByteSymbolReader<Reader> {
    fn next_symbol(&mut self) -> Option<u8> {
        if let Some(Ok(sym)) = self.bytes.next() {
            Some(sym.clone())
        } else {
            None
        }
    }
}

//
// Can read from strings
//
impl<'a> SymbolSource<'a, char> for &'a str {
    type SymbolReader = Chars<'a>;

    fn read_symbols(self) -> Self::SymbolReader {
        self.chars()
    }
}

impl<'a> SymbolReader<char> for Chars<'a> {
    fn next_symbol(&mut self) -> Option<char> {
        self.next()
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn can_read_from_vec() {
        let source      = vec![1, 2, 3];
        let mut reader  = source.read_symbols();

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_read_from_bytes_reader() {
        let array: [u8; 3] = [1, 2, 3];
        let slice = &array[..];
        let mut reader = ByteSymbolReader::from(slice);

        assert!(reader.next_symbol() == Some(1));
        assert!(reader.next_symbol() == Some(2));
        assert!(reader.next_symbol() == Some(3));
        assert!(reader.next_symbol() == None);
    }

    #[test]
    fn can_read_from_string_reader() {
        let mut reader = "abc".read_symbols();

        assert!(reader.next_symbol() == Some('a'));
        assert!(reader.next_symbol() == Some('b'));
        assert!(reader.next_symbol() == Some('c'));
        assert!(reader.next_symbol() == None);
    }
}
<|endoftext|>


<commit_before>//! Provide helpers for making ioctl system calls
//!
//! Currently supports Linux on all architectures. Other platforms welcome!
//!
//! This library is pretty low-level and messy. `ioctl` is not fun.
//!
//! What is an `ioctl`?
//! ===================
//!
//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want
//! to add a new syscall? Make it an `ioctl`! `ioctl` refers to both the syscall,
//! and the commands that can be send with it. `ioctl` stands for "IO control",
//! and the commands are always sent to a file descriptor.
//!
//! It is common to see `ioctl`s used for the following purposes:
//!
//! * Provide read/write access to out-of-band data related
//!   to a device such as configuration (for instance, setting
//!   serial port options)
//! * Provide a mechanism for performing full-duplex data
//!   transfers (for instance, xfer on SPI devices).
//! * Provide access to control functions on a device (for example,
//!   on Linux you can send commands like pause, resume, and eject
//!   to the CDROM device.
//! * Do whatever else the device driver creator thought made most sense.
//!
//! `ioctl`s are synchronous system calls and are similar to read and
//! write calls in that regard.
//!
//! What does this module support?
//! ===============================
//!
//! This library provides the `ioctl!` macro, for binding `ioctl`s.
//! Here's a few examples of how that can work for SPI under Linux
//! from [rust-spidev](https://github.com/posborne/rust-spidev).
//!
//! ```
//! #[allow(non_camel_case_types)]
//! pub struct spi_ioc_transfer {
//!     pub tx_buf: u64,
//!     pub rx_buf: u64,
//!     pub len: u32,
//!
//!     // optional overrides
//!     pub speed_hz: u32,
//!     pub delay_usecs: u16,
//!     pub bits_per_word: u8,
//!     pub cs_change: u8,
//!     pub pad: u32,
//! }
//!
//! #[cfg(linux)]
//! mod ioctl {
//!     use super::*;
//!
//!     const SPI_IOC_MAGIC: u8 = 'k' as u8;
//!     const SPI_IOC_NR_TRANSFER: u8 = 0;
//!     const SPI_IOC_NR_MODE: u8 = 1;
//!     const SPI_IOC_NR_LSB_FIRST: u8 = 2;
//!     const SPI_IOC_NR_BITS_PER_WORD: u8 = 3;
//!     const SPI_IOC_NR_MAX_SPEED_HZ: u8 = 4;
//!     const SPI_IOC_NR_MODE32: u8 = 5;
//!
//!     ioctl!(read  get_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8);
//!     ioctl!(read  get_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u32);
//!     ioctl!(write set_mode_u8 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE; u8);
//!     ioctl!(write set_mode_u32 with SPI_IOC_MAGIC, SPI_IOC_NR_MODE32; u32);
//!     ioctl!(read  get_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8);
//!     ioctl!(write set_lsb_first with SPI_IOC_MAGIC, SPI_IOC_NR_LSB_FIRST; u8);
//!     ioctl!(read  get_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8);
//!     ioctl!(write set_bits_per_word with SPI_IOC_MAGIC, SPI_IOC_NR_BITS_PER_WORD; u8);
//!     ioctl!(read  get_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32);
//!     ioctl!(write set_max_speed_hz with SPI_IOC_MAGIC, SPI_IOC_NR_MAX_SPEED_HZ; u32);
//!     ioctl!(write spidev_transfer with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer);
//!     ioctl!(write buf spidev_transfer_buf with SPI_IOC_MAGIC, SPI_IOC_NR_TRANSFER; spi_ioc_transfer);
//! }
//!
//! // doctest workaround
//! fn main() {}
//! ```
//!
//! Spidev uses the `_IOC` macros that are encouraged (as far as
//! `ioctl` can be encouraged at all) for newer drivers.  Many
//! drivers, however, just use magic numbers with no attached
//! semantics.  For those, the `ioctl!(bad ...)` variant should be
//! used (the "bad" terminology is from the Linux kernel).
//!
//! How do I get the magic numbers?
//! ===============================
//!
//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
//! of lines defining macros which use `_IOR`, `_IOW`, `_IOC`, and `_IORW`.  These macros
//! correspond to the `ior!`, `iow!`, `ioc!`, and `iorw!` macros defined in this crate.
//! Additionally, there is the `ioctl!` macro for creating a wrapper around `ioctl` that is
//! somewhat more type-safe.
//!
//! Most `ioctl`s have no or little documentation. You'll need to scrounge through
//! the source to figure out what they do and how they should be used.
//!
#[cfg(any(target_os = "linux", target_os = "android"))]
#[path = "platform/linux.rs"]
#[macro_use]
mod platform;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "netbsd",
          target_os = "openbsd",
          target_os = "freebsd",
          target_os = "dragonfly"))]
#[path = "platform/bsd.rs"]
#[macro_use]
mod platform;

pub use self::platform::*;

/// Convert raw ioctl return value to a Nix result
#[macro_export]
#[doc(hidden)]
macro_rules! convert_ioctl_res {
    ($w:expr) => (
        {
            $crate::Errno::result($w)
        }
    );
}

/// Generates ioctl functions. See [::sys::ioctl](sys/ioctl/index.html).
#[macro_export]
macro_rules! ioctl {
    (bad $name:ident with $nr:expr) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            data: *mut u8)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::libc::c_ulong, data))
        }
        );
    (bad none $name:ident with $nr:expr) => (
        pub unsafe fn $name(fd: $crate::libc::c_int)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::libc::c_ulong))
        }
        );
    (none $name:ident with $ioty:expr, $nr:expr) => (
        pub unsafe fn $name(fd: $crate::libc::c_int)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, io!($ioty, $nr) as $crate::libc::c_ulong))
        }
        );
    (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *mut $ty)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val))
        }
        );
    (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: $ty)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val))
        }
        );
    (readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *mut $ty)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val))
        }
        );
    (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *mut $ty,
                            len: usize)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, len) as $crate::libc::c_ulong, val))
        }
        );
    (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *const $ty,
                            len: usize) -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, len) as $crate::libc::c_ulong, val))
        }
        );
    (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *mut $ty,
                            len: usize)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, len) as $crate::libc::c_ulong, val))
        }
        );
}
<commit_msg>Revise ioctl module documentation<commit_after>//! Provide helpers for making ioctl system calls.
//!
//! This library is pretty low-level and messy. `ioctl` is not fun.
//!
//! What is an `ioctl`?
//! ===================
//!
//! The `ioctl` syscall is the grab-bag syscall on POSIX systems. Don't want to add a new
//! syscall? Make it an `ioctl`! `ioctl` refers to both the syscall, and the commands that can be
//! sent with it. `ioctl` stands for "IO control", and the commands are always sent to a file
//! descriptor.
//!
//! It is common to see `ioctl`s used for the following purposes:
//!
//!   * Provide read/write access to out-of-band data related to a device such as configuration
//!     (for instance, setting serial port options)
//!   * Provide a mechanism for performing full-duplex data transfers (for instance, xfer on SPI
//!     devices).
//!   * Provide access to control functions on a device (for example, on Linux you can send
//!     commands like pause, resume, and eject to the CDROM device.
//!   * Do whatever else the device driver creator thought made most sense.
//!
//! `ioctl`s are synchronous system calls and are similar to read and write calls in that regard.
//! They operate on file descriptors and have an identifier that specifies what the ioctl is.
//! Additionally they may read or write data and therefore need to pass along a data pointer.
//! Besides the semantics of the ioctls being confusing, the generation of this identifer can also
//! be difficult.
//!
//! Historically `ioctl` numbers were arbitrary hard-coded values. In Linux (before 2.6) and some
//! unices this has changed to a more-ordered system where the ioctl numbers are partitioned into
//! subcomponents (For linux this is documented in
//! [`Documentation/ioctl/ioctl-number.txt`](http://elixir.free-electrons.com/linux/latest/source/Documentation/ioctl/ioctl-number.txt)):
//!
//!   * Number: The actual ioctl ID
//!   * Type: A grouping of ioctls for a common purpose or driver
//!   * Size: The size in bytes of the data that will be transferred
//!   * Direction: Whether there is any data and if it's read, write, or both
//!
//! Newer drivers should not generate complete integer identifiers for their `ioctl`s instead
//! preferring to use the 4 components above to generate the final ioctl identifier. Because of
//! how old `ioctl`s are, however, there are many hard-coded `ioctl` identifiers. These are
//! commonly referred to as "bad" in `ioctl` documentation.
//!
//! Defining ioctls
//! ===============
//!
//! This library provides the `ioctl!` macro, for binding `ioctl`s. This macro generates public
//! unsafe functions that can then be used for calling the ioctl. This macro has a few different
//! ways it can be used depending on the specific ioctl you're working with.
//!
//! A simple `ioctl` is `SPI_IOC_RD_MODE`. This ioctl works with the SPI interface on Linux. This
//! specific `ioctl` reads the mode of the SPI device as a `u8`. It's declared in
//! `/include/uapi/linux/spi/spidev.h` as `_IOR(SPI_IOC_MAGIC, 1, __u8)`. Since it uses the `_IOR`
//! macro, we know it's a `read` ioctl and can use the `ioctl!` macro as follows:
//!
//! ```
//! # #[macro_use] extern crate nix;
//! const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
//! const SPI_IOC_TYPE_MODE: u8 = 1;
//! ioctl!(read spi_read_mode with SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE; u8);
//! # fn main() {}
//! ```
//!
//! This generates the function:
//!
//! ```
//! # #[macro_use] extern crate nix;
//! # use std::mem;
//! # use nix::{Errno, libc, Result};
//! # use nix::libc::c_int as c_int;
//! # const SPI_IOC_MAGIC: u8 = b'k'; // Defined in linux/spi/spidev.h
//! # const SPI_IOC_TYPE_MODE: u8 = 1;
//! pub unsafe fn spi_read_mode(fd: c_int, data: *mut u8) -> Result<c_int> {
//!     let res = libc::ioctl(fd, ior!(SPI_IOC_MAGIC, SPI_IOC_TYPE_MODE, mem::size_of::<u8>()), data);
//!     Errno::result(res)
//! }
//! # fn main() {}
//! ```
//!
//! The return value for `ioctl` functions generated by the `ioctl!` macro are `nix::Error`s.
//! These are generated by assuming the return value of the ioctl is `-1` on error and everything
//! else is a valid return value. If this is not the case, `Result::map` can be used to map some
//! of the range of "good" values (-2..-Inf, 0..Inf) into a smaller range in a helper function.
//!
//! The mode for a given `ioctl` should be clear from the documentation if it has good
//! documentation. Otherwise it will be clear based on the macro used to generate the `ioctl`
//! number where `_IO`, `_IOR`, `_IOW`, and `_IORW` map to "none", "read", "write_*", and "readwrite"
//! respectively. To determine the specific `write_` variant to use you'll need to find
//! what the argument type is supposed to be. If it's an `int`, then `write_int` should be used,
//! otherwise it should be a pointer and `write_ptr` should be used. On Linux the
//! [`ioctl_list` man page](http://man7.org/linux/man-pages/man2/ioctl_list.2.html) describes a
//! large number of `ioctl`s and describes their argument data type.
//!
//! More examples on using `ioctl!` can be found in the [rust-spidev crate](https://github.com/rust-embedded/rust-spidev).
//!
//! ```text
//! pub unsafe fn $NAME(fd: c_int, val: *mut u8, len: usize) -> Result<c_int>;
//! ```
//!
//! As mentioned earlier, there are many old `ioctl`s that do not use the newer method of
//! generating `ioctl` numbers and instead use hardcoded values. These can be used with the `bad`
//! form of the `ioctl!` macro (there is no data transfer direction used with `bad`). The naming of
//! this comes from the Linux kernel which refers to these `ioctl`s as "bad".
//!
//! For example the `TCGETS` `ioctl` reads a `termios` data structure for a given file descriptor.
//! It can be implemented as:
//!
//! ```
//! # #[macro_use] extern crate nix;
//! # #[cfg(any(target_os = "android", target_os = "linux"))]
//! # use nix::libc::TCGETS as TCGETS;
//! # #[cfg(any(target_os = "android", target_os = "linux"))]
//! ioctl!(bad tcgets with TCGETS);
//! # fn main() {}
//! ```
//!
//! The generated function has the same form as that generated by `read`:
//!
//! ```text
//! pub unsafe fn tcgets(fd: c_int, val: *mut u8) -> Result<c_int>;
//! ```
//!
//! There is also a `bad none` form for use with hard-coded `ioctl`s that do not transfer data.
//! The `TIOCEXCL` `ioctl` that's part of the termios API can be implemented as:
//!
//! ```
//! # #[macro_use] extern crate nix;
//! # use nix::libc::TIOCEXCL as TIOCEXCL;
//! ioctl!(bad none tiocexcl with TIOCEXCL);
//! # fn main() {}
//! ```
//!
//! More examples on using `ioctl!` can be found in the [rust-spidev crate](https://github.com/rust-embedded/rust-spidev).
//!
//! Finding ioctl documentation
//! ---------------------------
//!
//! For Linux, look at your system's headers. For example, `/usr/include/linux/input.h` has a lot
//! of lines defining macros which use `_IO`, `_IOR`, `_IOW`, `_IOC`, and `_IORW`. Some `ioctl`s are
//! documented directly in the headers defining their constants, but others have more extensive
//! documentation in man pages (like termios' `ioctl`s which are in `tty_ioctl(4)`).
#[cfg(any(target_os = "linux", target_os = "android"))]
#[path = "platform/linux.rs"]
#[macro_use]
mod platform;

#[cfg(any(target_os = "macos",
          target_os = "ios",
          target_os = "netbsd",
          target_os = "openbsd",
          target_os = "freebsd",
          target_os = "dragonfly"))]
#[path = "platform/bsd.rs"]
#[macro_use]
mod platform;

pub use self::platform::*;

/// Convert raw ioctl return value to a Nix result
#[macro_export]
#[doc(hidden)]
macro_rules! convert_ioctl_res {
    ($w:expr) => (
        {
            $crate::Errno::result($w)
        }
    );
}

/// Generates ioctl functions. See [::sys::ioctl](sys/ioctl/index.html).
#[macro_export]
macro_rules! ioctl {
    (bad $name:ident with $nr:expr) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            data: *mut u8)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::libc::c_ulong, data))
        }
        );
    (bad none $name:ident with $nr:expr) => (
        pub unsafe fn $name(fd: $crate::libc::c_int)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, $nr as $crate::libc::c_ulong))
        }
        );
    (none $name:ident with $ioty:expr, $nr:expr) => (
        pub unsafe fn $name(fd: $crate::libc::c_int)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, io!($ioty, $nr) as $crate::libc::c_ulong))
        }
        );
    (read $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *mut $ty)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val))
        }
        );
    (write $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: $ty)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val))
        }
        );
    (readwrite $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *mut $ty)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, ::std::mem::size_of::<$ty>()) as $crate::libc::c_ulong, val))
        }
        );
    (read buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *mut $ty,
                            len: usize)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, ior!($ioty, $nr, len) as $crate::libc::c_ulong, val))
        }
        );
    (write buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *const $ty,
                            len: usize) -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, iow!($ioty, $nr, len) as $crate::libc::c_ulong, val))
        }
        );
    (readwrite buf $name:ident with $ioty:expr, $nr:expr; $ty:ty) => (
        pub unsafe fn $name(fd: $crate::libc::c_int,
                            val: *mut $ty,
                            len: usize)
                            -> $crate::Result<$crate::libc::c_int> {
            convert_ioctl_res!($crate::libc::ioctl(fd, iorw!($ioty, $nr, len) as $crate::libc::c_ulong, val))
        }
        );
}
<|endoftext|>


<commit_before>use Renderable;
use Block;
use Value;
use template::Template;
use LiquidOptions;
use tags::IfBlock;
use lexer::Token;
use lexer::Token::{Identifier, StringLiteral, NumberLiteral, Comparison};
use lexer::ComparisonOperator;
use lexer::ComparisonOperator::{
    Equals, NotEquals,
    LessThan, GreaterThan,
    LessThanEquals, GreaterThanEquals,
    Contains
};
use parser::parse;
use lexer::Element;
use lexer::Element::{Tag, Raw};
use std::collections::HashMap;
use std::default::Default;

struct If<'a>{
    lh : Token,
    comparison : ComparisonOperator,
    rh : Token,
    if_true: Template<'a>,
    if_false: Option<Template<'a>>
}

impl<'a> If<'a>{
    fn compare(&self, context: &HashMap<String, Value>) -> Result<bool, &'static str>{
        match (&self.lh, &self.rh)  {
            (&NumberLiteral(a), &NumberLiteral(b)) => Ok(compare_numbers(a, b, &self.comparison)),
            (&Identifier(ref var), &NumberLiteral(b)) => {
                match context.get(var.as_slice()) {
                    Some(&Value::Num(a)) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            },
            (&NumberLiteral(a), &Identifier(ref var)) => {
                match context.get(var.as_slice()) {
                    Some(&Value::Num(b)) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            }
            (&Identifier(ref var_a), &Identifier(ref var_b)) => {
                match (context.get(var_a.as_slice()), context.get(var_b.as_slice())) {
                    (Some(&Value::Num(a)), Some(&Value::Num(b))) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            }
            (_, _) => Err("not implemented yet!") // TODO
        }
    }
}

fn compare_numbers(a : f32, b : f32, comparison : &ComparisonOperator) -> bool{
    match comparison {
        &Equals => a == b,
        &NotEquals => a != b,
        &LessThan => a < b,
        &GreaterThan => a > b,
        &LessThanEquals => a <= b,
        &GreaterThanEquals => a >= b,
        &Contains => false, // TODO!!!
    }
}

impl<'a> Renderable for If<'a>{
    fn render(&self, context: &HashMap<String, Value>) -> Option<String>{
        if self.compare(context).unwrap_or(false){
            self.if_true.render(context)
        }else{
            match self.if_false {
                Some(ref template) => template.render(context),
                _ => None
            }
        }
    }
}

impl<'b> Block for IfBlock<'b>{
    fn initialize<'a>(&'a self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &'a LiquidOptions<'a>) -> Box<Renderable>{
        let mut args = arguments.iter();

        let lh = match args.next() {
            Some(&StringLiteral(ref x)) => StringLiteral(x.clone()),
            Some(&NumberLiteral(ref x)) => NumberLiteral(x.clone()),
            Some(&Identifier(ref x)) => Identifier(x.clone()),
            x => panic!("Expected a value, found {}", x)
        };

        let comp = match args.next() {
            Some(&Comparison(ref x)) => x.clone(),
            x => panic!("Expected a comparison operator, found {}", x)
        };

        let rh = match args.next() {
            Some(&StringLiteral(ref x)) => StringLiteral(x.clone()),
            Some(&NumberLiteral(ref x)) => NumberLiteral(x.clone()),
            Some(&Identifier(ref x)) => Identifier(x.clone()),
            x => panic!("Expected a value, found {}", x)
        };

        let else_block = vec![Identifier("else".to_string())];

        let if_true_tokens = tokens.iter().take_while(|&x| match x  {
            &Tag(ref eb, _) => *eb != else_block,
            _ => true
        }).map(|x| x.clone()).collect();

        let if_false_tokens : Vec<Element> = tokens.iter().skip_while(|&x| match x  {
            &Tag(ref eb, _) => *eb != else_block,
            _ => true
        }).map(|x| x.clone()).collect();

        let if_false = if if_false_tokens.len() > 0 {
            Some(Template::new(parse(if_false_tokens, options)))
        }else{
            None
        };

        box If{
            lh : lh,
            comparison : comp,
            rh : rh,
            if_true: Template::new(parse(if_true_tokens, options)),
            if_false: if_false
        } as Box<Renderable>
    }
}

#[test]
fn test_if() {
    let block = IfBlock;
    let options : LiquidOptions = Default::default();
    let if_tag = block.initialize("if", vec![NumberLiteral(5f32), Comparison(LessThan), NumberLiteral(6f32)][0..], vec![Raw("if true".to_string())], &options);
    assert_eq!(if_tag.render(&HashMap::new()).unwrap(), "if true".to_string());

    let else_tag = block.initialize("if", vec![NumberLiteral(7f32), Comparison(LessThan), NumberLiteral(6f32)][0..], vec![Raw("if true".to_string()), Tag(vec![Identifier("else".to_string())], "".to_string()), Raw("if false".to_string())], &options);
    assert_eq!(else_tag.render(&HashMap::new()).unwrap(), "if false".to_string());
}

<commit_msg>Fix If including else token in else block<commit_after>use Renderable;
use Block;
use Value;
use template::Template;
use LiquidOptions;
use tags::IfBlock;
use lexer::Token;
use lexer::Token::{Identifier, StringLiteral, NumberLiteral, Comparison};
use lexer::ComparisonOperator;
use lexer::ComparisonOperator::{
    Equals, NotEquals,
    LessThan, GreaterThan,
    LessThanEquals, GreaterThanEquals,
    Contains
};
use parser::parse;
use lexer::Element;
use lexer::Element::{Tag, Raw};
use std::collections::HashMap;
use std::default::Default;

struct If<'a>{
    lh : Token,
    comparison : ComparisonOperator,
    rh : Token,
    if_true: Template<'a>,
    if_false: Option<Template<'a>>
}

impl<'a> If<'a>{
    fn compare(&self, context: &HashMap<String, Value>) -> Result<bool, &'static str>{
        match (&self.lh, &self.rh)  {
            (&NumberLiteral(a), &NumberLiteral(b)) => Ok(compare_numbers(a, b, &self.comparison)),
            (&Identifier(ref var), &NumberLiteral(b)) => {
                match context.get(var.as_slice()) {
                    Some(&Value::Num(a)) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            },
            (&NumberLiteral(a), &Identifier(ref var)) => {
                match context.get(var.as_slice()) {
                    Some(&Value::Num(b)) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            }
            (&Identifier(ref var_a), &Identifier(ref var_b)) => {
                match (context.get(var_a.as_slice()), context.get(var_b.as_slice())) {
                    (Some(&Value::Num(a)), Some(&Value::Num(b))) => Ok(compare_numbers(a, b, &self.comparison)),
                    _ => Err("not comparable")
                }
            }
            (_, _) => Err("not implemented yet!") // TODO
        }
    }
}

fn compare_numbers(a : f32, b : f32, comparison : &ComparisonOperator) -> bool{
    match comparison {
        &Equals => a == b,
        &NotEquals => a != b,
        &LessThan => a < b,
        &GreaterThan => a > b,
        &LessThanEquals => a <= b,
        &GreaterThanEquals => a >= b,
        &Contains => false, // TODO!!!
    }
}

impl<'a> Renderable for If<'a>{
    fn render(&self, context: &HashMap<String, Value>) -> Option<String>{
        if self.compare(context).unwrap_or(false){
            self.if_true.render(context)
        }else{
            match self.if_false {
                Some(ref template) => template.render(context),
                _ => None
            }
        }
    }
}

impl<'b> Block for IfBlock<'b>{
    fn initialize<'a>(&'a self, tag_name: &str, arguments: &[Token], tokens: Vec<Element>, options : &'a LiquidOptions<'a>) -> Box<Renderable>{
        let mut args = arguments.iter();

        let lh = match args.next() {
            Some(&StringLiteral(ref x)) => StringLiteral(x.clone()),
            Some(&NumberLiteral(ref x)) => NumberLiteral(x.clone()),
            Some(&Identifier(ref x)) => Identifier(x.clone()),
            x => panic!("Expected a value, found {}", x)
        };

        let comp = match args.next() {
            Some(&Comparison(ref x)) => x.clone(),
            x => panic!("Expected a comparison operator, found {}", x)
        };

        let rh = match args.next() {
            Some(&StringLiteral(ref x)) => StringLiteral(x.clone()),
            Some(&NumberLiteral(ref x)) => NumberLiteral(x.clone()),
            Some(&Identifier(ref x)) => Identifier(x.clone()),
            x => panic!("Expected a value, found {}", x)
        };

        let else_block = vec![Identifier("else".to_string())];

        // advance until the end or an else token is reached
        // to gather everything to be executed if the condition is true
        let if_true_tokens = tokens.iter().take_while(|&x| match x  {
            &Tag(ref eb, _) => *eb != else_block,
            _ => true
        }).map(|x| x.clone()).collect();

        // gather everything after the else block
        // to be executed if the condition is false
        let if_false_tokens : Vec<Element> = tokens.iter().skip_while(|&x| match x  {
            &Tag(ref eb, _) => *eb != else_block,
            _ => true
        }).skip(1).map(|x| x.clone()).collect();

        let if_false = if if_false_tokens.len() > 0 {
            Some(Template::new(parse(if_false_tokens, options)))
        }else{
            None
        };

        box If{
            lh : lh,
            comparison : comp,
            rh : rh,
            if_true: Template::new(parse(if_true_tokens, options)),
            if_false: if_false
        } as Box<Renderable>
    }
}

#[test]
fn test_if() {
    let block = IfBlock;
    let options : LiquidOptions = Default::default();
    let if_tag = block.initialize("if", vec![NumberLiteral(5f32), Comparison(LessThan), NumberLiteral(6f32)][0..], vec![Raw("if true".to_string())], &options);
    assert_eq!(if_tag.render(&HashMap::new()).unwrap(), "if true".to_string());

    let else_tag = block.initialize("if", vec![NumberLiteral(7f32), Comparison(LessThan), NumberLiteral(6f32)][0..], vec![Raw("if true".to_string()), Tag(vec![Identifier("else".to_string())], "".to_string()), Raw("if false".to_string())], &options);
    assert_eq!(else_tag.render(&HashMap::new()).unwrap(), "if false".to_string());
}

<|endoftext|>


<commit_before>//! Implements the SSA construction algorithm described in
//! "Simple and Efficient Construction of Static Single Assignment Form"

use petgraph::graph::{DefIndex, NodeIndex};
use middle::cfg::CFG;
use middle::ssa::{SSA, NodeData};
use std::collections::{HashSet, HashMap};

type VarId = String; // consider transitioning to &str
type Block = NodeIndex;
type Node = NodeIndex;

struct SSAConstruction<'a> {
	cfg:             &'a CFG,
	ssa:             &'a mut SSA,
	variables:       Vec<VarId>, // assume consequtive integers?
	sealed_blocks:   HashSet<Block>, // replace with bitfield
	current_def:     HashMap<VarId, HashMap<Block, Node>>,
	incomplete_phis: HashMap<Block, HashMap<VarId, Node>>
}

impl<'a> SSAConstruction<'a> {
	pub fn new(variables: Vec<VarId>, cfg: &'a CFG, ssa: &'a mut SSA) -> SSAConstruction<'a> {
		let mut s = SSAConstruction {
			cfg:             cfg,
			ssa:             ssa,
			variables:       variables,
			sealed_blocks:   HashSet::new(),
			current_def:     HashMap::new(),
			incomplete_phis: HashMap::new()
		};
		for var in &s.variables {
			s.current_def.insert(var.clone(), HashMap::new());
		}
		for bbi in 0..cfg.g.node_count() {
			s.incomplete_phis.insert(NodeIndex::new(bbi), HashMap::new());
		}
		return s
	}

	pub fn write_variable(&mut self, variable: VarId, block: Block, value: Node) {
		self.current_def.get_mut(&variable).unwrap().insert(block, value);
	}

	pub fn read_variable(&mut self, variable: VarId, block: Block) -> Node {
		match self.current_def[&variable].get(&block).map(|r|*r) {
			Option::Some(r) => r,
			Option::None => self.read_variable_recursive(variable, block)
		}
	}

	pub fn seal_block(&mut self, block: Block) {
		for (variable, node) in &self.incomplete_phis[&block] {
			self.add_phi_operands(variable.clone(), node.clone());
		}
		self.sealed_blocks.insert(block);
	}

	fn newphi(&mut self, block: Block) -> Node {
		self.ssa.g.add_node(NodeData::Phi)
	}

	fn read_variable_recursive(&mut self, variable: VarId, block: Block) -> Node {
		let mut val;

		if !self.sealed_blocks.contains(&block) {
			// Incomplete CFG
			val = self.newphi(block);
			self.incomplete_phis.get_mut(&block).unwrap().insert(variable.clone(), val);
		} else {
			let pred = self.ssa.preds_of(block);
			if pred.len() == 1 {
				// Optimize the common case of one predecessor: No phi needed
				val = self.read_variable(variable.clone(), pred[0])
			} else {
				// Break potential cycles with operandless phi
				val = self.newphi(block);
				// TODO: only mark (see paper)
				self.write_variable(variable.clone(), block, val);
				val = self.add_phi_operands(variable.clone(), val)
			}
		}
		self.write_variable(variable, block, val);
		return val
	}

	fn add_phi_operands(&mut self, variable: VarId, phi: Node) -> Node {
		// Determine operands from predecessors
		for pred in self.ssa.preds_of(self.ssa.block_of(phi)) {
			let datasource = self.read_variable(variable.clone(), pred);
			self.ssa.phi_use(phi, datasource)
		}
		return self.try_remove_trivial_phi(phi)
	}

	fn try_remove_trivial_phi(&mut self, phi: Node) -> Node {
		let undef = NodeIndex::end();
		let mut same: Node = undef; // The phi is unreachable or in the start block
		for op in self.ssa.args_of(phi) {
			if op == same || op == phi {
				continue // Unique value or self−reference
			}
			if same != undef {
				return phi // The phi merges at least two values: not trivial
			}
			same = op
		}

		let users = self.ssa.uses_of(phi);
		self.ssa.replace(phi, same); // Reroute all uses of phi to same and remove phi

		// Try to recursively remove all phi users, which might have become trivial
		for use_ in users {
			if use_ == phi { continue; }
			if let NodeData::Phi = self.ssa.g[use_] {
				self.try_remove_trivial_phi(use_);
			}
		}
		return same
	}

	/*fn remove_redundant_phis(&self, phi_functions: Vec<Node>) {
		// should phi_functions be `Vec` or something else?
		let sccs = compute_phi_sccs(induced_subgraph(phi_functions));
		for scc in topological_sort(sccs) {
			processSCC(scc)
		}
	}*/

	/*fn processSCC(&self, scc) {
		if len(scc) = 1 { return } // we already handled trivial φ functions

		let inner = HashSet::new();
		let outerOps = HashSet::new();

		for phi in scc:
			isInner = True
			for operand in phi.getOperands() {
				if operand not in scc {
					outerOps.add(operand)
					isInner = False
				}
			}
			if isInner {
				inner.add(phi)
			}

		if len(outerOps) == 1 {
			replaceSCCByValue(scc, outerOps.pop())
		} else if len(outerOps) > 1 {
			remove_redundant_phis(inner)
		}
	}*/
}
<commit_msg>make ssa transform compile<commit_after>//! Implements the SSA construction algorithm described in
//! "Simple and Efficient Construction of Static Single Assignment Form"

use petgraph::graph::{DefIndex, NodeIndex};
use middle::cfg::CFG;
use middle::ssa::{SSA, NodeData};
use std::collections::{HashSet, HashMap};

type VarId = String; // consider transitioning to &str
type Block = NodeIndex;
type Node = NodeIndex;

struct SSAConstruction<'a> {
	cfg:             &'a CFG,
	ssa:             &'a mut SSA,
	variables:       Vec<VarId>, // assume consequtive integers?
	sealed_blocks:   HashSet<Block>, // replace with bitfield
	current_def:     HashMap<VarId, HashMap<Block, Node>>,
	incomplete_phis: HashMap<Block, HashMap<VarId, Node>>
}

impl<'a> SSAConstruction<'a> {
	pub fn new(variables: Vec<VarId>, cfg: &'a CFG, ssa: &'a mut SSA) -> SSAConstruction<'a> {
		let mut s = SSAConstruction {
			cfg:             cfg,
			ssa:             ssa,
			variables:       variables,
			sealed_blocks:   HashSet::new(),
			current_def:     HashMap::new(),
			incomplete_phis: HashMap::new()
		};
		for var in &s.variables {
			s.current_def.insert(var.clone(), HashMap::new());
		}
		for bbi in 0..cfg.g.node_count() {
			s.incomplete_phis.insert(NodeIndex::new(bbi), HashMap::new());
		}
		return s
	}

	pub fn write_variable(&mut self, variable: VarId, block: Block, value: Node) {
		self.current_def.get_mut(&variable).unwrap().insert(block, value);
	}

	pub fn read_variable(&mut self, variable: VarId, block: Block) -> Node {
		match self.current_def[&variable].get(&block).map(|r|*r) {
			Option::Some(r) => r,
			Option::None => self.read_variable_recursive(variable, block)
		}
	}

	pub fn seal_block(&mut self, block: Block) {
		let inc = self.incomplete_phis[&block].clone(); // TODO: remove clone

		for (variable, node) in inc {
			self.add_phi_operands(variable.clone(), node.clone());
		}
		self.sealed_blocks.insert(block);
	}

	fn newphi(&mut self, block: Block) -> Node {
		self.ssa.g.add_node(NodeData::Phi)
	}

	fn read_variable_recursive(&mut self, variable: VarId, block: Block) -> Node {
		let mut val;

		if !self.sealed_blocks.contains(&block) {
			// Incomplete CFG
			val = self.newphi(block);
			let oldval = self.incomplete_phis.get_mut(&block).unwrap().insert(variable.clone(), val);
			assert!(oldval.is_none());
		} else {
			let pred = self.ssa.preds_of(block);
			if pred.len() == 1 {
				// Optimize the common case of one predecessor: No phi needed
				val = self.read_variable(variable.clone(), pred[0])
			} else {
				// Break potential cycles with operandless phi
				val = self.newphi(block);
				// TODO: only mark (see paper)
				self.write_variable(variable.clone(), block, val);
				val = self.add_phi_operands(variable.clone(), val)
			}
		}
		self.write_variable(variable, block, val);
		return val
	}

	fn add_phi_operands(&mut self, variable: VarId, phi: Node) -> Node {
		// Determine operands from predecessors
		for pred in self.ssa.preds_of(self.ssa.block_of(phi)) {
			let datasource = self.read_variable(variable.clone(), pred);
			self.ssa.phi_use(phi, datasource)
		}
		return self.try_remove_trivial_phi(phi)
	}

	fn try_remove_trivial_phi(&mut self, phi: Node) -> Node {
		let undef = NodeIndex::end();
		let mut same: Node = undef; // The phi is unreachable or in the start block
		for op in self.ssa.args_of(phi) {
			if op == same || op == phi {
				continue // Unique value or self−reference
			}
			if same != undef {
				return phi // The phi merges at least two values: not trivial
			}
			same = op
		}

		let users = self.ssa.uses_of(phi);
		self.ssa.replace(phi, same); // Reroute all uses of phi to same and remove phi

		// Try to recursively remove all phi users, which might have become trivial
		for use_ in users {
			if use_ == phi { continue; }
			if let NodeData::Phi = self.ssa.g[use_] {
				self.try_remove_trivial_phi(use_);
			}
		}
		return same
	}

	/*fn remove_redundant_phis(&self, phi_functions: Vec<Node>) {
		// should phi_functions be `Vec` or something else?
		let sccs = compute_phi_sccs(induced_subgraph(phi_functions));
		for scc in topological_sort(sccs) {
			processSCC(scc)
		}
	}*/

	/*fn processSCC(&self, scc) {
		if len(scc) = 1 { return } // we already handled trivial φ functions

		let inner = HashSet::new();
		let outerOps = HashSet::new();

		for phi in scc:
			isInner = True
			for operand in phi.getOperands() {
				if operand not in scc {
					outerOps.add(operand)
					isInner = False
				}
			}
			if isInner {
				inner.add(phi)
			}

		if len(outerOps) == 1 {
			replaceSCCByValue(scc, outerOps.pop())
		} else if len(outerOps) > 1 {
			remove_redundant_phis(inner)
		}
	}*/
}
<|endoftext|>


<commit_before>//! Types for Vec-based storage with stack-like pushable states.

use std::fmt;
use std::mem;
use std::ptr;
use std::slice;
use std::convert::From;
use std::default::Default;
use std::ops::{Deref, DerefMut, Index, Range, RangeFrom, RangeFull, RangeTo};

/// Vec-like type with support for saving and restoring states via stack-like
/// operations
///
///
#[derive(Clone)]
pub struct SplitVec<T> {
    data: Vec<T>,
    splits: Vec<usize>
}

impl<T> SplitVec<T> {

    /// Create a new, empty SplitVec instance.
    #[inline]
    pub fn new() -> Self {
        SplitVec{data: Vec::new(), splits: Vec::new()}
    }

    /// Create a new, empty SplitVec instance with space for the specified
    /// number of entries.
    #[inline]
    pub fn with_capacity(data_capacity: usize, splits_capacity: usize) -> Self {
        SplitVec{data: Vec::with_capacity(data_capacity), splits: Vec::with_capacity(splits_capacity)}
    }

    /// Determine the offset of the first item in the current state.
    #[inline]
    fn offset(&self) -> usize {
        self.splits.last().cloned().unwrap_or_else(|| 0)
    }

    /// Mark a split above the current working state.
    ///
    /// This creates a new, empty state at the top of the `SplitVec`'s stack;
    /// you can use `pop_state` to return to the previous state or
    /// `pop_and_merge_states` to merge the current state with the
    /// previous one.
    #[inline]
    pub fn push_state(&mut self) {
        self.splits.push(self.data.len());
    }

    /// Mark a split above the current working state, then copy the contents of
    /// that state into the new working area.
    pub fn push_and_copy_state(&mut self) where T: Copy {
        let ofs = self.offset();
        let count = self.len();
        self.push_state();
        self.data.reserve(count);
        unsafe {
            let src = self.data.as_ptr().offset(ofs as isize);
            let dst = self.data.as_mut_ptr().offset((ofs + count) as isize);
            ptr::copy_nonoverlapping(src,
                                     dst,
                                     count);
            self.data.set_len(ofs + 2 * count);
        }
    }

    /// Restore the most-recently-pushed state, discarding all data added to
    /// the working vector since the last call to `push_state`.
    #[inline]
    pub fn pop_state(&mut self) {
        self.data.truncate(self.splits.pop().expect("Call to `pop_state` without prior matching `push_state` call"));
    }

    /// Remove the split between the current and previous states; this has the
    /// effect of merging their contents into the previous state.
    ///
    /// Calling this method will have no effect if no prior state exists.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::from(vec![1, 2, 3]);
    /// s.push_state();
    ///
    /// s.extend_from_slice(&[4, 5, 6]);
    /// assert_eq!(&*s, &[4, 5, 6]);
    ///
    /// s.pop_and_merge_states();
    /// assert_eq!(&*s, &[1, 2, 3, 4, 5, 6]);
    /// # }
    /// ```
    #[inline]
    pub fn pop_and_merge_states(&mut self) {
        self.splits.pop();
    }

    /// Get the number of items in the working state.
    #[inline]
    pub fn len(&self) -> usize {
        self.data.len() - self.offset()
    }

    /// Truncate the working state to at most a given number of elements.
    #[inline]
    pub fn truncate(&mut self, len: usize) {
        let ofs = self.offset();
        self.data.truncate(ofs + len)
    }

    /// Push an item onto the end of the working state.
    pub fn push(&mut self, value: T) {
        self.data.push(value)
    }

    /// Remove the top-most item from the working state and return it.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::new();
    /// assert_eq!(None, s.pop());
    ///
    /// s.extend_from_slice(&[1, 2, 3]);
    /// assert_eq!(Some(3), s.pop());
    /// # }
    /// ```
    ///
    /// `pop` works only within the current state, and will return `None` if the
    /// current state is empty even if a prior state is not:
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::from(vec![1, 2, 3]);
    /// s.push_state();
    ///
    /// assert_eq!(None, s.pop());
    /// # }
    /// ```
    pub fn pop(&mut self) -> Option<T> {
        if self.len() > 0 { self.data.pop() }
        else { None }
    }

    /// Extend the current working state from a slice.
    #[inline]
    pub fn extend_from_slice<'a>(&mut self, slice: &'a [T]) where T: Copy {
        self.data.extend_from_slice(slice)
    }

    /// Get a reference to the current working state as a slice.
    #[inline]
    pub fn as_slice(&self) -> &[T] {
        self
    }

    /// Remove adjacent duplicates in the working state.
    pub fn dedup(&mut self) where T: PartialEq {
        unsafe {
            let ofs = self.offset();
            let ln = self.data.len();
            if ln <= ofs {
                return;
            }

            let p = self.data.as_mut_ptr();
            let mut r: usize = 1 + ofs;
            let mut w: usize = 1 + ofs;

            while r < ln {
                let p_r = p.offset(r as isize);
                let p_wm1 = p.offset((w - 1) as isize);
                if *p_r != *p_wm1 {
                    if r != w {
                        let p_w = p_wm1.offset(1);
                        mem::swap(&mut *p_r, &mut *p_w);
                    }
                    w += 1;
                }
                r += 1;
            }

            self.truncate(w - ofs);
        }
    }

    /// Iterate over all states contained within the SplitVec.
    ///
    /// The final state is guaranteed to be the current working state.
    pub fn iter_states<'a>(&'a self) -> StateIter<'a, T> {
        StateIter{splits_iter: self.splits.iter(), data: &self.data[..], last_split: Some(0)}
    }
}

/// Iterator over the states of a SplitVec as slices.
///
/// Instances of `StateIter` are obtained by calling `iter_states` on
/// a [`SplitVec`](struct.SplitVec.html).
pub struct StateIter<'a,T> where T: 'a {
    splits_iter: slice::Iter<'a,usize>,
    data: &'a [T],
    last_split: Option<usize>
}

impl<'a, T: 'a> Iterator for StateIter<'a, T> {
    type Item = &'a [T];
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(start) = self.last_split {
            if let Some(end) = self.splits_iter.next() {
                self.last_split = Some(*end);
                Some(&self.data[start..*end])
            } else {
                self.last_split = None;
                Some(&self.data[start..])
            }
        } else { None }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.splits_iter.size_hint()
    }
}

use itertools::Itertools;
impl<T> fmt::Debug for SplitVec<T> where T: fmt::Debug {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}]",
               self.iter_states().map(|s| s.iter().map(|ref elt| format!("{:?}", elt)).join(", "))
               .join(" | "))
    }
}

impl<T> AsRef<SplitVec<T>> for SplitVec<T> {
    fn as_ref(&self) -> &Self {
        self
    }
}
impl<T> AsMut<SplitVec<T>> for SplitVec<T> {
    fn as_mut(&mut self) -> &mut Self {
        self
    }
}

impl<T> AsRef<[T]> for SplitVec<T> {
    fn as_ref(&self) -> &[T] {
        self
    }
}
impl<T> AsMut<[T]> for SplitVec<T> {
    fn as_mut(&mut self) -> &mut [T] {
        self
    }
}

impl<T> From<Vec<T>> for SplitVec<T> {
    fn from(v: Vec<T>) -> Self {
        SplitVec{data: v, splits: Vec::new()}
    }
}

impl<'a,T> From<&'a [T]> for SplitVec<T> where T: Clone {
    fn from(s: &'a [T]) -> Self {
        SplitVec{data: s.into(), splits: Vec::new()}
    }
}

impl<T> Default for SplitVec<T> {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Extend<T> for SplitVec<T> {
    fn extend<I>(&mut self, iter: I) where I: IntoIterator<Item=T> {
        self.data.extend(iter);
    }
}

impl<T> Deref for SplitVec<T> {
    type Target = [T];
    fn deref(&self) -> &Self::Target {
        let o = self.offset();
        &self.data[o..]
    }
}

impl<T> DerefMut for SplitVec<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let o = self.offset();
        &mut self.data[o..]
    }
}

impl<T> Index<usize> for SplitVec<T> {
    type Output = T;
    #[inline]
    fn index<'a>(&'a self, idx: usize) -> &'a T {
        let o = self.offset();
        &self.data[idx + o]
    }
}

impl<T> Index<Range<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: Range<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[(o + r.start)..(o + r.end)]
    }
}
impl<T> Index<RangeFrom<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: RangeFrom<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[(o + r.start)..]
    }
}
impl<T> Index<RangeTo<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: RangeTo<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[..(o + r.end)]
    }
}
impl<T> Index<RangeFull> for SplitVec<T> {
    type Output = [T];
    #[inline(always)]
    fn index<'a>(&'a self, _: RangeFull) -> &'a [T] {
        &self.data[..]
    }
}
<commit_msg>util/splitvec: add From<&[_;N]> impls for SplitVec for N in 0..32<commit_after>//! Types for Vec-based storage with stack-like pushable states.

use std::fmt;
use std::mem;
use std::ptr;
use std::slice;
use std::convert::From;
use std::default::Default;
use std::ops::{Deref, DerefMut, Index, Range, RangeFrom, RangeFull, RangeTo};

/// Vec-like type with support for saving and restoring states via stack-like
/// operations
///
///
#[derive(Clone)]
pub struct SplitVec<T> {
    data: Vec<T>,
    splits: Vec<usize>
}

impl<T> SplitVec<T> {

    /// Create a new, empty SplitVec instance.
    #[inline]
    pub fn new() -> Self {
        SplitVec{data: Vec::new(), splits: Vec::new()}
    }

    /// Create a new, empty SplitVec instance with space for the specified
    /// number of entries.
    #[inline]
    pub fn with_capacity(data_capacity: usize, splits_capacity: usize) -> Self {
        SplitVec{data: Vec::with_capacity(data_capacity), splits: Vec::with_capacity(splits_capacity)}
    }

    /// Determine the offset of the first item in the current state.
    #[inline]
    fn offset(&self) -> usize {
        self.splits.last().cloned().unwrap_or_else(|| 0)
    }

    /// Mark a split above the current working state.
    ///
    /// This creates a new, empty state at the top of the `SplitVec`'s stack;
    /// you can use `pop_state` to return to the previous state or
    /// `pop_and_merge_states` to merge the current state with the
    /// previous one.
    #[inline]
    pub fn push_state(&mut self) {
        self.splits.push(self.data.len());
    }

    /// Mark a split above the current working state, then copy the contents of
    /// that state into the new working area.
    pub fn push_and_copy_state(&mut self) where T: Copy {
        let ofs = self.offset();
        let count = self.len();
        self.push_state();
        self.data.reserve(count);
        unsafe {
            let src = self.data.as_ptr().offset(ofs as isize);
            let dst = self.data.as_mut_ptr().offset((ofs + count) as isize);
            ptr::copy_nonoverlapping(src,
                                     dst,
                                     count);
            self.data.set_len(ofs + 2 * count);
        }
    }

    /// Restore the most-recently-pushed state, discarding all data added to
    /// the working vector since the last call to `push_state`.
    #[inline]
    pub fn pop_state(&mut self) {
        self.data.truncate(self.splits.pop().expect("Call to `pop_state` without prior matching `push_state` call"));
    }

    /// Remove the split between the current and previous states; this has the
    /// effect of merging their contents into the previous state.
    ///
    /// Calling this method will have no effect if no prior state exists.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::from(vec![1, 2, 3]);
    /// s.push_state();
    ///
    /// s.extend_from_slice(&[4, 5, 6]);
    /// assert_eq!(&*s, &[4, 5, 6]);
    ///
    /// s.pop_and_merge_states();
    /// assert_eq!(&*s, &[1, 2, 3, 4, 5, 6]);
    /// # }
    /// ```
    #[inline]
    pub fn pop_and_merge_states(&mut self) {
        self.splits.pop();
    }

    /// Get the number of items in the working state.
    #[inline]
    pub fn len(&self) -> usize {
        self.data.len() - self.offset()
    }

    /// Truncate the working state to at most a given number of elements.
    #[inline]
    pub fn truncate(&mut self, len: usize) {
        let ofs = self.offset();
        self.data.truncate(ofs + len)
    }

    /// Push an item onto the end of the working state.
    pub fn push(&mut self, value: T) {
        self.data.push(value)
    }

    /// Remove the top-most item from the working state and return it.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::new();
    /// assert_eq!(None, s.pop());
    ///
    /// s.extend_from_slice(&[1, 2, 3]);
    /// assert_eq!(Some(3), s.pop());
    /// # }
    /// ```
    ///
    /// `pop` works only within the current state, and will return `None` if the
    /// current state is empty even if a prior state is not:
    ///
    /// ```rust
    /// # extern crate cripes;
    /// # use cripes::util::splitvec::SplitVec;
    /// # fn main() {
    /// let mut s = SplitVec::from(vec![1, 2, 3]);
    /// s.push_state();
    ///
    /// assert_eq!(None, s.pop());
    /// # }
    /// ```
    pub fn pop(&mut self) -> Option<T> {
        if self.len() > 0 { self.data.pop() }
        else { None }
    }

    /// Extend the current working state from a slice.
    #[inline]
    pub fn extend_from_slice<'a>(&mut self, slice: &'a [T]) where T: Copy {
        self.data.extend_from_slice(slice)
    }

    /// Get a reference to the current working state as a slice.
    #[inline]
    pub fn as_slice(&self) -> &[T] {
        self
    }

    /// Remove adjacent duplicates in the working state.
    pub fn dedup(&mut self) where T: PartialEq {
        unsafe {
            let ofs = self.offset();
            let ln = self.data.len();
            if ln <= ofs {
                return;
            }

            let p = self.data.as_mut_ptr();
            let mut r: usize = 1 + ofs;
            let mut w: usize = 1 + ofs;

            while r < ln {
                let p_r = p.offset(r as isize);
                let p_wm1 = p.offset((w - 1) as isize);
                if *p_r != *p_wm1 {
                    if r != w {
                        let p_w = p_wm1.offset(1);
                        mem::swap(&mut *p_r, &mut *p_w);
                    }
                    w += 1;
                }
                r += 1;
            }

            self.truncate(w - ofs);
        }
    }

    /// Iterate over all states contained within the SplitVec.
    ///
    /// The final state is guaranteed to be the current working state.
    pub fn iter_states<'a>(&'a self) -> StateIter<'a, T> {
        StateIter{splits_iter: self.splits.iter(), data: &self.data[..], last_split: Some(0)}
    }
}

/// Iterator over the states of a SplitVec as slices.
///
/// Instances of `StateIter` are obtained by calling `iter_states` on
/// a [`SplitVec`](struct.SplitVec.html).
pub struct StateIter<'a,T> where T: 'a {
    splits_iter: slice::Iter<'a,usize>,
    data: &'a [T],
    last_split: Option<usize>
}

impl<'a, T: 'a> Iterator for StateIter<'a, T> {
    type Item = &'a [T];
    fn next(&mut self) -> Option<Self::Item> {
        if let Some(start) = self.last_split {
            if let Some(end) = self.splits_iter.next() {
                self.last_split = Some(*end);
                Some(&self.data[start..*end])
            } else {
                self.last_split = None;
                Some(&self.data[start..])
            }
        } else { None }
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.splits_iter.size_hint()
    }
}

use itertools::Itertools;
impl<T> fmt::Debug for SplitVec<T> where T: fmt::Debug {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}]",
               self.iter_states().map(|s| s.iter().map(|ref elt| format!("{:?}", elt)).join(", "))
               .join(" | "))
    }
}

macro_rules! impl_from_array_reference_types {
    ($($N: expr)+) => {
        $(
            impl<'a,T> From<&'a [T; $N]> for SplitVec<T> where T: Copy {
                  fn from(a: &'a [T; $N]) -> Self {
                      let mut sv = SplitVec::new();
                      sv.extend_from_slice(a);
                      sv
                  }
            }
        )+
    }
}

impl_from_array_reference_types!{
    0  1  2  3  4  5  6  7  8  9
   10 11 12 13 14 15 16 17 18 19
   20 21 22 23 24 25 26 27 28 29
   30 31 32
}

impl<T> AsRef<SplitVec<T>> for SplitVec<T> {
    fn as_ref(&self) -> &Self {
        self
    }
}
impl<T> AsMut<SplitVec<T>> for SplitVec<T> {
    fn as_mut(&mut self) -> &mut Self {
        self
    }
}

impl<T> AsRef<[T]> for SplitVec<T> {
    fn as_ref(&self) -> &[T] {
        self
    }
}
impl<T> AsMut<[T]> for SplitVec<T> {
    fn as_mut(&mut self) -> &mut [T] {
        self
    }
}

impl<T> From<Vec<T>> for SplitVec<T> {
    fn from(v: Vec<T>) -> Self {
        SplitVec{data: v, splits: Vec::new()}
    }
}

impl<'a,T> From<&'a [T]> for SplitVec<T> where T: Clone {
    fn from(s: &'a [T]) -> Self {
        SplitVec{data: s.into(), splits: Vec::new()}
    }
}

impl<T> Default for SplitVec<T> {
    #[inline]
    fn default() -> Self {
        Self::new()
    }
}

impl<T> Extend<T> for SplitVec<T> {
    fn extend<I>(&mut self, iter: I) where I: IntoIterator<Item=T> {
        self.data.extend(iter);
    }
}

impl<T> Deref for SplitVec<T> {
    type Target = [T];
    fn deref(&self) -> &Self::Target {
        let o = self.offset();
        &self.data[o..]
    }
}

impl<T> DerefMut for SplitVec<T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        let o = self.offset();
        &mut self.data[o..]
    }
}

impl<T> Index<usize> for SplitVec<T> {
    type Output = T;
    #[inline]
    fn index<'a>(&'a self, idx: usize) -> &'a T {
        let o = self.offset();
        &self.data[idx + o]
    }
}

impl<T> Index<Range<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: Range<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[(o + r.start)..(o + r.end)]
    }
}
impl<T> Index<RangeFrom<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: RangeFrom<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[(o + r.start)..]
    }
}
impl<T> Index<RangeTo<usize>> for SplitVec<T> {
    type Output = [T];
    #[inline]
    fn index<'a>(&'a self, r: RangeTo<usize>) -> &'a [T] {
        let o = self.offset();
        &self.data[..(o + r.end)]
    }
}
impl<T> Index<RangeFull> for SplitVec<T> {
    type Output = [T];
    #[inline(always)]
    fn index<'a>(&'a self, _: RangeFull) -> &'a [T] {
        let o = self.offset();
        &self.data[o..]
    }
}
<|endoftext|>