<commit_before>use super::{Error};
use std::io::Write;
use std::io::Read;
use super::super::parse::ast::DataSrc;
use super::super::parse::ast::CompType;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

/// General enums in SQL
#[derive(Debug, Clone, Copy, RustcDecodable, RustcEncodable, PartialEq)]
pub enum SqlType {
    Int,
    Bool,
    Char(u8),
}

/// Defines the size of Sql data types
/// and returns them
impl SqlType {
    pub fn size(&self) -> u32 {
        match self {
            &SqlType::Int => 4 as u32,
            &SqlType::Bool => 1 as u32,
            &SqlType::Char(len) => (len + 1) as u32,
        }
    }

    /// Decodes the data in buf according to SqlType into a DataSrc enum.
    pub fn decode_from<R: Read>(&self, mut buf: &mut R) -> Result<DataSrc, Error> {
        match self {
            &SqlType::Int => {
                let i = try!(buf.read_i32::<BigEndian>());
                Ok(DataSrc::Int(i as i64))
            },
            &SqlType::Bool => {
                let b = try!(buf.read_u8());
                Ok(DataSrc::Bool(b))
            },
            &SqlType::Char(_) => {
                let mut s = String::new();
                try!(buf.read_to_string(&mut s));
                Ok(DataSrc::String(s))
            },
        }
    }

    /// Writes data to buf
    /// Returns the bytes written.
    /// Returns Error::InvalidType if type of DataSrc does not match expected
    /// type.
    /// Returns byteorder::Error, if data could not be written to buf.
    /// DataSrc: contains data to write to buf
    /// buf: target of write operation.
    pub fn encode_into<W: Write>(&self, mut buf: &mut W, data: &DataSrc)
    -> Result<u32, Error>
    {
        match self {
            &SqlType::Int => {
                match data {
                    &DataSrc::Int(a) => {
                        if a > i32::max_value() as i64 {
                            Err(Error::InvalidType)
                        }
                        else {
                            try!(buf.write_i32::<BigEndian>(a as i32));
                            Ok(self.size())
                        }
                    },
                    _=> {
                        Err(Error::InvalidType)
                    }
                }
            },
            &SqlType::Bool => {
                match data {
                    &DataSrc::Bool(a) => {
                        try!(buf.write_u8(a as u8));
                        Ok(self.size())
                    }
                    _=> {
                        Err(Error::InvalidType)
                    }
                }
            },
            &SqlType::Char(len) => {
                match data {
                    &DataSrc::String(ref a) => {
                        let str_as_bytes = Self::to_nul_terminated_bytes(&a, (len + 1) as u32);
                        try!(buf.write_all(&str_as_bytes));
                        Ok(self.size())
                    }
                    _=> {
                        Err(Error::InvalidType)
                    }
                }
            },
        }
    }
    /// Writes the vector vec to buf.
    /// Returns the bytes written.
    /// Returns byteorder::Error if vec could not be written to buf
    fn write_to_buf<W: Write>(mut buf: W, vec: &Vec<u8>) -> Result<u32, Error> {
        let mut it = vec.into_iter();
        let mut bytes_written = 0;

        loop {
            match it.next() {
                Some(v) => {
                    try!(buf.write_u8(*v));
                    bytes_written += 1;
                },
                None => break,
            }
        }
        Ok(bytes_written)
    }

    /// Convert s to a vector with l bytes.
    /// If length of s is > l, the returning vector will only contain the first
    /// l bytes.
    /// Otherwise the returned vector will be filled with \0
    /// until it contains l bytes.
    fn to_nul_terminated_bytes(s : &str, l: u32) -> Vec<u8> {
        let mut v = s.to_string().into_bytes();

        v.truncate((l - 1) as usize);

        while v.len() < l as usize {
            v.push(0x00);
        }
        v
    }
    /// compare function that lets you logical compare slices of u8
    /// returns a boolean on success and Error on fail
    /// uses other compare fn for the actual compare
    pub fn cmp(&self, val: &[u8], val2: &[u8], comp: CompType)
    -> Result<bool, Error>
    {
        info!("checking Compare type: {:?}", comp);
        match self {
            &SqlType::Int => {
                match comp {
                    CompType::Equ => {
                        self.equal_for_int_with_value(val, val2)
                    },
                    CompType::NEqu => {
                        self.equal_for_int_with_value(val, val2).map(|x| !x)
                    },
                    CompType::GThan => {
                        self.greater_than_for_int_with_value(val, val2)
                    },
                    CompType::SThan => {
                        self.lesser_than_for_int_with_value(val, val2)
                    },
                    CompType::GEThan => {
                        self.lesser_than_for_int_with_value(val, val2).map(|x| !x)
                    },
                    CompType::SEThan => {
                        self.greater_than_for_int_with_value(val, val2).map(|x| !x)
                    },
                }
            },

            &SqlType::Bool => {
                match comp {
                    CompType::Equ => {
                        self.compare_as_bool(val, val2)
                    },
                    CompType::NEqu => {
                        self.compare_byte_for_equal(val, val2).map(|x| !x)
                    },
                    _ => {
                        Err(Error::NoOperationPossible)
                    }
                }
            },

            &SqlType::Char(_) => {
                match comp {
                    CompType::Equ => {
                        self.compare_byte_for_equal(val, val2)
                    },
                    CompType::NEqu => {
                        self.compare_byte_for_equal(val, val2).map(|x| !x)
                    },
                    CompType::GThan => {
                        self.compare_byte_greater_than(val, val2)
                    },
                    CompType::SThan => {
                        self.compare_byte_lesser_than(val, val2)
                    },
                    CompType::GEThan => {
                        self.compare_byte_lesser_than(val, val2).map(|x| !x)
                    },
                    CompType::SEThan => {
                        self.compare_byte_greater_than(val, val2).map(|x| !x)
                    },
                }
            },
        }
    }
    /// fn compares slices of u8 byte for byte and returns if both values are equal
    /// returns boolean on success and Error when given values do not have the same size
    fn compare_byte_for_equal(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        if val != val2 {
            return Err(Error::WrongLength)
        }
        info!("start comparing each byte");
        for i in 0 .. val.len() {
            if val[i] != val2[i] {
                return Ok(false)
            }
        }
        Ok(true)
    }
    /// fn compares slices of u8 byte for byte and returns
    /// if first given value is greater than the second one
    /// returns boolean on success and Error when given values do not have the same size
    fn compare_byte_greater_than(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start comparing each byte");
        if val != val2 {
            return Err(Error::WrongLength)
        }
        for i in 0 .. val.len() {
            if val[i] > val2[i] {
                return Ok(true)
            }
        }
        Ok(false)
    }

    /// fn compares slices of u8 byte for byte and returns
    /// if first given value is lesser than the second one
    /// returns boolean on success and Error when given values do not have the same size
    fn compare_byte_lesser_than(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start comparing each byte");
        if val.len() != val2.len() {
            return Err(Error::WrongLength)
        }
        for i in 0 .. val.len() {
            if val[i] < val2[i] {
                return Ok(true)
            }
        }
        Ok(false)
    }

    /// fn compares slices of u8 as booleans and returns
    /// if both both booleans are true
    /// returns boolean on success and Error when given values do not have the same size
    fn compare_as_bool(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start checking length");
        if val.len() > 1 || val != val2 {
            return Err(Error::WrongLength)
        }
        info!("start comparing bool");
        if val == val2 {
            return Ok(true)
        }
        Ok(false)
    }
    /// converts value to i32 and compares if equal (needs 4 bytes)
    /// returns boolean if successful returns Error if not
    fn equal_for_int_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start converting to i32");
        let int1: i32 = try!(i32::from_sql(val));
        let int2: i32 = try!(i32::from_sql(val2));
        info!("start comparing i32");
        Ok(int1 == int2)
    }

    /// converts value to i32 and compares if first value is greater (needs 4 bytes)
    /// returns boolean if successful returns Error if not
    fn greater_than_for_int_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start converting to i32");
        let int1: i32 = try!(i32::from_sql(val));
        let int2: i32 = try!(i32::from_sql(val2));
        info!("start comparing i32");
        Ok(int1 == int2)
    }

    /// converts value to i32 and compares if first value is lesser (needs 4 bytes)
    /// returns boolean if successful returns Error if not
    fn lesser_than_for_int_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start converting to i32");
        let int1: i32 = try!(i32::from_sql(val));
        let int2: i32 = try!(i32::from_sql(val2));
        info!("start comparing i32");
        if int1 < int2 {
            return Ok(true)
        }
        Ok(false)
    }
    /// converts each character into value and uses the average of both val
    /// to determin equal or not
    /// returns boolean if successfull returns Error if not
    fn _equal_for_str_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        let mut value: u64 = 0;
        let mut value2: u64 = 0;
        info!("starting to calculate value of strings");
        for i in 0 .. val.len() {
            value += val[i] as u64;
        }
        value /= val.len() as u64;
        for i in 0 .. val2.len() {
            value2 += val2[i] as u64;
        }
        value2 /= val2.len() as u64;

        info!("starting to compare the value");
        if value2 == value {
            return Ok(true)
        }
        Ok(false)
    }
    /// converts each character into value and uses the average of both val
    /// to determin if val is greater than val2
    /// returns boolean if successfull returns Error if not
    fn _greater_than_for_str_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        let mut value: u64 = 0;
        let mut value2: u64 = 0;
        info!("starting to calculate value of strings");
        for i in 0 .. val.len() {
            value += val[i] as u64;
        }
        value /= val.len() as u64;
        for i in 0 .. val2.len() {
            value2 += val2[i] as u64;
        }
        value2 /= val2.len() as u64;
        info!("starting to compare the value");
        if value > value2 {
            return Ok(true)
        }
        Ok(false)
    }
    /// converts each character into value and uses the average of both val
    /// to determin if val is lesser than val2
    /// returns boolean if successfull returns Error if not
    fn _lesser_than_for_str_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        let mut value: u64 = 0;
        let mut value2: u64 = 0;
        info!("starting to calculate value of strings");
        for i in 0 .. val.len() {
            value += val[i] as u64;
        }
        value /= val.len() as u64;
        for i in 0 .. val2.len() {
            value2 += val2[i] as u64;
        }
        value2 /= val2.len() as u64;
        info!("starting to compare the value");
        if value < value2 {
            return Ok(true)
        }
        Ok(false)
    }
}

//---------------------------------------------------------------
// Column
//---------------------------------------------------------------

/// A table column. Has a name, a type, ...
#[derive(Debug,RustcDecodable, RustcEncodable,Clone)]
pub struct Column {
    pub name: String, // name of column
    pub sql_type: SqlType, // name of the data type that is contained in this column
    pub is_primary_key: bool, // defines if column is PK
    pub allow_null: bool, // defines if cloumn allows null
    pub description: String //Displays text describing this column.
}

impl Column {
    /// Creates a new column object
    /// Returns with Column
    pub fn new(
        name: &str,
        sql_type: SqlType,
        allow_null: bool,
        description: &str,
        is_primary_key: bool
        ) -> Column {

        Column {
            name: name.to_string(),
            sql_type: sql_type.clone(),
            allow_null: allow_null,
            description: description.to_string(),
            is_primary_key: is_primary_key
        }
    }

    pub fn get_sql_type(&self) -> &SqlType {
        &self.sql_type
    }

    pub fn get_coulmn_name(&self) -> &str {
        &self.name
    }

    pub fn get_size(&self) -> u32 {
        self.sql_type.size() as u32
    }
}

//---------------------------------------------------------------
// FromSql
//---------------------------------------------------------------

pub trait FromSql {
    fn from_sql(data: &[u8]) -> Result<Self, Error>;
}

impl FromSql for i32 {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {
        let i = try!(data.read_i32::<BigEndian>());
        Ok(i)
    }
}

impl FromSql for u16 {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {
        let u = try!(data.read_u16::<BigEndian>());
        Ok(u)
    }
}

impl FromSql for u8 {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {
        Err(Error::NoImplementation)
    }
}
impl FromSql for String {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {

        let mut s = String::new();

        try!(data.read_to_string(&mut s));
        //s.trim_matches('\0');
        Ok(s)
    }
}

impl FromSql for bool {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {
        Ok(try!(data.read_u8()) != 0)
    }
}
<commit_msg>some code shorting<commit_after>use super::{Error};
use std::io::Write;
use std::io::Read;
use super::super::parse::ast::DataSrc;
use super::super::parse::ast::CompType;
use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};

/// General enums in SQL
#[derive(Debug, Clone, Copy, RustcDecodable, RustcEncodable, PartialEq)]
pub enum SqlType {
    Int,
    Bool,
    Char(u8),
}

/// Defines the size of Sql data types
/// and returns them
impl SqlType {
    pub fn size(&self) -> u32 {
        match self {
            &SqlType::Int => 4 as u32,
            &SqlType::Bool => 1 as u32,
            &SqlType::Char(len) => (len + 1) as u32,
        }
    }

    /// Decodes the data in buf according to SqlType into a DataSrc enum.
    pub fn decode_from<R: Read>(&self, mut buf: &mut R) -> Result<DataSrc, Error> {
        match self {
            &SqlType::Int => {
                let i = try!(buf.read_i32::<BigEndian>());
                Ok(DataSrc::Int(i as i64))
            },
            &SqlType::Bool => {
                let b = try!(buf.read_u8());
                Ok(DataSrc::Bool(b))
            },
            &SqlType::Char(_) => {
                let mut s = String::new();
                try!(buf.read_to_string(&mut s));
                Ok(DataSrc::String(s))
            },
        }
    }

    /// Writes data to buf
    /// Returns the bytes written.
    /// Returns Error::InvalidType if type of DataSrc does not match expected
    /// type.
    /// Returns byteorder::Error, if data could not be written to buf.
    /// DataSrc: contains data to write to buf
    /// buf: target of write operation.
    pub fn encode_into<W: Write>(&self, mut buf: &mut W, data: &DataSrc)
    -> Result<u32, Error>
    {
        match self {
            &SqlType::Int => {
                match data {
                    &DataSrc::Int(a) => {
                        if a > i32::max_value() as i64 {
                            Err(Error::InvalidType)
                        }
                        else {
                            try!(buf.write_i32::<BigEndian>(a as i32));
                            Ok(self.size())
                        }
                    },
                    _=> {
                        Err(Error::InvalidType)
                    }
                }
            },
            &SqlType::Bool => {
                match data {
                    &DataSrc::Bool(a) => {
                        try!(buf.write_u8(a as u8));
                        Ok(self.size())
                    }
                    _=> {
                        Err(Error::InvalidType)
                    }
                }
            },
            &SqlType::Char(len) => {
                match data {
                    &DataSrc::String(ref a) => {
                        let str_as_bytes = Self::to_nul_terminated_bytes(&a, (len + 1) as u32);
                        try!(buf.write_all(&str_as_bytes));
                        Ok(self.size())
                    }
                    _=> {
                        Err(Error::InvalidType)
                    }
                }
            },
        }
    }
    /// Writes the vector vec to buf.
    /// Returns the bytes written.
    /// Returns byteorder::Error if vec could not be written to buf
    fn write_to_buf<W: Write>(mut buf: W, vec: &Vec<u8>) -> Result<u32, Error> {
        let mut it = vec.into_iter();
        let mut bytes_written = 0;

        loop {
            match it.next() {
                Some(v) => {
                    try!(buf.write_u8(*v));
                    bytes_written += 1;
                },
                None => break,
            }
        }
        Ok(bytes_written)
    }

    /// Convert s to a vector with l bytes.
    /// If length of s is > l, the returning vector will only contain the first
    /// l bytes.
    /// Otherwise the returned vector will be filled with \0
    /// until it contains l bytes.
    fn to_nul_terminated_bytes(s : &str, l: u32) -> Vec<u8> {
        let mut v = s.to_string().into_bytes();

        v.truncate((l - 1) as usize);

        while v.len() < l as usize {
            v.push(0x00);
        }
        v
    }
    /// compare function that lets you logical compare slices of u8
    /// returns a boolean on success and Error on fail
    /// uses other compare fn for the actual compare
    pub fn cmp(&self, val: &[u8], val2: &[u8], comp: CompType)
    -> Result<bool, Error>
    {
        info!("checking Compare type: {:?}", comp);
        match self {
            &SqlType::Int => {
                match comp {
                    CompType::Equ => {
                        self.equal_for_int_with_value(val, val2)
                    },
                    CompType::NEqu => {
                        self.equal_for_int_with_value(val, val2).map(|x| !x)
                    },
                    CompType::GThan => {
                        self.greater_than_for_int_with_value(val, val2)
                    },
                    CompType::SThan => {
                        self.lesser_than_for_int_with_value(val, val2)
                    },
                    CompType::GEThan => {
                        self.lesser_than_for_int_with_value(val, val2).map(|x| !x)
                    },
                    CompType::SEThan => {
                        self.greater_than_for_int_with_value(val, val2).map(|x| !x)
                    },
                }
            },

            &SqlType::Bool => {
                match comp {
                    CompType::Equ => {
                        self.compare_as_bool(val, val2)
                    },
                    CompType::NEqu => {
                        self.compare_byte_for_equal(val, val2).map(|x| !x)
                    },
                    _ => {
                        Err(Error::NoOperationPossible)
                    }
                }
            },

            &SqlType::Char(_) => {
                match comp {
                    CompType::Equ => {
                        self.compare_byte_for_equal(val, val2)
                    },
                    CompType::NEqu => {
                        self.compare_byte_for_equal(val, val2).map(|x| !x)
                    },
                    CompType::GThan => {
                        self.compare_byte_greater_than(val, val2)
                    },
                    CompType::SThan => {
                        self.compare_byte_lesser_than(val, val2)
                    },
                    CompType::GEThan => {
                        self.compare_byte_lesser_than(val, val2).map(|x| !x)
                    },
                    CompType::SEThan => {
                        self.compare_byte_greater_than(val, val2).map(|x| !x)
                    },
                }
            },
        }
    }
    /// fn compares slices of u8 byte for byte and returns if both values are equal
    /// returns boolean on success and Error when given values do not have the same size
    fn compare_byte_for_equal(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        if val != val2 {
            return Err(Error::WrongLength)
        }
        info!("start comparing each byte");
        for i in 0 .. val.len() {
            if val[i] != val2[i] {
                return Ok(false)
            }
        }
        Ok(true)
    }
    /// fn compares slices of u8 byte for byte and returns
    /// if first given value is greater than the second one
    /// returns boolean on success and Error when given values do not have the same size
    fn compare_byte_greater_than(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start comparing each byte");
        if val != val2 {
            return Err(Error::WrongLength)
        }
        for i in 0 .. val.len() {
            if val[i] > val2[i] {
                return Ok(true)
            }
        }
        Ok(false)
    }

    /// fn compares slices of u8 byte for byte and returns
    /// if first given value is lesser than the second one
    /// returns boolean on success and Error when given values do not have the same size
    fn compare_byte_lesser_than(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start comparing each byte");
        if val.len() != val2.len() {
            return Err(Error::WrongLength)
        }
        for i in 0 .. val.len() {
            if val[i] < val2[i] {
                return Ok(true)
            }
        }
        Ok(false)
    }

    /// fn compares slices of u8 as booleans and returns
    /// if both both booleans are true
    /// returns boolean on success and Error when given values do not have the same size
    fn compare_as_bool(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start checking length");
        if val.len() > 1 || val != val2 {
            return Err(Error::WrongLength)
        }
        info!("start comparing bool");
        Ok(val == val2)
    }
    /// converts value to i32 and compares if equal (needs 4 bytes)
    /// returns boolean if successful returns Error if not
    fn equal_for_int_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start converting to i32");
        let int1: i32 = try!(i32::from_sql(val));
        let int2: i32 = try!(i32::from_sql(val2));
        info!("start comparing i32");
        Ok(int1 == int2)
    }

    /// converts value to i32 and compares if first value is greater (needs 4 bytes)
    /// returns boolean if successful returns Error if not
    fn greater_than_for_int_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start converting to i32");
        let int1: i32 = try!(i32::from_sql(val));
        let int2: i32 = try!(i32::from_sql(val2));
        info!("start comparing i32");
        Ok(int1 == int2)
    }

    /// converts value to i32 and compares if first value is lesser (needs 4 bytes)
    /// returns boolean if successful returns Error if not
    fn lesser_than_for_int_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        info!("start converting to i32");
        let int1: i32 = try!(i32::from_sql(val));
        let int2: i32 = try!(i32::from_sql(val2));
        info!("start comparing i32");
        Ok(int1 < int2)
    }
    /// converts each character into value and uses the average of both val
    /// to determin equal or not
    /// returns boolean if successfull returns Error if not
    fn _equal_for_str_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        let mut value: u64 = 0;
        let mut value2: u64 = 0;
        info!("starting to calculate value of strings");
        for i in 0 .. val.len() {
            value += val[i] as u64;
        }
        value /= val.len() as u64;
        for i in 0 .. val2.len() {
            value2 += val2[i] as u64;
        }
        value2 /= val2.len() as u64;

        info!("starting to compare the value");
        Ok(value2 == value)
    }
    /// converts each character into value and uses the average of both val
    /// to determin if val is greater than val2
    /// returns boolean if successfull returns Error if not
    fn _greater_than_for_str_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        let mut value: u64 = 0;
        let mut value2: u64 = 0;
        info!("starting to calculate value of strings");
        for i in 0 .. val.len() {
            value += val[i] as u64;
        }
        value /= val.len() as u64;
        for i in 0 .. val2.len() {
            value2 += val2[i] as u64;
        }
        value2 /= val2.len() as u64;
        info!("starting to compare the value");
        Ok(value > value2)
    }
    /// converts each character into value and uses the average of both val
    /// to determin if val is lesser than val2
    /// returns boolean if successfull returns Error if not
    fn _lesser_than_for_str_with_value(&self, val: &[u8], val2: &[u8])
    -> Result<bool, Error>
    {
        let mut value: u64 = 0;
        let mut value2: u64 = 0;
        info!("starting to calculate value of strings");
        for i in 0 .. val.len() {
            value += val[i] as u64;
        }
        value /= val.len() as u64;
        for i in 0 .. val2.len() {
            value2 += val2[i] as u64;
        }
        value2 /= val2.len() as u64;
        info!("starting to compare the value");
        Ok(value < value2)
    }
}

//---------------------------------------------------------------
// Column
//---------------------------------------------------------------

/// A table column. Has a name, a type, ...
#[derive(Debug,RustcDecodable, RustcEncodable,Clone)]
pub struct Column {
    pub name: String, // name of column
    pub sql_type: SqlType, // name of the data type that is contained in this column
    pub is_primary_key: bool, // defines if column is PK
    pub allow_null: bool, // defines if cloumn allows null
    pub description: String //Displays text describing this column.
}

impl Column {
    /// Creates a new column object
    /// Returns with Column
    pub fn new(
        name: &str,
        sql_type: SqlType,
        allow_null: bool,
        description: &str,
        is_primary_key: bool
        ) -> Column {

        Column {
            name: name.to_string(),
            sql_type: sql_type.clone(),
            allow_null: allow_null,
            description: description.to_string(),
            is_primary_key: is_primary_key
        }
    }

    pub fn get_sql_type(&self) -> &SqlType {
        &self.sql_type
    }

    pub fn get_coulmn_name(&self) -> &str {
        &self.name
    }

    pub fn get_size(&self) -> u32 {
        self.sql_type.size() as u32
    }
}

//---------------------------------------------------------------
// FromSql
//---------------------------------------------------------------

pub trait FromSql {
    fn from_sql(data: &[u8]) -> Result<Self, Error>;
}

impl FromSql for i32 {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {
        let i = try!(data.read_i32::<BigEndian>());
        Ok(i)
    }
}

impl FromSql for u16 {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {
        let u = try!(data.read_u16::<BigEndian>());
        Ok(u)
    }
}

impl FromSql for u8 {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {
        Err(Error::NoImplementation)
    }
}
impl FromSql for String {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {

        let mut s = String::new();

        try!(data.read_to_string(&mut s));
        //s.trim_matches('\0');
        Ok(s)
    }
}

impl FromSql for bool {
    fn from_sql(mut data: &[u8]) -> Result<Self, Error> {
        Ok(try!(data.read_u8()) != 0)
    }
}
<|endoftext|>


<commit_before>use crate::builder::Builder;
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::{
    common::IntPredicate,
    traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods},
};
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::Ty;
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};

#[allow(dead_code)]
fn round_pointer_up_to_alignment(
    bx: &mut Builder<'a, 'll, 'tcx>,
    addr: &'ll Value,
    align: Align,
    ptr_ty: &'ll Type,
) -> &'ll Value {
    let mut ptr_as_int = bx.ptrtoint(addr, bx.cx().type_isize());
    ptr_as_int = bx.add(ptr_as_int, bx.cx().const_i32(align.bytes() as i32 - 1));
    ptr_as_int = bx.and(ptr_as_int, bx.cx().const_i32(-(align.bytes() as i32)));
    bx.inttoptr(ptr_as_int, ptr_ty)
}

fn emit_direct_ptr_va_arg(
    bx: &mut Builder<'a, 'll, 'tcx>,
    list: OperandRef<'tcx, &'ll Value>,
    llty: &'ll Type,
    size: Size,
    align: Align,
    slot_size: Align,
    allow_higher_align: bool,
) -> (&'ll Value, Align) {
    let va_list_ptr_ty = bx.cx().type_ptr_to(bx.cx.type_i8p());
    let va_list_addr = if list.layout.llvm_type(bx.cx) != va_list_ptr_ty {
        bx.bitcast(list.immediate(), va_list_ptr_ty)
    } else {
        list.immediate()
    };

    let ptr = bx.load(va_list_addr, bx.tcx().data_layout.pointer_align.abi);

    let (addr, addr_align) = if allow_higher_align && align > slot_size {
        (round_pointer_up_to_alignment(bx, ptr, align, bx.cx().type_i8p()), align)
    } else {
        (ptr, slot_size)
    };

    let aligned_size = size.align_to(slot_size).bytes() as i32;
    let full_direct_size = bx.cx().const_i32(aligned_size);
    let next = bx.inbounds_gep(addr, &[full_direct_size]);
    bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi);

    if size.bytes() < slot_size.bytes() && &*bx.tcx().sess.target.target.target_endian == "big" {
        let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32);
        let adjusted = bx.inbounds_gep(addr, &[adjusted_size]);
        (bx.bitcast(adjusted, bx.cx().type_ptr_to(llty)), addr_align)
    } else {
        (bx.bitcast(addr, bx.cx().type_ptr_to(llty)), addr_align)
    }
}

fn emit_ptr_va_arg(
    bx: &mut Builder<'a, 'll, 'tcx>,
    list: OperandRef<'tcx, &'ll Value>,
    target_ty: Ty<'tcx>,
    indirect: bool,
    slot_size: Align,
    allow_higher_align: bool,
) -> &'ll Value {
    let layout = bx.cx.layout_of(target_ty);
    let (llty, size, align) = if indirect {
        (
            bx.cx.layout_of(bx.cx.tcx.mk_imm_ptr(target_ty)).llvm_type(bx.cx),
            bx.cx.data_layout().pointer_size,
            bx.cx.data_layout().pointer_align,
        )
    } else {
        (layout.llvm_type(bx.cx), layout.size, layout.align)
    };
    let (addr, addr_align) =
        emit_direct_ptr_va_arg(bx, list, llty, size, align.abi, slot_size, allow_higher_align);
    if indirect {
        let tmp_ret = bx.load(addr, addr_align);
        bx.load(tmp_ret, align.abi)
    } else {
        bx.load(addr, addr_align)
    }
}

fn emit_aapcs_va_arg(
    bx: &mut Builder<'a, 'll, 'tcx>,
    list: OperandRef<'tcx, &'ll Value>,
    target_ty: Ty<'tcx>,
) -> &'ll Value {
    // Implementation of the AAPCS64 calling convention for va_args see
    // https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst
    let va_list_addr = list.immediate();
    let layout = bx.cx.layout_of(target_ty);

    let mut maybe_reg = bx.build_sibling_block("va_arg.maybe_reg");
    let mut in_reg = bx.build_sibling_block("va_arg.in_reg");
    let mut on_stack = bx.build_sibling_block("va_arg.on_stack");
    let mut end = bx.build_sibling_block("va_arg.end");
    let zero = bx.const_i32(0);
    let offset_align = Align::from_bytes(4).unwrap();
    assert!(&*bx.tcx().sess.target.target.target_endian == "little");

    let gr_type = target_ty.is_any_ptr() || target_ty.is_integral();
    let (reg_off, reg_top_index, slot_size) = if gr_type {
        let gr_offs = bx.struct_gep(va_list_addr, 7);
        let nreg = (layout.size.bytes() + 7) / 8;
        (gr_offs, 3, nreg * 8)
    } else {
        let vr_off = bx.struct_gep(va_list_addr, 9);
        let nreg = (layout.size.bytes() + 15) / 16;
        (vr_off, 5, nreg * 16)
    };

    // if the offset >= 0 then the value will be on the stack
    let mut reg_off_v = bx.load(reg_off, offset_align);
    let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero);
    bx.cond_br(use_stack, &on_stack.llbb(), &maybe_reg.llbb());

    // The value at this point might be in a register, but there is a chance that
    // it could be on the stack so we have to update the offset and then check
    // the offset again.

    if layout.align.abi.bytes() > 8 {
        assert!(layout.align.abi.bytes() <= 16);
        reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(15));
        reg_off_v = maybe_reg.and(reg_off_v, bx.const_i32(-16));
    }
    let new_reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(slot_size as i32));

    maybe_reg.store(new_reg_off_v, reg_off, offset_align);

    // Check to see if we have overflowed the registers as a result of this.
    // If we have then we need to use the stack for this value
    let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero);
    maybe_reg.cond_br(use_stack, &on_stack.llbb(), &in_reg.llbb());

    let top = in_reg.struct_gep(va_list_addr, reg_top_index);
    let top = in_reg.load(top, bx.tcx().data_layout.pointer_align.abi);

    // reg_value = *(@top + reg_off_v);
    let top = in_reg.gep(top, &[reg_off_v]);
    let top = in_reg.bitcast(top, bx.cx.type_ptr_to(layout.llvm_type(bx)));
    let reg_value = in_reg.load(top, layout.align.abi);
    in_reg.br(&end.llbb());

    // On Stack block
    let stack_value =
        emit_ptr_va_arg(&mut on_stack, list, target_ty, false, Align::from_bytes(8).unwrap(), true);
    on_stack.br(&end.llbb());

    let val = end.phi(
        layout.immediate_llvm_type(bx),
        &[reg_value, stack_value],
        &[&in_reg.llbb(), &on_stack.llbb()],
    );

    *bx = end;
    val
}

pub(super) fn emit_va_arg(
    bx: &mut Builder<'a, 'll, 'tcx>,
    addr: OperandRef<'tcx, &'ll Value>,
    target_ty: Ty<'tcx>,
) -> &'ll Value {
    // Determine the va_arg implementation to use. The LLVM va_arg instruction
    // is lacking in some instances, so we should only use it as a fallback.
    let target = &bx.cx.tcx.sess.target.target;
    let arch = &bx.cx.tcx.sess.target.target.arch;
    match (&**arch, target.options.is_like_windows) {
        // Windows x86
        ("x86", true) => {
            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), false)
        }
        // Generic x86
        ("x86", _) => {
            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true)
        }
        // Windows AArch64
        ("aarch64", true) => {
            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false)
        }
        // iOS AArch64
        ("aarch64", _) if target.target_os == "ios" => {
            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true)
        }
        ("aarch64", _) => emit_aapcs_va_arg(bx, addr, target_ty),
        // Windows x86_64
        ("x86_64", true) => {
            let target_ty_size = bx.cx.size_of(target_ty).bytes();
            let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two();
            emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false)
        }
        // For all other architecture/OS combinations fall back to using
        // the LLVM va_arg instruction.
        // https://llvm.org/docs/LangRef.html#va-arg-instruction
        _ => bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)),
    }
}
<commit_msg>Remove the assert on alignment check.<commit_after>use crate::builder::Builder;
use crate::type_::Type;
use crate::type_of::LayoutLlvmExt;
use crate::value::Value;
use rustc_codegen_ssa::mir::operand::OperandRef;
use rustc_codegen_ssa::{
    common::IntPredicate,
    traits::{BaseTypeMethods, BuilderMethods, ConstMethods, DerivedTypeMethods},
};
use rustc_middle::ty::layout::HasTyCtxt;
use rustc_middle::ty::Ty;
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};

#[allow(dead_code)]
fn round_pointer_up_to_alignment(
    bx: &mut Builder<'a, 'll, 'tcx>,
    addr: &'ll Value,
    align: Align,
    ptr_ty: &'ll Type,
) -> &'ll Value {
    let mut ptr_as_int = bx.ptrtoint(addr, bx.cx().type_isize());
    ptr_as_int = bx.add(ptr_as_int, bx.cx().const_i32(align.bytes() as i32 - 1));
    ptr_as_int = bx.and(ptr_as_int, bx.cx().const_i32(-(align.bytes() as i32)));
    bx.inttoptr(ptr_as_int, ptr_ty)
}

fn emit_direct_ptr_va_arg(
    bx: &mut Builder<'a, 'll, 'tcx>,
    list: OperandRef<'tcx, &'ll Value>,
    llty: &'ll Type,
    size: Size,
    align: Align,
    slot_size: Align,
    allow_higher_align: bool,
) -> (&'ll Value, Align) {
    let va_list_ptr_ty = bx.cx().type_ptr_to(bx.cx.type_i8p());
    let va_list_addr = if list.layout.llvm_type(bx.cx) != va_list_ptr_ty {
        bx.bitcast(list.immediate(), va_list_ptr_ty)
    } else {
        list.immediate()
    };

    let ptr = bx.load(va_list_addr, bx.tcx().data_layout.pointer_align.abi);

    let (addr, addr_align) = if allow_higher_align && align > slot_size {
        (round_pointer_up_to_alignment(bx, ptr, align, bx.cx().type_i8p()), align)
    } else {
        (ptr, slot_size)
    };

    let aligned_size = size.align_to(slot_size).bytes() as i32;
    let full_direct_size = bx.cx().const_i32(aligned_size);
    let next = bx.inbounds_gep(addr, &[full_direct_size]);
    bx.store(next, va_list_addr, bx.tcx().data_layout.pointer_align.abi);

    if size.bytes() < slot_size.bytes() && &*bx.tcx().sess.target.target.target_endian == "big" {
        let adjusted_size = bx.cx().const_i32((slot_size.bytes() - size.bytes()) as i32);
        let adjusted = bx.inbounds_gep(addr, &[adjusted_size]);
        (bx.bitcast(adjusted, bx.cx().type_ptr_to(llty)), addr_align)
    } else {
        (bx.bitcast(addr, bx.cx().type_ptr_to(llty)), addr_align)
    }
}

fn emit_ptr_va_arg(
    bx: &mut Builder<'a, 'll, 'tcx>,
    list: OperandRef<'tcx, &'ll Value>,
    target_ty: Ty<'tcx>,
    indirect: bool,
    slot_size: Align,
    allow_higher_align: bool,
) -> &'ll Value {
    let layout = bx.cx.layout_of(target_ty);
    let (llty, size, align) = if indirect {
        (
            bx.cx.layout_of(bx.cx.tcx.mk_imm_ptr(target_ty)).llvm_type(bx.cx),
            bx.cx.data_layout().pointer_size,
            bx.cx.data_layout().pointer_align,
        )
    } else {
        (layout.llvm_type(bx.cx), layout.size, layout.align)
    };
    let (addr, addr_align) =
        emit_direct_ptr_va_arg(bx, list, llty, size, align.abi, slot_size, allow_higher_align);
    if indirect {
        let tmp_ret = bx.load(addr, addr_align);
        bx.load(tmp_ret, align.abi)
    } else {
        bx.load(addr, addr_align)
    }
}

fn emit_aapcs_va_arg(
    bx: &mut Builder<'a, 'll, 'tcx>,
    list: OperandRef<'tcx, &'ll Value>,
    target_ty: Ty<'tcx>,
) -> &'ll Value {
    // Implementation of the AAPCS64 calling convention for va_args see
    // https://github.com/ARM-software/abi-aa/blob/master/aapcs64/aapcs64.rst
    let va_list_addr = list.immediate();
    let layout = bx.cx.layout_of(target_ty);

    let mut maybe_reg = bx.build_sibling_block("va_arg.maybe_reg");
    let mut in_reg = bx.build_sibling_block("va_arg.in_reg");
    let mut on_stack = bx.build_sibling_block("va_arg.on_stack");
    let mut end = bx.build_sibling_block("va_arg.end");
    let zero = bx.const_i32(0);
    let offset_align = Align::from_bytes(4).unwrap();
    assert!(&*bx.tcx().sess.target.target.target_endian == "little");

    let gr_type = target_ty.is_any_ptr() || target_ty.is_integral();
    let (reg_off, reg_top_index, slot_size) = if gr_type {
        let gr_offs = bx.struct_gep(va_list_addr, 7);
        let nreg = (layout.size.bytes() + 7) / 8;
        (gr_offs, 3, nreg * 8)
    } else {
        let vr_off = bx.struct_gep(va_list_addr, 9);
        let nreg = (layout.size.bytes() + 15) / 16;
        (vr_off, 5, nreg * 16)
    };

    // if the offset >= 0 then the value will be on the stack
    let mut reg_off_v = bx.load(reg_off, offset_align);
    let use_stack = bx.icmp(IntPredicate::IntSGE, reg_off_v, zero);
    bx.cond_br(use_stack, &on_stack.llbb(), &maybe_reg.llbb());

    // The value at this point might be in a register, but there is a chance that
    // it could be on the stack so we have to update the offset and then check
    // the offset again.

    if gr_type && layout.align.abi.bytes() > 8 {
        reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(15));
        reg_off_v = maybe_reg.and(reg_off_v, bx.const_i32(-16));
    }
    let new_reg_off_v = maybe_reg.add(reg_off_v, bx.const_i32(slot_size as i32));

    maybe_reg.store(new_reg_off_v, reg_off, offset_align);

    // Check to see if we have overflowed the registers as a result of this.
    // If we have then we need to use the stack for this value
    let use_stack = maybe_reg.icmp(IntPredicate::IntSGT, new_reg_off_v, zero);
    maybe_reg.cond_br(use_stack, &on_stack.llbb(), &in_reg.llbb());

    let top = in_reg.struct_gep(va_list_addr, reg_top_index);
    let top = in_reg.load(top, bx.tcx().data_layout.pointer_align.abi);

    // reg_value = *(@top + reg_off_v);
    let top = in_reg.gep(top, &[reg_off_v]);
    let top = in_reg.bitcast(top, bx.cx.type_ptr_to(layout.llvm_type(bx)));
    let reg_value = in_reg.load(top, layout.align.abi);
    in_reg.br(&end.llbb());

    // On Stack block
    let stack_value =
        emit_ptr_va_arg(&mut on_stack, list, target_ty, false, Align::from_bytes(8).unwrap(), true);
    on_stack.br(&end.llbb());

    let val = end.phi(
        layout.immediate_llvm_type(bx),
        &[reg_value, stack_value],
        &[&in_reg.llbb(), &on_stack.llbb()],
    );

    *bx = end;
    val
}

pub(super) fn emit_va_arg(
    bx: &mut Builder<'a, 'll, 'tcx>,
    addr: OperandRef<'tcx, &'ll Value>,
    target_ty: Ty<'tcx>,
) -> &'ll Value {
    // Determine the va_arg implementation to use. The LLVM va_arg instruction
    // is lacking in some instances, so we should only use it as a fallback.
    let target = &bx.cx.tcx.sess.target.target;
    let arch = &bx.cx.tcx.sess.target.target.arch;
    match (&**arch, target.options.is_like_windows) {
        // Windows x86
        ("x86", true) => {
            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), false)
        }
        // Generic x86
        ("x86", _) => {
            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(4).unwrap(), true)
        }
        // Windows AArch64
        ("aarch64", true) => {
            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), false)
        }
        // iOS AArch64
        ("aarch64", _) if target.target_os == "ios" => {
            emit_ptr_va_arg(bx, addr, target_ty, false, Align::from_bytes(8).unwrap(), true)
        }
        ("aarch64", _) => emit_aapcs_va_arg(bx, addr, target_ty),
        // Windows x86_64
        ("x86_64", true) => {
            let target_ty_size = bx.cx.size_of(target_ty).bytes();
            let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two();
            emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false)
        }
        // For all other architecture/OS combinations fall back to using
        // the LLVM va_arg instruction.
        // https://llvm.org/docs/LangRef.html#va-arg-instruction
        _ => bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)),
    }
}
<|endoftext|>


<commit_before>//!
//! [`RawDevice`](RawDevice) and [`RawSurface`](RawSurface)
//! implementations using the atomic mode-setting infrastructure.
//!
//! Usually this implementation will wrapped into a [`GbmDevice`](::backend::drm::gbm::GbmDevice).
//! Take a look at `anvil`s source code for an example of this.
//!
//! For an example how to use this standalone, take a look at the raw_atomic_drm example.
//!

use std::cell::RefCell;
use std::collections::HashMap;
use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::{Rc, Weak};
use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};

use drm::control::{atomic::AtomicModeReq, AtomicCommitFlags, Device as ControlDevice, Event};
use drm::control::{
    connector, crtc, encoder, framebuffer, plane, property, PropertyValueSet, ResourceHandle, ResourceHandles,
};
use drm::SystemError as DrmError;
use drm::{ClientCapability, Device as BasicDevice};
use failure::{Fail, ResultExt};
use nix::libc::dev_t;
use nix::sys::stat::fstat;

use super::{common::Error, DevPath, Device, DeviceHandler, RawDevice};

mod surface;
pub use self::surface::AtomicDrmSurface;
use self::surface::AtomicDrmSurfaceInternal;

#[cfg(feature = "backend_session")]
pub mod session;

/// Open raw drm device utilizing atomic mode-setting
pub struct AtomicDrmDevice<A: AsRawFd + 'static> {
    dev: Rc<Dev<A>>,
    dev_id: dev_t,
    active: Arc<AtomicBool>,
    backends: Rc<RefCell<HashMap<crtc::Handle, Weak<AtomicDrmSurfaceInternal<A>>>>>,
    handler: Option<RefCell<Box<dyn DeviceHandler<Device = AtomicDrmDevice<A>>>>>,
    logger: ::slog::Logger,
}

type OldState = (
    Vec<(connector::Handle, PropertyValueSet)>,
    Vec<(crtc::Handle, PropertyValueSet)>,
    Vec<(framebuffer::Handle, PropertyValueSet)>,
    Vec<(plane::Handle, PropertyValueSet)>,
);

type Mapping = (
    HashMap<connector::Handle, HashMap<String, property::Handle>>,
    HashMap<crtc::Handle, HashMap<String, property::Handle>>,
    HashMap<framebuffer::Handle, HashMap<String, property::Handle>>,
    HashMap<plane::Handle, HashMap<String, property::Handle>>,
);

struct Dev<A: AsRawFd + 'static> {
    fd: A,
    privileged: bool,
    active: Arc<AtomicBool>,
    old_state: OldState,
    prop_mapping: Mapping,
    logger: ::slog::Logger,
}

impl<A: AsRawFd + 'static> AsRawFd for Dev<A> {
    fn as_raw_fd(&self) -> RawFd {
        self.fd.as_raw_fd()
    }
}
impl<A: AsRawFd + 'static> BasicDevice for Dev<A> {}
impl<A: AsRawFd + 'static> ControlDevice for Dev<A> {}
impl<A: AsRawFd + 'static> Drop for Dev<A> {
    fn drop(&mut self) {
        info!(self.logger, "Dropping device: {:?}", self.dev_path());
        if self.active.load(Ordering::SeqCst) {
            // Here we restore the card/tty's to it's previous state.
            // In case e.g. getty was running on the tty sets the correct framebuffer again,
            // so that getty will be visible.

            let mut req = AtomicModeReq::new();

            fn add_multiple_props<T: ResourceHandle>(
                req: &mut AtomicModeReq,
                old_state: &[(T, PropertyValueSet)],
            ) {
                for (handle, set) in old_state {
                    let (prop_handles, values) = set.as_props_and_values();
                    for (&prop_handle, &val) in prop_handles.iter().zip(values.iter()) {
                        req.add_raw_property((*handle).into(), prop_handle, val);
                    }
                }
            };

            add_multiple_props(&mut req, &self.old_state.0);
            add_multiple_props(&mut req, &self.old_state.1);
            add_multiple_props(&mut req, &self.old_state.2);
            add_multiple_props(&mut req, &self.old_state.3);

            if let Err(err) = self.atomic_commit(&[AtomicCommitFlags::AllowModeset], req) {
                error!(self.logger, "Failed to restore previous state. Error: {}", err);
            }
        }
        if self.privileged {
            if let Err(err) = self.release_master_lock() {
                error!(self.logger, "Failed to drop drm master state. Error: {}", err);
            }
        }
    }
}

impl<A: AsRawFd + 'static> Dev<A> {
    // Add all properties of given handles to a given drm resource type to state.
    // You may use this to snapshot the current state of the drm device (fully or partially).
    fn add_props<T>(&self, handles: &[T], state: &mut Vec<(T, PropertyValueSet)>) -> Result<(), Error>
    where
        A: AsRawFd + 'static,
        T: ResourceHandle,
    {
        let iter = handles.iter().map(|x| (x, self.get_properties(*x)));
        if let Some(len) = iter.size_hint().1 {
            state.reserve_exact(len)
        }

        iter.map(|(x, y)| (*x, y))
            .try_for_each(|(x, y)| match y {
                Ok(y) => {
                    state.push((x, y));
                    Ok(())
                }
                Err(err) => Err(err),
            })
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error reading properties",
                dev: self.dev_path(),
                source,
            })
    }

    /// Create a mapping of property names and handles for given handles of a given drm resource type.
    /// You may use this to easily lookup properties by name instead of going through this procedure manually.
    fn map_props<T>(
        &self,
        handles: &[T],
        mapping: &mut HashMap<T, HashMap<String, property::Handle>>,
    ) -> Result<(), Error>
    where
        A: AsRawFd + 'static,
        T: ResourceHandle + Eq + std::hash::Hash,
    {
        handles
            .iter()
            .map(|x| (x, self.get_properties(*x)))
            .try_for_each(|(handle, props)| {
                let mut map = HashMap::new();
                match props {
                    Ok(props) => {
                        let (prop_handles, _) = props.as_props_and_values();
                        for prop in prop_handles {
                            if let Ok(info) = self.get_property(*prop) {
                                let name = info.name().to_string_lossy().into_owned();
                                map.insert(name, *prop);
                            }
                        }
                        mapping.insert(*handle, map);
                        Ok(())
                    }
                    Err(err) => Err(err),
                }
            })
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error reading properties on {:?}",
                dev: self.dev_path(),
                source,
            })
    }
}

impl<A: AsRawFd + 'static> AtomicDrmDevice<A> {
    /// Create a new [`AtomicDrmDevice`] from an open drm node
    ///
    /// Returns an error if the file is no valid drm node or context creation was not
    /// successful.
    pub fn new<L>(fd: A, logger: L) -> Result<Self, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_drm"));
        info!(log, "AtomicDrmDevice initializing");

        let dev_id = fstat(fd.as_raw_fd())
            .map_err(|source| Error::UnableToGetDeviceId(source))?
            .st_rdev;

        let active = Arc::new(AtomicBool::new(true));
        let mut dev = Dev {
            fd,
            privileged: true,
            active: active.clone(),
            old_state: (Vec::new(), Vec::new(), Vec::new(), Vec::new()),
            prop_mapping: (HashMap::new(), HashMap::new(), HashMap::new(), HashMap::new()),
            logger: log.clone(),
        };

        // we want to modeset, so we better be the master, if we run via a tty session
        if dev.acquire_master_lock().is_err() {
            warn!(log, "Unable to become drm master, assuming unprivileged mode");
            dev.privileged = false;
        };

        // enable the features we need
        dev.set_client_capability(ClientCapability::UniversalPlanes, true)
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error enabling UniversalPlanes",
                dev: dev.dev_path(),
                source,
            })?;
        dev.set_client_capability(ClientCapability::Atomic, true)
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error enabling AtomicModesetting",
                dev: dev.dev_path(),
                source,
            })?;

        // enumerate (and save) the current device state
        let res_handles = ControlDevice::resource_handles(&dev)
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error loading drm resources",
                dev: dev.dev_path(),
                source,
            })?;

        let plane_handles = dev.plane_handles().compat().map_err(|source| Error::Access {
            errmsg: "Error loading planes",
            dev: dev.dev_path(),
            source,
        })?;
        let planes = plane_handles.planes();

        let mut old_state = dev.old_state.clone();
        let mut mapping = dev.prop_mapping.clone();

        dev.add_props(res_handles.connectors(), &mut old_state.0)?;
        dev.add_props(res_handles.crtcs(), &mut old_state.1)?;
        dev.add_props(res_handles.framebuffers(), &mut old_state.2)?;
        dev.add_props(planes, &mut old_state.3)?;

        dev.map_props(res_handles.connectors(), &mut mapping.0)?;
        dev.map_props(res_handles.crtcs(), &mut mapping.1)?;
        dev.map_props(res_handles.framebuffers(), &mut mapping.2)?;
        dev.map_props(planes, &mut mapping.3)?;

        dev.old_state = old_state;
        dev.prop_mapping = mapping;
        debug!(log, "Mapping: {:#?}", dev.prop_mapping);

        Ok(AtomicDrmDevice {
            dev: Rc::new(dev),
            dev_id,
            active,
            backends: Rc::new(RefCell::new(HashMap::new())),
            handler: None,
            logger: log.clone(),
        })
    }
}

impl<A: AsRawFd + 'static> AsRawFd for AtomicDrmDevice<A> {
    fn as_raw_fd(&self) -> RawFd {
        self.dev.as_raw_fd()
    }
}

impl<A: AsRawFd + 'static> BasicDevice for AtomicDrmDevice<A> {}
impl<A: AsRawFd + 'static> ControlDevice for AtomicDrmDevice<A> {}

impl<A: AsRawFd + 'static> Device for AtomicDrmDevice<A> {
    type Surface = AtomicDrmSurface<A>;

    fn device_id(&self) -> dev_t {
        self.dev_id
    }

    fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
        self.handler = Some(RefCell::new(Box::new(handler)));
    }

    fn clear_handler(&mut self) {
        let _ = self.handler.take();
    }

    fn create_surface(&mut self, crtc: crtc::Handle) -> Result<AtomicDrmSurface<A>, Error> {
        if self.backends.borrow().contains_key(&crtc) {
            return Err(Error::CrtcAlreadyInUse(crtc));
        }

        if !self.active.load(Ordering::SeqCst) {
            return Err(Error::DeviceInactive);
        }

        let backend = Rc::new(AtomicDrmSurfaceInternal::new(
            self.dev.clone(),
            crtc,
            self.logger.new(o!("crtc" => format!("{:?}", crtc))),
        )?);

        self.backends.borrow_mut().insert(crtc, Rc::downgrade(&backend));
        Ok(AtomicDrmSurface(backend))
    }

    fn process_events(&mut self) {
        match self.receive_events() {
            Ok(events) => {
                for event in events {
                    if let Event::PageFlip(event) = event {
                        trace!(self.logger, "Got event!");
                        if self.active.load(Ordering::SeqCst) {
                            if self
                                .backends
                                .borrow()
                                .get(&event.crtc)
                                .iter()
                                .flat_map(|x| x.upgrade())
                                .next()
                                .is_some()
                            {
                                trace!(self.logger, "Handling event for backend {:?}", event.crtc);
                                if let Some(handler) = self.handler.as_ref() {
                                    handler.borrow_mut().vblank(event.crtc);
                                }
                            } else {
                                self.backends.borrow_mut().remove(&event.crtc);
                            }
                        } else {
                            debug!(self.logger, "Device not active. Ignoring PageFlip");
                        }
                    } else {
                        trace!(self.logger, "Unrelated event");
                    }
                }
            }
            Err(source) => {
                if let Some(handler) = self.handler.as_ref() {
                    handler.borrow_mut().error(Error::Access {
                        errmsg: "Error processing drm events",
                        dev: self.dev_path(),
                        source: source.compat(),
                    });
                }
            }
        }
    }

    fn resource_handles(&self) -> Result<ResourceHandles, Error> {
        ControlDevice::resource_handles(self)
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error loading resource info",
                dev: self.dev_path(),
                source,
            })
    }

    fn get_connector_info(&self, conn: connector::Handle) -> Result<connector::Info, DrmError> {
        self.get_connector(conn)
    }
    fn get_crtc_info(&self, crtc: crtc::Handle) -> Result<crtc::Info, DrmError> {
        self.get_crtc(crtc)
    }
    fn get_encoder_info(&self, enc: encoder::Handle) -> Result<encoder::Info, DrmError> {
        self.get_encoder(enc)
    }
    fn get_framebuffer_info(&self, fb: framebuffer::Handle) -> Result<framebuffer::Info, DrmError> {
        self.get_framebuffer(fb)
    }
    fn get_plane_info(&self, plane: plane::Handle) -> Result<plane::Info, DrmError> {
        self.get_plane(plane)
    }
}

impl<A: AsRawFd + 'static> RawDevice for AtomicDrmDevice<A> {
    type Surface = AtomicDrmSurface<A>;
}

impl<A: AsRawFd + 'static> Drop for AtomicDrmDevice<A> {
    fn drop(&mut self) {
        self.clear_handler();
    }
}
<commit_msg>atomic: flesh out trace logs<commit_after>//!
//! [`RawDevice`](RawDevice) and [`RawSurface`](RawSurface)
//! implementations using the atomic mode-setting infrastructure.
//!
//! Usually this implementation will wrapped into a [`GbmDevice`](::backend::drm::gbm::GbmDevice).
//! Take a look at `anvil`s source code for an example of this.
//!
//! For an example how to use this standalone, take a look at the raw_atomic_drm example.
//!

use std::cell::RefCell;
use std::collections::HashMap;
use std::os::unix::io::{AsRawFd, RawFd};
use std::rc::{Rc, Weak};
use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};

use drm::control::{atomic::AtomicModeReq, AtomicCommitFlags, Device as ControlDevice, Event};
use drm::control::{
    connector, crtc, encoder, framebuffer, plane, property, PropertyValueSet, ResourceHandle, ResourceHandles,
};
use drm::SystemError as DrmError;
use drm::{ClientCapability, Device as BasicDevice};
use failure::{Fail, ResultExt};
use nix::libc::dev_t;
use nix::sys::stat::fstat;

use super::{common::Error, DevPath, Device, DeviceHandler, RawDevice};

mod surface;
pub use self::surface::AtomicDrmSurface;
use self::surface::AtomicDrmSurfaceInternal;

#[cfg(feature = "backend_session")]
pub mod session;

/// Open raw drm device utilizing atomic mode-setting
pub struct AtomicDrmDevice<A: AsRawFd + 'static> {
    dev: Rc<Dev<A>>,
    dev_id: dev_t,
    active: Arc<AtomicBool>,
    backends: Rc<RefCell<HashMap<crtc::Handle, Weak<AtomicDrmSurfaceInternal<A>>>>>,
    handler: Option<RefCell<Box<dyn DeviceHandler<Device = AtomicDrmDevice<A>>>>>,
    logger: ::slog::Logger,
}

type OldState = (
    Vec<(connector::Handle, PropertyValueSet)>,
    Vec<(crtc::Handle, PropertyValueSet)>,
    Vec<(framebuffer::Handle, PropertyValueSet)>,
    Vec<(plane::Handle, PropertyValueSet)>,
);

type Mapping = (
    HashMap<connector::Handle, HashMap<String, property::Handle>>,
    HashMap<crtc::Handle, HashMap<String, property::Handle>>,
    HashMap<framebuffer::Handle, HashMap<String, property::Handle>>,
    HashMap<plane::Handle, HashMap<String, property::Handle>>,
);

struct Dev<A: AsRawFd + 'static> {
    fd: A,
    privileged: bool,
    active: Arc<AtomicBool>,
    old_state: OldState,
    prop_mapping: Mapping,
    logger: ::slog::Logger,
}

impl<A: AsRawFd + 'static> AsRawFd for Dev<A> {
    fn as_raw_fd(&self) -> RawFd {
        self.fd.as_raw_fd()
    }
}
impl<A: AsRawFd + 'static> BasicDevice for Dev<A> {}
impl<A: AsRawFd + 'static> ControlDevice for Dev<A> {}
impl<A: AsRawFd + 'static> Drop for Dev<A> {
    fn drop(&mut self) {
        info!(self.logger, "Dropping device: {:?}", self.dev_path());
        if self.active.load(Ordering::SeqCst) {
            // Here we restore the card/tty's to it's previous state.
            // In case e.g. getty was running on the tty sets the correct framebuffer again,
            // so that getty will be visible.

            let mut req = AtomicModeReq::new();

            fn add_multiple_props<T: ResourceHandle>(
                req: &mut AtomicModeReq,
                old_state: &[(T, PropertyValueSet)],
            ) {
                for (handle, set) in old_state {
                    let (prop_handles, values) = set.as_props_and_values();
                    for (&prop_handle, &val) in prop_handles.iter().zip(values.iter()) {
                        req.add_raw_property((*handle).into(), prop_handle, val);
                    }
                }
            };

            add_multiple_props(&mut req, &self.old_state.0);
            add_multiple_props(&mut req, &self.old_state.1);
            add_multiple_props(&mut req, &self.old_state.2);
            add_multiple_props(&mut req, &self.old_state.3);

            if let Err(err) = self.atomic_commit(&[AtomicCommitFlags::AllowModeset], req) {
                error!(self.logger, "Failed to restore previous state. Error: {}", err);
            }
        }
        if self.privileged {
            if let Err(err) = self.release_master_lock() {
                error!(self.logger, "Failed to drop drm master state. Error: {}", err);
            }
        }
    }
}

impl<A: AsRawFd + 'static> Dev<A> {
    // Add all properties of given handles to a given drm resource type to state.
    // You may use this to snapshot the current state of the drm device (fully or partially).
    fn add_props<T>(&self, handles: &[T], state: &mut Vec<(T, PropertyValueSet)>) -> Result<(), Error>
    where
        A: AsRawFd + 'static,
        T: ResourceHandle,
    {
        let iter = handles.iter().map(|x| (x, self.get_properties(*x)));
        if let Some(len) = iter.size_hint().1 {
            state.reserve_exact(len)
        }

        iter.map(|(x, y)| (*x, y))
            .try_for_each(|(x, y)| match y {
                Ok(y) => {
                    state.push((x, y));
                    Ok(())
                }
                Err(err) => Err(err),
            })
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error reading properties",
                dev: self.dev_path(),
                source,
            })
    }

    /// Create a mapping of property names and handles for given handles of a given drm resource type.
    /// You may use this to easily lookup properties by name instead of going through this procedure manually.
    fn map_props<T>(
        &self,
        handles: &[T],
        mapping: &mut HashMap<T, HashMap<String, property::Handle>>,
    ) -> Result<(), Error>
    where
        A: AsRawFd + 'static,
        T: ResourceHandle + Eq + std::hash::Hash,
    {
        handles
            .iter()
            .map(|x| (x, self.get_properties(*x)))
            .try_for_each(|(handle, props)| {
                let mut map = HashMap::new();
                match props {
                    Ok(props) => {
                        let (prop_handles, _) = props.as_props_and_values();
                        for prop in prop_handles {
                            if let Ok(info) = self.get_property(*prop) {
                                let name = info.name().to_string_lossy().into_owned();
                                map.insert(name, *prop);
                            }
                        }
                        mapping.insert(*handle, map);
                        Ok(())
                    }
                    Err(err) => Err(err),
                }
            })
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error reading properties on {:?}",
                dev: self.dev_path(),
                source,
            })
    }
}

impl<A: AsRawFd + 'static> AtomicDrmDevice<A> {
    /// Create a new [`AtomicDrmDevice`] from an open drm node
    ///
    /// Returns an error if the file is no valid drm node or context creation was not
    /// successful.
    pub fn new<L>(fd: A, logger: L) -> Result<Self, Error>
    where
        L: Into<Option<::slog::Logger>>,
    {
        let log = crate::slog_or_stdlog(logger).new(o!("smithay_module" => "backend_drm"));
        info!(log, "AtomicDrmDevice initializing");

        let dev_id = fstat(fd.as_raw_fd())
            .map_err(|source| Error::UnableToGetDeviceId(source))?
            .st_rdev;

        let active = Arc::new(AtomicBool::new(true));
        let mut dev = Dev {
            fd,
            privileged: true,
            active: active.clone(),
            old_state: (Vec::new(), Vec::new(), Vec::new(), Vec::new()),
            prop_mapping: (HashMap::new(), HashMap::new(), HashMap::new(), HashMap::new()),
            logger: log.clone(),
        };

        // we want to modeset, so we better be the master, if we run via a tty session
        if dev.acquire_master_lock().is_err() {
            warn!(log, "Unable to become drm master, assuming unprivileged mode");
            dev.privileged = false;
        };

        // enable the features we need
        dev.set_client_capability(ClientCapability::UniversalPlanes, true)
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error enabling UniversalPlanes",
                dev: dev.dev_path(),
                source,
            })?;
        dev.set_client_capability(ClientCapability::Atomic, true)
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error enabling AtomicModesetting",
                dev: dev.dev_path(),
                source,
            })?;

        // enumerate (and save) the current device state
        let res_handles = ControlDevice::resource_handles(&dev)
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error loading drm resources",
                dev: dev.dev_path(),
                source,
            })?;

        let plane_handles = dev.plane_handles().compat().map_err(|source| Error::Access {
            errmsg: "Error loading planes",
            dev: dev.dev_path(),
            source,
        })?;
        let planes = plane_handles.planes();

        let mut old_state = dev.old_state.clone();
        let mut mapping = dev.prop_mapping.clone();

        dev.add_props(res_handles.connectors(), &mut old_state.0)?;
        dev.add_props(res_handles.crtcs(), &mut old_state.1)?;
        dev.add_props(res_handles.framebuffers(), &mut old_state.2)?;
        dev.add_props(planes, &mut old_state.3)?;

        dev.map_props(res_handles.connectors(), &mut mapping.0)?;
        dev.map_props(res_handles.crtcs(), &mut mapping.1)?;
        dev.map_props(res_handles.framebuffers(), &mut mapping.2)?;
        dev.map_props(planes, &mut mapping.3)?;

        dev.old_state = old_state;
        dev.prop_mapping = mapping;
        debug!(log, "Mapping: {:#?}", dev.prop_mapping);

        Ok(AtomicDrmDevice {
            dev: Rc::new(dev),
            dev_id,
            active,
            backends: Rc::new(RefCell::new(HashMap::new())),
            handler: None,
            logger: log.clone(),
        })
    }
}

impl<A: AsRawFd + 'static> AsRawFd for AtomicDrmDevice<A> {
    fn as_raw_fd(&self) -> RawFd {
        self.dev.as_raw_fd()
    }
}

impl<A: AsRawFd + 'static> BasicDevice for AtomicDrmDevice<A> {}
impl<A: AsRawFd + 'static> ControlDevice for AtomicDrmDevice<A> {}

impl<A: AsRawFd + 'static> Device for AtomicDrmDevice<A> {
    type Surface = AtomicDrmSurface<A>;

    fn device_id(&self) -> dev_t {
        self.dev_id
    }

    fn set_handler(&mut self, handler: impl DeviceHandler<Device = Self> + 'static) {
        self.handler = Some(RefCell::new(Box::new(handler)));
    }

    fn clear_handler(&mut self) {
        let _ = self.handler.take();
    }

    fn create_surface(&mut self, crtc: crtc::Handle) -> Result<AtomicDrmSurface<A>, Error> {
        if self.backends.borrow().contains_key(&crtc) {
            return Err(Error::CrtcAlreadyInUse(crtc));
        }

        if !self.active.load(Ordering::SeqCst) {
            return Err(Error::DeviceInactive);
        }

        let backend = Rc::new(AtomicDrmSurfaceInternal::new(
            self.dev.clone(),
            crtc,
            self.logger.new(o!("crtc" => format!("{:?}", crtc))),
        )?);

        self.backends.borrow_mut().insert(crtc, Rc::downgrade(&backend));
        Ok(AtomicDrmSurface(backend))
    }

    fn process_events(&mut self) {
        match self.receive_events() {
            Ok(events) => {
                for event in events {
                    if let Event::PageFlip(event) = event {
                        trace!(self.logger, "Got a page-flip event for crtc ({:?})", event.crtc);
                        if self.active.load(Ordering::SeqCst) {
                            if self
                                .backends
                                .borrow()
                                .get(&event.crtc)
                                .iter()
                                .flat_map(|x| x.upgrade())
                                .next()
                                .is_some()
                            {
                                trace!(self.logger, "Handling event for backend {:?}", event.crtc);
                                if let Some(handler) = self.handler.as_ref() {
                                    handler.borrow_mut().vblank(event.crtc);
                                }
                            } else {
                                self.backends.borrow_mut().remove(&event.crtc);
                            }
                        } else {
                            debug!(
                                self.logger,
                                "Device ({:?}) not active. Ignoring PageFlip",
                                self.dev_path()
                            );
                        }
                    } else {
                        trace!(
                            self.logger,
                            "Got a non-page-flip event of device '{:?}'.",
                            self.dev_path()
                        );
                    }
                }
            }
            Err(source) => {
                if let Some(handler) = self.handler.as_ref() {
                    handler.borrow_mut().error(Error::Access {
                        errmsg: "Error processing drm events",
                        dev: self.dev_path(),
                        source: source.compat(),
                    });
                }
            }
        }
    }

    fn resource_handles(&self) -> Result<ResourceHandles, Error> {
        ControlDevice::resource_handles(self)
            .compat()
            .map_err(|source| Error::Access {
                errmsg: "Error loading resource info",
                dev: self.dev_path(),
                source,
            })
    }

    fn get_connector_info(&self, conn: connector::Handle) -> Result<connector::Info, DrmError> {
        self.get_connector(conn)
    }
    fn get_crtc_info(&self, crtc: crtc::Handle) -> Result<crtc::Info, DrmError> {
        self.get_crtc(crtc)
    }
    fn get_encoder_info(&self, enc: encoder::Handle) -> Result<encoder::Info, DrmError> {
        self.get_encoder(enc)
    }
    fn get_framebuffer_info(&self, fb: framebuffer::Handle) -> Result<framebuffer::Info, DrmError> {
        self.get_framebuffer(fb)
    }
    fn get_plane_info(&self, plane: plane::Handle) -> Result<plane::Info, DrmError> {
        self.get_plane(plane)
    }
}

impl<A: AsRawFd + 'static> RawDevice for AtomicDrmDevice<A> {
    type Surface = AtomicDrmSurface<A>;
}

impl<A: AsRawFd + 'static> Drop for AtomicDrmDevice<A> {
    fn drop(&mut self) {
        self.clear_handler();
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::path;

use crate::bindgen::bindings::Bindings;
use crate::bindgen::cargo::Cargo;
use crate::bindgen::config::{Braces, Config, Language};
use crate::bindgen::error::Error;
use crate::bindgen::library::Library;
use crate::bindgen::parser::{self, Parse};

/// A builder for generating a bindings header.
#[derive(Debug, Clone)]
pub struct Builder {
    config: Config,
    srcs: Vec<path::PathBuf>,
    lib: Option<(path::PathBuf, Option<String>)>,
    lib_cargo: Option<Cargo>,
    std_types: bool,
    lockfile: Option<path::PathBuf>,
}

impl Builder {
    #[allow(clippy::new_without_default)]
    pub fn new() -> Builder {
        Builder {
            config: Config::default(),
            srcs: Vec::new(),
            lib: None,
            lib_cargo: None,
            std_types: true,
            lockfile: None,
        }
    }

    #[allow(unused)]
    pub fn with_header<S: AsRef<str>>(mut self, header: S) -> Builder {
        self.config.header = Some(String::from(header.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_no_includes(mut self) -> Builder {
        self.config.no_includes = true;
        self
    }

    #[allow(unused)]
    pub fn with_include<S: AsRef<str>>(mut self, include: S) -> Builder {
        self.config.includes.push(String::from(include.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_sys_include<S: AsRef<str>>(mut self, include: S) -> Builder {
        self.config
            .sys_includes
            .push(String::from(include.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_after_include<S: AsRef<str>>(mut self, line: S) -> Builder {
        self.config.after_includes = Some(String::from(line.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_trailer<S: AsRef<str>>(mut self, trailer: S) -> Builder {
        self.config.trailer = Some(String::from(trailer.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_include_guard<S: AsRef<str>>(mut self, include_guard: S) -> Builder {
        self.config.include_guard = Some(String::from(include_guard.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_pragma_once(mut self, pragma_once: bool) -> Builder {
        self.config.pragma_once = pragma_once;
        self
    }

    #[allow(unused)]
    pub fn with_autogen_warning<S: AsRef<str>>(mut self, autogen_warning: S) -> Builder {
        self.config.autogen_warning = Some(String::from(autogen_warning.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_include_version(mut self, include_version: bool) -> Builder {
        self.config.include_version = include_version;
        self
    }

    #[allow(unused)]
    pub fn with_namespace<S: AsRef<str>>(mut self, namespace: S) -> Builder {
        self.config.namespace = Some(String::from(namespace.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_namespaces<S: AsRef<str>>(mut self, namespaces: &[S]) -> Builder {
        self.config.namespaces = Some(
            namespaces
                .iter()
                .map(|x| String::from(x.as_ref()))
                .collect(),
        );
        self
    }

    #[allow(unused)]
    pub fn with_braces(mut self, braces: Braces) -> Builder {
        self.config.braces = braces;
        self
    }

    #[allow(unused)]
    pub fn with_line_length(mut self, line_length: usize) -> Builder {
        self.config.line_length = line_length;
        self
    }

    #[allow(unused)]
    pub fn with_tab_width(mut self, tab_width: usize) -> Builder {
        self.config.tab_width = tab_width;
        self
    }

    #[allow(unused)]
    pub fn with_language(mut self, language: Language) -> Builder {
        self.config.language = language;
        self
    }

    #[allow(unused)]
    pub fn include_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
        self.config
            .export
            .include
            .push(String::from(item_name.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn exclude_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
        self.config
            .export
            .exclude
            .push(String::from(item_name.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn rename_item<S: AsRef<str>>(mut self, from: S, to: S) -> Builder {
        self.config
            .export
            .rename
            .insert(String::from(from.as_ref()), String::from(to.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_item_prefix<S: AsRef<str>>(mut self, prefix: S) -> Builder {
        self.config.export.prefix = Some(String::from(prefix.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_parse_deps(mut self, parse_deps: bool) -> Builder {
        self.config.parse.parse_deps = parse_deps;
        self
    }

    #[allow(unused)]
    pub fn with_parse_include<S: AsRef<str>>(mut self, include: &[S]) -> Builder {
        self.config.parse.include =
            Some(include.iter().map(|x| String::from(x.as_ref())).collect());
        self
    }

    #[allow(unused)]
    pub fn with_parse_exclude<S: AsRef<str>>(mut self, exclude: &[S]) -> Builder {
        self.config.parse.exclude = exclude.iter().map(|x| String::from(x.as_ref())).collect();
        self
    }

    #[allow(unused)]
    pub fn with_parse_expand<S: AsRef<str>>(mut self, expand: &[S]) -> Builder {
        self.config.parse.expand.crates = expand.iter().map(|x| String::from(x.as_ref())).collect();
        self
    }

    #[allow(unused)]
    pub fn with_parse_expand_all_features(mut self, expand_all_features: bool) -> Builder {
        self.config.parse.expand.all_features = expand_all_features;
        self
    }

    #[allow(unused)]
    pub fn with_parse_expand_default_features(mut self, expand_default_features: bool) -> Builder {
        self.config.parse.expand.default_features = expand_default_features;
        self
    }

    #[allow(unused)]
    pub fn with_parse_expand_features<S: AsRef<str>>(mut self, expand_features: &[S]) -> Builder {
        self.config.parse.expand.features = Some(
            expand_features
                .iter()
                .map(|x| String::from(x.as_ref()))
                .collect(),
        );
        self
    }

    #[allow(unused)]
    pub fn with_documentation(mut self, documentation: bool) -> Builder {
        self.config.documentation = documentation;
        self
    }

    #[allow(unused)]
    pub fn with_target_os_define(mut self, platform: &str, preprocessor_define: &str) -> Builder {
        self.config.defines.insert(
            format!("target_os = {}", platform),
            preprocessor_define.to_owned(),
        );
        self
    }

    #[allow(unused)]
    pub fn with_define(mut self, key: &str, value: &str, preprocessor_define: &str) -> Builder {
        self.config.defines.insert(
            format!("{} = {}", key, value),
            preprocessor_define.to_owned(),
        );
        self
    }

    #[allow(unused)]
    pub fn with_config(mut self, config: Config) -> Builder {
        self.config = config;
        self
    }

    #[allow(unused)]
    pub fn with_std_types(mut self, std_types: bool) -> Builder {
        self.std_types = std_types;
        self
    }

    #[allow(unused)]
    pub fn with_src<P: AsRef<path::Path>>(mut self, src: P) -> Builder {
        self.srcs.push(src.as_ref().to_owned());
        self
    }

    #[allow(unused)]
    pub fn with_crate<P: AsRef<path::Path>>(mut self, lib_dir: P) -> Builder {
        debug_assert!(self.lib.is_none());
        debug_assert!(self.lib_cargo.is_none());
        self.lib = Some((path::PathBuf::from(lib_dir.as_ref()), None));
        self
    }

    #[allow(unused)]
    pub fn with_crate_and_name<P: AsRef<path::Path>, S: AsRef<str>>(
        mut self,
        lib_dir: P,
        binding_lib_name: S,
    ) -> Builder {
        debug_assert!(self.lib.is_none());
        debug_assert!(self.lib_cargo.is_none());
        self.lib = Some((
            path::PathBuf::from(lib_dir.as_ref()),
            Some(String::from(binding_lib_name.as_ref())),
        ));
        self
    }

    #[allow(unused)]
    pub(crate) fn with_cargo(mut self, lib: Cargo) -> Builder {
        debug_assert!(self.lib.is_none());
        debug_assert!(self.lib_cargo.is_none());
        self.lib_cargo = Some(lib);
        self
    }

    #[allow(unused)]
    pub fn with_lockfile<P: AsRef<path::Path>>(mut self, lockfile: P) -> Builder {
        debug_assert!(self.lockfile.is_none());
        debug_assert!(self.lib_cargo.is_none());
        self.lockfile = Some(path::PathBuf::from(lockfile.as_ref()));
        self
    }

    pub fn generate(self) -> Result<Bindings, Error> {
        let mut result = Parse::new();

        if self.std_types {
            result.add_std_types();
        }

        for x in &self.srcs {
            result.extend_with(&parser::parse_src(x, &self.config)?);
        }

        if let Some((lib_dir, binding_lib_name)) = self.lib.clone() {
            let lockfile = self.lockfile.as_ref().and_then(|p| p.to_str());

            let cargo = Cargo::load(
                &lib_dir,
                lockfile,
                binding_lib_name.as_deref(),
                self.config.parse.parse_deps,
                self.config.parse.clean,
                /* existing_metadata = */ None,
            )?;

            result.extend_with(&parser::parse_lib(cargo, &self.config)?);
        } else if let Some(cargo) = self.lib_cargo.clone() {
            result.extend_with(&parser::parse_lib(cargo, &self.config)?);
        }

        Library::new(
            self.config,
            result.constants,
            result.globals,
            result.enums,
            result.structs,
            result.unions,
            result.opaque_items,
            result.typedefs,
            result.functions,
        )
        .generate()
    }
}
<commit_msg>Add missing function `with_style` to the Builder<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::path;

use crate::bindgen::bindings::Bindings;
use crate::bindgen::cargo::Cargo;
use crate::bindgen::config::{Braces, Config, Language, Style};
use crate::bindgen::error::Error;
use crate::bindgen::library::Library;
use crate::bindgen::parser::{self, Parse};

/// A builder for generating a bindings header.
#[derive(Debug, Clone)]
pub struct Builder {
    config: Config,
    srcs: Vec<path::PathBuf>,
    lib: Option<(path::PathBuf, Option<String>)>,
    lib_cargo: Option<Cargo>,
    std_types: bool,
    lockfile: Option<path::PathBuf>,
}

impl Builder {
    #[allow(clippy::new_without_default)]
    pub fn new() -> Builder {
        Builder {
            config: Config::default(),
            srcs: Vec::new(),
            lib: None,
            lib_cargo: None,
            std_types: true,
            lockfile: None,
        }
    }

    #[allow(unused)]
    pub fn with_header<S: AsRef<str>>(mut self, header: S) -> Builder {
        self.config.header = Some(String::from(header.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_no_includes(mut self) -> Builder {
        self.config.no_includes = true;
        self
    }

    #[allow(unused)]
    pub fn with_include<S: AsRef<str>>(mut self, include: S) -> Builder {
        self.config.includes.push(String::from(include.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_sys_include<S: AsRef<str>>(mut self, include: S) -> Builder {
        self.config
            .sys_includes
            .push(String::from(include.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_after_include<S: AsRef<str>>(mut self, line: S) -> Builder {
        self.config.after_includes = Some(String::from(line.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_trailer<S: AsRef<str>>(mut self, trailer: S) -> Builder {
        self.config.trailer = Some(String::from(trailer.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_include_guard<S: AsRef<str>>(mut self, include_guard: S) -> Builder {
        self.config.include_guard = Some(String::from(include_guard.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_pragma_once(mut self, pragma_once: bool) -> Builder {
        self.config.pragma_once = pragma_once;
        self
    }

    #[allow(unused)]
    pub fn with_autogen_warning<S: AsRef<str>>(mut self, autogen_warning: S) -> Builder {
        self.config.autogen_warning = Some(String::from(autogen_warning.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_include_version(mut self, include_version: bool) -> Builder {
        self.config.include_version = include_version;
        self
    }

    #[allow(unused)]
    pub fn with_namespace<S: AsRef<str>>(mut self, namespace: S) -> Builder {
        self.config.namespace = Some(String::from(namespace.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_namespaces<S: AsRef<str>>(mut self, namespaces: &[S]) -> Builder {
        self.config.namespaces = Some(
            namespaces
                .iter()
                .map(|x| String::from(x.as_ref()))
                .collect(),
        );
        self
    }

    #[allow(unused)]
    pub fn with_braces(mut self, braces: Braces) -> Builder {
        self.config.braces = braces;
        self
    }

    #[allow(unused)]
    pub fn with_line_length(mut self, line_length: usize) -> Builder {
        self.config.line_length = line_length;
        self
    }

    #[allow(unused)]
    pub fn with_tab_width(mut self, tab_width: usize) -> Builder {
        self.config.tab_width = tab_width;
        self
    }

    #[allow(unused)]
    pub fn with_language(mut self, language: Language) -> Builder {
        self.config.language = language;
        self
    }

    #[allow(unused)]
    pub fn with_style(mut self, style: Style) -> Builder {
        self.config.style = style;
        self
    }

    #[allow(unused)]
    pub fn include_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
        self.config
            .export
            .include
            .push(String::from(item_name.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn exclude_item<S: AsRef<str>>(mut self, item_name: S) -> Builder {
        self.config
            .export
            .exclude
            .push(String::from(item_name.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn rename_item<S: AsRef<str>>(mut self, from: S, to: S) -> Builder {
        self.config
            .export
            .rename
            .insert(String::from(from.as_ref()), String::from(to.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_item_prefix<S: AsRef<str>>(mut self, prefix: S) -> Builder {
        self.config.export.prefix = Some(String::from(prefix.as_ref()));
        self
    }

    #[allow(unused)]
    pub fn with_parse_deps(mut self, parse_deps: bool) -> Builder {
        self.config.parse.parse_deps = parse_deps;
        self
    }

    #[allow(unused)]
    pub fn with_parse_include<S: AsRef<str>>(mut self, include: &[S]) -> Builder {
        self.config.parse.include =
            Some(include.iter().map(|x| String::from(x.as_ref())).collect());
        self
    }

    #[allow(unused)]
    pub fn with_parse_exclude<S: AsRef<str>>(mut self, exclude: &[S]) -> Builder {
        self.config.parse.exclude = exclude.iter().map(|x| String::from(x.as_ref())).collect();
        self
    }

    #[allow(unused)]
    pub fn with_parse_expand<S: AsRef<str>>(mut self, expand: &[S]) -> Builder {
        self.config.parse.expand.crates = expand.iter().map(|x| String::from(x.as_ref())).collect();
        self
    }

    #[allow(unused)]
    pub fn with_parse_expand_all_features(mut self, expand_all_features: bool) -> Builder {
        self.config.parse.expand.all_features = expand_all_features;
        self
    }

    #[allow(unused)]
    pub fn with_parse_expand_default_features(mut self, expand_default_features: bool) -> Builder {
        self.config.parse.expand.default_features = expand_default_features;
        self
    }

    #[allow(unused)]
    pub fn with_parse_expand_features<S: AsRef<str>>(mut self, expand_features: &[S]) -> Builder {
        self.config.parse.expand.features = Some(
            expand_features
                .iter()
                .map(|x| String::from(x.as_ref()))
                .collect(),
        );
        self
    }

    #[allow(unused)]
    pub fn with_documentation(mut self, documentation: bool) -> Builder {
        self.config.documentation = documentation;
        self
    }

    #[allow(unused)]
    pub fn with_target_os_define(mut self, platform: &str, preprocessor_define: &str) -> Builder {
        self.config.defines.insert(
            format!("target_os = {}", platform),
            preprocessor_define.to_owned(),
        );
        self
    }

    #[allow(unused)]
    pub fn with_define(mut self, key: &str, value: &str, preprocessor_define: &str) -> Builder {
        self.config.defines.insert(
            format!("{} = {}", key, value),
            preprocessor_define.to_owned(),
        );
        self
    }

    #[allow(unused)]
    pub fn with_config(mut self, config: Config) -> Builder {
        self.config = config;
        self
    }

    #[allow(unused)]
    pub fn with_std_types(mut self, std_types: bool) -> Builder {
        self.std_types = std_types;
        self
    }

    #[allow(unused)]
    pub fn with_src<P: AsRef<path::Path>>(mut self, src: P) -> Builder {
        self.srcs.push(src.as_ref().to_owned());
        self
    }

    #[allow(unused)]
    pub fn with_crate<P: AsRef<path::Path>>(mut self, lib_dir: P) -> Builder {
        debug_assert!(self.lib.is_none());
        debug_assert!(self.lib_cargo.is_none());
        self.lib = Some((path::PathBuf::from(lib_dir.as_ref()), None));
        self
    }

    #[allow(unused)]
    pub fn with_crate_and_name<P: AsRef<path::Path>, S: AsRef<str>>(
        mut self,
        lib_dir: P,
        binding_lib_name: S,
    ) -> Builder {
        debug_assert!(self.lib.is_none());
        debug_assert!(self.lib_cargo.is_none());
        self.lib = Some((
            path::PathBuf::from(lib_dir.as_ref()),
            Some(String::from(binding_lib_name.as_ref())),
        ));
        self
    }

    #[allow(unused)]
    pub(crate) fn with_cargo(mut self, lib: Cargo) -> Builder {
        debug_assert!(self.lib.is_none());
        debug_assert!(self.lib_cargo.is_none());
        self.lib_cargo = Some(lib);
        self
    }

    #[allow(unused)]
    pub fn with_lockfile<P: AsRef<path::Path>>(mut self, lockfile: P) -> Builder {
        debug_assert!(self.lockfile.is_none());
        debug_assert!(self.lib_cargo.is_none());
        self.lockfile = Some(path::PathBuf::from(lockfile.as_ref()));
        self
    }

    pub fn generate(self) -> Result<Bindings, Error> {
        let mut result = Parse::new();

        if self.std_types {
            result.add_std_types();
        }

        for x in &self.srcs {
            result.extend_with(&parser::parse_src(x, &self.config)?);
        }

        if let Some((lib_dir, binding_lib_name)) = self.lib.clone() {
            let lockfile = self.lockfile.as_ref().and_then(|p| p.to_str());

            let cargo = Cargo::load(
                &lib_dir,
                lockfile,
                binding_lib_name.as_deref(),
                self.config.parse.parse_deps,
                self.config.parse.clean,
                /* existing_metadata = */ None,
            )?;

            result.extend_with(&parser::parse_lib(cargo, &self.config)?);
        } else if let Some(cargo) = self.lib_cargo.clone() {
            result.extend_with(&parser::parse_lib(cargo, &self.config)?);
        }

        Library::new(
            self.config,
            result.constants,
            result.globals,
            result.enums,
            result.structs,
            result.unions,
            result.opaque_items,
            result.typedefs,
            result.functions,
        )
        .generate()
    }
}

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

    #[test]
    fn with_style() {
        assert_eq!(
            Style::Tag,
            Builder::new().with_style(Style::Tag).config.style
        );
    }
}
<|endoftext|>


<commit_before>use std::sync::{Arc, RwLock};
use std::option::Option;

use uuid::Uuid;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

pub struct CellFormat {
    name: String,
    type_: CellType
}

pub struct RecFormat {
    cols: Vec<CellFormat>
}

trait Metaformat<T> {
    fn construct(format_: CellFormat) -> T;
}

//impl Metaformat<Cell> for Cell {
//    fn construct(format_: CellFormat) -> Cell {
//        return match format_.type_ {
//            CellType::Int32(_) => Cell { value: CellType::Int32(None) },
//            CellType::Int64(_) => Cell { value: CellType::Int64(None) },
//            CellType::Text(_) => Cell { value: CellType::Text(None) }
//        }
//    }
//}

trait Container<T> {
    fn size(&self) -> usize;
    fn push(&mut self, item: T);
    //fn remove
}

pub struct Rec {
    pub guid: Uuid,
    pub cells: Vec<CellType>,
    pub format: Arc<RwLock<RecFormat>>
}

pub fn construct_rec(format: Arc<RwLock<RecFormat>>) -> Rec {
    let cells = format.read().unwrap().cols.iter().map(|x| x.type_).collect::<Vec<CellType>>();
    return Rec{guid: Uuid::new_v4(),
        cells: cells,
        format: format}
}

//impl Container<Cell> for Rec {

//    fn size(&self) -> usize {
//        return self.cells.len();
//    }

//    fn push(&mut self, item: Cell) {
//        self.cells.push(item);
//    }
//}

pub struct Table {
    pub name: String,
    pub rows: Vec<Rec>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Container<Rec> for Table {
    fn size(&self) -> usize {
        return self.rows.len();
    }

    fn push(&mut self, item: Rec) {
        self.rows.push(item);
    }
}
<commit_msg>Make fields public<commit_after>use std::sync::{Arc, RwLock};
use std::option::Option;

use uuid::Uuid;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

pub struct CellFormat {
    pub name: String,
    pub type_: CellType
}

pub struct RecFormat {
    pub cols: Vec<CellFormat>
}

trait Metaformat<T> {
    fn construct(format_: CellFormat) -> T;
}

//impl Metaformat<Cell> for Cell {
//    fn construct(format_: CellFormat) -> Cell {
//        return match format_.type_ {
//            CellType::Int32(_) => Cell { value: CellType::Int32(None) },
//            CellType::Int64(_) => Cell { value: CellType::Int64(None) },
//            CellType::Text(_) => Cell { value: CellType::Text(None) }
//        }
//    }
//}

trait Container<T> {
    fn size(&self) -> usize;
    fn push(&mut self, item: T);
    //fn remove
}

pub struct Rec {
    pub guid: Uuid,
    pub cells: Vec<CellType>,
    pub format: Arc<RwLock<RecFormat>>
}

pub fn construct_rec(format: Arc<RwLock<RecFormat>>) -> Rec {
    let cells = format.read().unwrap().cols.iter().map(|x| x.type_).collect::<Vec<CellType>>();
    return Rec{guid: Uuid::new_v4(),
        cells: cells,
        format: format}
}

//impl Container<Cell> for Rec {

//    fn size(&self) -> usize {
//        return self.cells.len();
//    }

//    fn push(&mut self, item: Cell) {
//        self.cells.push(item);
//    }
//}

pub struct Table {
    pub name: String,
    pub rows: Vec<Rec>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Container<Rec> for Table {
    fn size(&self) -> usize {
        return self.rows.len();
    }

    fn push(&mut self, item: Rec) {
        self.rows.push(item);
    }
}
<|endoftext|>