<commit_before>use std::fmt;

// TODO: figure out how to use failure for error (or some other pattern)
#[derive(Debug)]
pub enum Error {
    NotAnInstruction,
    LongInstruction,
}

/// FlowMeta is metadata that describes code flow for an instruction.
///
/// The metadata is packed into a single byte, with the expectation that,
///  there may be one `FlowMeta` instance for each (code) offset in a program.
/// However, the you should not be worried about the representation, just the interface.
#[derive(Debug, Clone)]
pub struct FlowMeta(u8);

impl FlowMeta {
    pub fn zero() -> FlowMeta {
        FlowMeta(0x0)
    }

    /// Create a new FlowMeta.
    ///
    /// Args:
    ///   - insn_length: size of instruction, or 0 if not an instruction, or 0xF if 0xF or larger.
    ///   - does_fallthrough: is there a fallthrough code flow to the next instruction?
    ///   - has_xrefs_from: are there code xrefs from this instruction (non-fallthrough)?
    pub fn new(insn_length: u8, does_fallthrough: bool, has_xrefs_from: bool) -> FlowMeta {
        let len = if insn_length >= 0xF {
            // instrunction length too long
            0x0F
        } else if insn_length == 0x0 {
            // not an instruction
            0x00
        } else {
            // good flow
            insn_length & 0x0F
        };

        let fallthrough = if does_fallthrough {
            0b0001_0000
        } else {
            0b0000_0000
        };

        let xfrom = if has_xrefs_from {
            0b0010_0000
        } else {
            0b0000_0000
        };

        FlowMeta(len | fallthrough | xfrom)
    }

    /// Fetch the cached length of the instruction.
    ///
    /// If longer than 14 bytes, then will return `Error::LongInstruction` and you'll have to decode
    ///  the instruction yourself.
    ///
    /// Errors:
    ///   - NotAnInstruction
    ///   - LongInstruction
    ///
    /// ```
    /// use matches::matches;
    /// use lancelot::flowmeta::*;
    /// assert_eq!(FlowMeta::new(0x01, true, true).get_insn_length().unwrap(),
    ///            0x01);
    /// assert!(matches!(FlowMeta::new(0x00, true, true).get_insn_length().err().unwrap(),
    ///                  Error::NotAnInstruction));
    /// assert!(matches!(FlowMeta::new(0x0F, true, true).get_insn_length().err().unwrap(),
    ///                  Error::LongInstruction));
    /// ```
    pub fn get_insn_length(&self) -> Result<u8, Error> {
        let v = self.0 & 0b0000_1111;
        match v {
            0x00 => Err(Error::NotAnInstruction),
            0x0F => Err(Error::LongInstruction),
            v @ _ => Ok(v)
        }
    }

    /// Does the instruction fallthrough?
    pub fn does_fallthrough(&self) -> bool {
        self.0 & 0b0001_0000 > 0
    }

    /// Does the instruction have flow xrefs from it?
    /// This does not include the fallthrough flow.
    pub fn has_xrefs_from(&self) -> bool {
        self.0 & 0b0010_0000 > 0
    }

    /// Does the instruction have flow xrefs to it?
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// assert_eq!(FlowMeta::new(0x01, false, false).has_xrefs_to(), false);
    /// ```
    pub fn has_xrefs_to(&self) -> bool {
        self.0 & 0b0100_0000 > 0
    }

    /// Set the bit indicating that there are flow xrefs to this instruction.
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// let mut m = FlowMeta::new(0x01, false, false);
    /// assert_eq!(m.has_xrefs_to(), false);
    ///
    /// m.set_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), true);
    /// ```
    pub fn set_xrefs_to(&mut self) {
        self.0 = self.0 | 0b0100_0000;
    }

    /// Unset the bit indicating that there are flow xrefs to this instruction.
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// let mut m = FlowMeta::new(0x01, false, false);
    /// assert_eq!(m.has_xrefs_to(), false);
    ///
    /// m.set_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), true);
    ///
    /// m.unset_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), false);
    /// ```
    pub fn unset_xrefs_to(&mut self) {
        self.0 = self.0 & 0b1011_1111
    }
}

impl fmt::Display for FlowMeta {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FlowMeta{{length: {}, fallthrough: {}, xrefs to: {}, xrefs from: {}}}",
               match self.get_insn_length() {
                   Ok(v) => format!("0x{:x}", v),
                   Err(Error::LongInstruction) => ">=0xF".to_string(),
                   Err(Error::NotAnInstruction) => "not an instruction".to_string(),
               },
               self.does_fallthrough(),
               self.has_xrefs_to(),
               self.has_xrefs_from())
    }
}
<commit_msg>flowmeta: add `.is_insn()` accessor<commit_after>use std::fmt;

// TODO: figure out how to use failure for error (or some other pattern)
#[derive(Debug)]
pub enum Error {
    NotAnInstruction,
    LongInstruction,
}

/// FlowMeta is metadata that describes code flow for an instruction.
///
/// The metadata is packed into a single byte, with the expectation that,
///  there may be one `FlowMeta` instance for each (code) offset in a program.
/// However, the you should not be worried about the representation, just the interface.
#[derive(Debug, Clone)]
pub struct FlowMeta(u8);

impl FlowMeta {
    pub fn zero() -> FlowMeta {
        FlowMeta(0x0)
    }

    /// Create a new FlowMeta.
    ///
    /// Args:
    ///   - insn_length: size of instruction, or 0 if not an instruction, or 0xF if 0xF or larger.
    ///   - does_fallthrough: is there a fallthrough code flow to the next instruction?
    ///   - has_xrefs_from: are there code xrefs from this instruction (non-fallthrough)?
    pub fn new(insn_length: u8, does_fallthrough: bool, has_xrefs_from: bool) -> FlowMeta {
        let len = if insn_length >= 0xF {
            // instrunction length too long
            0x0F
        } else if insn_length == 0x0 {
            // not an instruction
            0x00
        } else {
            // good flow
            insn_length & 0x0F
        };

        let fallthrough = if does_fallthrough {
            0b0001_0000
        } else {
            0b0000_0000
        };

        let xfrom = if has_xrefs_from {
            0b0010_0000
        } else {
            0b0000_0000
        };

        FlowMeta(len | fallthrough | xfrom)
    }

    /// Fetch the cached length of the instruction.
    ///
    /// If longer than 14 bytes, then will return `Error::LongInstruction` and you'll have to decode
    ///  the instruction yourself.
    ///
    /// Errors:
    ///   - NotAnInstruction
    ///   - LongInstruction
    ///
    /// ```
    /// use matches::matches;
    /// use lancelot::flowmeta::*;
    /// assert_eq!(FlowMeta::new(0x01, true, true).get_insn_length().unwrap(),
    ///            0x01);
    /// assert!(matches!(FlowMeta::new(0x00, true, true).get_insn_length().err().unwrap(),
    ///                  Error::NotAnInstruction));
    /// assert!(matches!(FlowMeta::new(0x0F, true, true).get_insn_length().err().unwrap(),
    ///                  Error::LongInstruction));
    /// ```
    pub fn get_insn_length(&self) -> Result<u8, Error> {
        let v = self.0 & 0b0000_1111;
        match v {
            0x00 => Err(Error::NotAnInstruction),
            0x0F => Err(Error::LongInstruction),
            v @ _ => Ok(v)
        }
    }

    pub fn is_insn(&self) -> bool {
        self.0 & 0b0000_1111 != 0
    }

    /// Does the instruction fallthrough?
    pub fn does_fallthrough(&self) -> bool {
        self.0 & 0b0001_0000 > 0
    }

    /// Does the instruction have flow xrefs from it?
    /// This does not include the fallthrough flow.
    pub fn has_xrefs_from(&self) -> bool {
        self.0 & 0b0010_0000 > 0
    }

    /// Does the instruction have flow xrefs to it?
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// assert_eq!(FlowMeta::new(0x01, false, false).has_xrefs_to(), false);
    /// ```
    pub fn has_xrefs_to(&self) -> bool {
        self.0 & 0b0100_0000 > 0
    }

    /// Set the bit indicating that there are flow xrefs to this instruction.
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// let mut m = FlowMeta::new(0x01, false, false);
    /// assert_eq!(m.has_xrefs_to(), false);
    ///
    /// m.set_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), true);
    /// ```
    pub fn set_xrefs_to(&mut self) {
        self.0 = self.0 | 0b0100_0000;
    }

    /// Unset the bit indicating that there are flow xrefs to this instruction.
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// let mut m = FlowMeta::new(0x01, false, false);
    /// assert_eq!(m.has_xrefs_to(), false);
    ///
    /// m.set_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), true);
    ///
    /// m.unset_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), false);
    /// ```
    pub fn unset_xrefs_to(&mut self) {
        self.0 = self.0 & 0b1011_1111
    }
}

impl fmt::Display for FlowMeta {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FlowMeta{{length: {}, fallthrough: {}, xrefs to: {}, xrefs from: {}}}",
               match self.get_insn_length() {
                   Ok(v) => format!("0x{:x}", v),
                   Err(Error::LongInstruction) => ">=0xF".to_string(),
                   Err(Error::NotAnInstruction) => "not an instruction".to_string(),
               },
               self.does_fallthrough(),
               self.has_xrefs_to(),
               self.has_xrefs_from())
    }
}
<|endoftext|>


<commit_before>use std::fmt;

// TODO: figure out how to use failure for error (or some other pattern)
#[derive(Debug)]
pub enum Error {
    NotAnInstruction,
    LongInstruction,
}

/// FlowMeta is metadata that describes code flow for an instruction.
///
/// The metadata is packed into a single byte, with the expectation that,
///  there may be one `FlowMeta` instance for each (code) offset in a program.
/// However, the you should not be worried about the representation, just the interface.
#[derive(Debug, Clone)]
pub struct FlowMeta(u8);

impl FlowMeta {
    // layout:
    //
    //     +-+-+-+-+-+-+-+-+
    //     |A|B|C|D|   E   |
    //     +-+-+-+-+-+-+-+-+
    //
    //  A - unused
    //  B - has xrefs to
    //  C - has xrefs from
    //  D - does fallthrough
    //  E - insn size

    pub fn zero() -> FlowMeta {
        FlowMeta(0x0)
    }

    /// Create a new FlowMeta.
    ///
    /// Args:
    ///   - insn_length: size of instruction, or 0 if not an instruction, or 0xF if 0xF or larger.
    ///   - does_fallthrough: is there a fallthrough code flow to the next instruction?
    ///   - has_xrefs_from: are there code xrefs from this instruction (non-fallthrough)?
    pub fn new(insn_length: u8, does_fallthrough: bool, has_xrefs_from: bool) -> FlowMeta {
        let len = if insn_length >= 0xF {
            // instrunction length too long
            0x0F
        } else if insn_length == 0x0 {
            // not an instruction
            0x00
        } else {
            // good flow
            insn_length & 0x0F
        };

        let fallthrough = if does_fallthrough {
            0b0001_0000
        } else {
            0b0000_0000
        };

        let xfrom = if has_xrefs_from {
            0b0010_0000
        } else {
            0b0000_0000
        };

        FlowMeta(len | fallthrough | xfrom)
    }

    /// Fetch the cached length of the instruction.
    ///
    /// If longer than 14 bytes, then will return `Error::LongInstruction` and you'll have to decode
    ///  the instruction yourself.
    ///
    /// Errors:
    ///   - NotAnInstruction
    ///   - LongInstruction
    ///
    /// ```
    /// use matches::matches;
    /// use lancelot::flowmeta::*;
    /// assert_eq!(FlowMeta::new(0x01, true, true).get_insn_length().unwrap(),
    ///            0x01);
    /// assert!(matches!(FlowMeta::new(0x00, true, true).get_insn_length().err().unwrap(),
    ///                  Error::NotAnInstruction));
    /// assert!(matches!(FlowMeta::new(0x0F, true, true).get_insn_length().err().unwrap(),
    ///                  Error::LongInstruction));
    /// ```
    pub fn get_insn_length(&self) -> Result<u8, Error> {
        let v = self.0 & 0b0000_1111;
        match v {
            0x00 => Err(Error::NotAnInstruction),
            0x0F => Err(Error::LongInstruction),
            v @ _ => Ok(v)
        }
    }

    /// ```
    /// use matches::matches;
    /// use lancelot::flowmeta::*;
    ///
    /// let mut m = FlowMeta::zero();
    ///
    /// m.set_insn_length(0);
    /// assert_eq!(m.is_insn(), false);
    /// assert!(matches!(m.get_insn_length().err().unwrap(), Error::NotAnInstruction));
    ///
    /// m.set_insn_length(1);
    /// assert_eq!(m.is_insn(), true);
    /// assert_eq!(m.get_insn_length().unwrap(), 0x1);
    ///
    /// m.set_insn_length(2);
    /// assert_eq!(m.get_insn_length().unwrap(), 0x2);
    ///
    /// m.set_insn_length(0xE);
    /// assert_eq!(m.get_insn_length().unwrap(), 0xE);
    ///
    /// m.set_insn_length(0xF);
    /// assert_eq!(m.is_insn(), true);
    /// assert!(matches!(m.get_insn_length().err().unwrap(), Error::LongInstruction));
    /// ```
    pub fn set_insn_length(&mut self, length: u8) {
        let len = if length >= 0xF {
            // instrunction length too long
            0x0F
        } else if length == 0x0 {
            // not an instruction
            0x00
        } else {
            // good flow
            length & 0x0F
        };

        self.0 = (self.0 & 0b1111_0000) | len;
    }

    pub fn is_insn(&self) -> bool {
        self.0 & 0b0000_1111 != 0
    }

    /// Does the instruction fallthrough?
    pub fn does_fallthrough(&self) -> bool {
        self.0 & 0b0001_0000 > 0
    }

    /// ```
    /// use matches::matches;
    /// use lancelot::flowmeta::*;
    ///
    /// let mut m = FlowMeta::zero();
    /// assert_eq!(m.does_fallthrough(), false);
    ///
    /// m.set_fallthrough();
    /// assert_eq!(m.does_fallthrough(), true);
    /// ```
    pub fn set_fallthrough(&mut self) {
        self.0 = self.0 | 0b0001_0000;
    }

    /// Does the instruction have flow xrefs from it?
    /// This does not include the fallthrough flow.
    pub fn has_xrefs_from(&self) -> bool {
        self.0 & 0b0010_0000 > 0
    }

    /// ```
    /// use matches::matches;
    /// use lancelot::flowmeta::*;
    ///
    /// let mut m = FlowMeta::zero();
    /// assert_eq!(m.has_xrefs_from(), false);
    ///
    /// m.set_xrefs_from();
    /// assert_eq!(m.has_xrefs_from(), true);
    /// ```
    pub fn set_xrefs_from(&mut self) {
        self.0 = self.0 | 0b0010_0000;
    }

    /// Does the instruction have flow xrefs to it?
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// assert_eq!(FlowMeta::new(0x01, false, false).has_xrefs_to(), false);
    /// ```
    pub fn has_xrefs_to(&self) -> bool {
        self.0 & 0b0100_0000 > 0
    }

    /// Set the bit indicating that there are flow xrefs to this instruction.
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// let mut m = FlowMeta::new(0x01, false, false);
    /// assert_eq!(m.has_xrefs_to(), false);
    ///
    /// m.set_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), true);
    /// ```
    pub fn set_xrefs_to(&mut self) {
        self.0 = self.0 | 0b0100_0000;
    }

    /// Unset the bit indicating that there are flow xrefs to this instruction.
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// let mut m = FlowMeta::new(0x01, false, false);
    /// assert_eq!(m.has_xrefs_to(), false);
    ///
    /// m.set_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), true);
    ///
    /// m.unset_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), false);
    /// ```
    pub fn unset_xrefs_to(&mut self) {
        self.0 = self.0 & 0b1011_1111
    }
}

impl fmt::Display for FlowMeta {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FlowMeta{{length: {}, fallthrough: {}, xrefs to: {}, xrefs from: {}}}",
               match self.get_insn_length() {
                   Ok(v) => format!("0x{:x}", v),
                   Err(Error::LongInstruction) => ">=0xF".to_string(),
                   Err(Error::NotAnInstruction) => "not an instruction".to_string(),
               },
               self.does_fallthrough(),
               self.has_xrefs_to(),
               self.has_xrefs_from())
    }
}
<commit_msg>flowmeta: remove old `.new()` ctor<commit_after>use std::fmt;

// TODO: figure out how to use failure for error (or some other pattern)
#[derive(Debug)]
pub enum Error {
    NotAnInstruction,
    LongInstruction,
}

/// FlowMeta is metadata that describes code flow for an instruction.
///
/// The metadata is packed into a single byte, with the expectation that,
///  there may be one `FlowMeta` instance for each (code) offset in a program.
/// However, the you should not be worried about the representation, just the interface.
#[derive(Debug, Clone)]
pub struct FlowMeta(u8);

impl FlowMeta {
    // layout:
    //
    //     +-+-+-+-+-+-+-+-+
    //     |A|B|C|D|   E   |
    //     +-+-+-+-+-+-+-+-+
    //
    //  A - unused
    //  B - has xrefs to
    //  C - has xrefs from
    //  D - does fallthrough
    //  E - insn size

    pub fn zero() -> FlowMeta {
        FlowMeta(0x0)
    }

    /// Fetch the cached length of the instruction.
    ///
    /// If longer than 14 bytes, then will return `Error::LongInstruction` and you'll have to decode
    ///  the instruction yourself.
    ///
    /// Errors:
    ///   - NotAnInstruction
    ///   - LongInstruction
    pub fn get_insn_length(&self) -> Result<u8, Error> {
        let v = self.0 & 0b0000_1111;
        match v {
            0x00 => Err(Error::NotAnInstruction),
            0x0F => Err(Error::LongInstruction),
            v @ _ => Ok(v)
        }
    }

    /// ```
    /// use matches::matches;
    /// use lancelot::flowmeta::*;
    ///
    /// let mut m = FlowMeta::zero();
    ///
    /// m.set_insn_length(0);
    /// assert_eq!(m.is_insn(), false);
    /// assert!(matches!(m.get_insn_length().err().unwrap(), Error::NotAnInstruction));
    ///
    /// m.set_insn_length(1);
    /// assert_eq!(m.is_insn(), true);
    /// assert_eq!(m.get_insn_length().unwrap(), 0x1);
    ///
    /// m.set_insn_length(2);
    /// assert_eq!(m.get_insn_length().unwrap(), 0x2);
    ///
    /// m.set_insn_length(0xE);
    /// assert_eq!(m.get_insn_length().unwrap(), 0xE);
    ///
    /// m.set_insn_length(0xF);
    /// assert_eq!(m.is_insn(), true);
    /// assert!(matches!(m.get_insn_length().err().unwrap(), Error::LongInstruction));
    /// ```
    pub fn set_insn_length(&mut self, length: u8) {
        let len = if length >= 0xF {
            // instrunction length too long
            0x0F
        } else if length == 0x0 {
            // not an instruction
            0x00
        } else {
            // good flow
            length & 0x0F
        };

        self.0 = (self.0 & 0b1111_0000) | len;
    }

    pub fn is_insn(&self) -> bool {
        self.0 & 0b0000_1111 != 0
    }

    /// Does the instruction fallthrough?
    pub fn does_fallthrough(&self) -> bool {
        self.0 & 0b0001_0000 > 0
    }

    /// ```
    /// use matches::matches;
    /// use lancelot::flowmeta::*;
    ///
    /// let mut m = FlowMeta::zero();
    /// assert_eq!(m.does_fallthrough(), false);
    ///
    /// m.set_fallthrough();
    /// assert_eq!(m.does_fallthrough(), true);
    /// ```
    pub fn set_fallthrough(&mut self) {
        self.0 = self.0 | 0b0001_0000;
    }

    /// Does the instruction have flow xrefs from it?
    /// This does not include the fallthrough flow.
    pub fn has_xrefs_from(&self) -> bool {
        self.0 & 0b0010_0000 > 0
    }

    /// ```
    /// use matches::matches;
    /// use lancelot::flowmeta::*;
    ///
    /// let mut m = FlowMeta::zero();
    /// assert_eq!(m.has_xrefs_from(), false);
    ///
    /// m.set_xrefs_from();
    /// assert_eq!(m.has_xrefs_from(), true);
    /// ```
    pub fn set_xrefs_from(&mut self) {
        self.0 = self.0 | 0b0010_0000;
    }

    /// Does the instruction have flow xrefs to it?
    pub fn has_xrefs_to(&self) -> bool {
        self.0 & 0b0100_0000 > 0
    }

    /// Set the bit indicating that there are flow xrefs to this instruction.
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// let mut m = FlowMeta::zero();
    /// assert_eq!(m.has_xrefs_to(), false);
    ///
    /// m.set_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), true);
    /// ```
    pub fn set_xrefs_to(&mut self) {
        self.0 = self.0 | 0b0100_0000;
    }

    /// Unset the bit indicating that there are flow xrefs to this instruction.
    ///
    /// ```
    /// use lancelot::flowmeta::*;
    /// let mut m = FlowMeta::zero();
    /// assert_eq!(m.has_xrefs_to(), false);
    ///
    /// m.set_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), true);
    ///
    /// m.unset_xrefs_to();
    /// assert_eq!(m.has_xrefs_to(), false);
    /// ```
    pub fn unset_xrefs_to(&mut self) {
        self.0 = self.0 & 0b1011_1111
    }
}

impl fmt::Display for FlowMeta {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "FlowMeta{{length: {}, fallthrough: {}, xrefs to: {}, xrefs from: {}}}",
               match self.get_insn_length() {
                   Ok(v) => format!("0x{:x}", v),
                   Err(Error::LongInstruction) => ">=0xF".to_string(),
                   Err(Error::NotAnInstruction) => "not an instruction".to_string(),
               },
               self.does_fallthrough(),
               self.has_xrefs_to(),
               self.has_xrefs_from())
    }
}
<|endoftext|>


<commit_before>use super::*;

/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct Generics {
    pub lifetimes: Vec<LifetimeDef>,
    pub ty_params: Vec<TyParam>,
    pub where_clause: WhereClause,
}

#[cfg(feature = "printing")]
/// Returned by `Generics::split_for_impl`.
#[derive(Debug)]
pub struct ImplGenerics<'a>(&'a Generics);

#[cfg(feature = "printing")]
/// Returned by `Generics::split_for_impl`.
#[derive(Debug)]
pub struct TyGenerics<'a>(&'a Generics);

impl Generics {
    #[cfg(feature = "printing")]
    /// Split a type's generics into the pieces required for impl'ing a trait
    /// for that type.
    ///
    /// ```
    /// # extern crate syn;
    /// # #[macro_use]
    /// # extern crate quote;
    /// # fn main() {
    /// # let generics: syn::Generics = Default::default();
    /// # let name = syn::Ident::new("MyType");
    /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
    /// quote! {
    ///     impl #impl_generics MyTrait for #name #ty_generics #where_clause {
    ///         // ...
    ///     }
    /// }
    /// # ;
    /// # }
    /// ```
    pub fn split_for_impl(&self) -> (ImplGenerics, TyGenerics, &WhereClause) {
        (ImplGenerics(self), TyGenerics(self), &self.where_clause)
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Lifetime {
    pub ident: Ident,
}

impl Lifetime {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        let id = Ident::new(t);
        if !id.as_ref().starts_with('\'') {
            panic!("lifetime name must start with apostrophe as in \"'a\", \
                   got {:?}",
                   id.as_ref());
        }
        Lifetime { ident: id }
    }
}

/// A lifetime definition, e.g. `'a: 'b+'c+'d`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct LifetimeDef {
    pub attrs: Vec<Attribute>,
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

impl LifetimeDef {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        LifetimeDef {
            attrs: Vec::new(),
            lifetime: Lifetime::new(t),
            bounds: Vec::new(),
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct TyParam {
    pub attrs: Vec<Attribute>,
    pub ident: Ident,
    pub bounds: Vec<TyParamBound>,
    pub default: Option<Ty>,
}

/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects Copy, Send and Sync.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum TyParamBound {
    Trait(PolyTraitRef, TraitBoundModifier),
    Region(Lifetime),
}

/// A modifier on a bound, currently this is only used for `?Sized`, where the
/// modifier is `Maybe`. Negative bounds should also be handled here.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TraitBoundModifier {
    None,
    Maybe,
}

/// A `where` clause in a definition
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct WhereClause {
    pub predicates: Vec<WherePredicate>,
}

impl WhereClause {
    pub fn none() -> Self {
        WhereClause { predicates: Vec::new() }
    }
}

/// A single predicate in a `where` clause
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum WherePredicate {
    /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
    BoundPredicate(WhereBoundPredicate),
    /// A lifetime predicate, e.g. `'a: 'b+'c`
    RegionPredicate(WhereRegionPredicate),
}

/// A type bound.
///
/// E.g. `for<'c> Foo: Send+Clone+'c`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct WhereBoundPredicate {
    /// Any lifetimes from a `for` binding
    pub bound_lifetimes: Vec<LifetimeDef>,
    /// The type being bounded
    pub bounded_ty: Ty,
    /// Trait and lifetime bounds (`Clone+Send+'static`)
    pub bounds: Vec<TyParamBound>,
}

/// A lifetime predicate.
///
/// E.g. `'a: 'b+'c`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct WhereRegionPredicate {
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use attr::parsing::outer_attr;
    use ident::parsing::ident;
    use ty::parsing::{ty, poly_trait_ref};

    named!(pub generics -> Generics, map!(
        alt!(
            do_parse!(
                punct!("<") >>
                lifetimes: separated_list!(punct!(","), lifetime_def) >>
                ty_params: opt_vec!(preceded!(
                    cond!(!lifetimes.is_empty(), punct!(",")),
                    separated_nonempty_list!(punct!(","), ty_param)
                )) >>
                punct!(">") >>
                (lifetimes, ty_params)
            )
            |
            epsilon!() => { |_| (Vec::new(), Vec::new()) }
        ),
        |(lifetimes, ty_params)| Generics {
            lifetimes: lifetimes,
            ty_params: ty_params,
            where_clause: Default::default(),
        }
    ));

    named!(pub lifetime -> Lifetime, preceded!(
        punct!("'"),
        alt!(
            map!(ident, |id| Lifetime {
                ident: format!("'{}", id).into(),
            })
            |
            map!(keyword!("static"), |_| Lifetime {
                ident: "'static".into(),
            })
        )
    ));

    named!(pub lifetime_def -> LifetimeDef, do_parse!(
        attrs: many0!(outer_attr) >>
        life: lifetime >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_nonempty_list!(punct!("+"), lifetime)
        )) >>
        (LifetimeDef {
            attrs: attrs,
            lifetime: life,
            bounds: bounds,
        })
    ));

    named!(pub bound_lifetimes -> Vec<LifetimeDef>, opt_vec!(do_parse!(
        keyword!("for") >>
        punct!("<") >>
        lifetimes: terminated_list!(punct!(","), lifetime_def) >>
        punct!(">") >>
        (lifetimes)
    )));

    named!(ty_param -> TyParam, do_parse!(
        attrs: many0!(outer_attr) >>
        id: ident >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_nonempty_list!(punct!("+"), ty_param_bound)
        )) >>
        default: option!(preceded!(
            punct!("="),
            ty
        )) >>
        (TyParam {
            attrs: attrs,
            ident: id,
            bounds: bounds,
            default: default,
        })
    ));

    named!(pub ty_param_bound -> TyParamBound, alt!(
        preceded!(punct!("?"), poly_trait_ref) => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::Maybe)
        }
        |
        lifetime => { TyParamBound::Region }
        |
        poly_trait_ref => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::None)
        }
    ));

    named!(pub where_clause -> WhereClause, alt!(
        do_parse!(
            keyword!("where") >>
            predicates: separated_nonempty_list!(punct!(","), where_predicate) >>
            option!(punct!(",")) >>
            (WhereClause { predicates: predicates })
        )
        |
        epsilon!() => { |_| Default::default() }
    ));

    named!(where_predicate -> WherePredicate, alt!(
        do_parse!(
            ident: lifetime >>
            punct!(":") >>
            bounds: separated_nonempty_list!(punct!("+"), lifetime) >>
            (WherePredicate::RegionPredicate(WhereRegionPredicate {
                lifetime: ident,
                bounds: bounds,
            }))
        )
        |
        do_parse!(
            bound_lifetimes: bound_lifetimes >>
            bounded_ty: ty >>
            punct!(":") >>
            bounds: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
            (WherePredicate::BoundPredicate(WhereBoundPredicate {
                bound_lifetimes: bound_lifetimes,
                bounded_ty: bounded_ty,
                bounds: bounds,
            }))
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use attr::FilterAttrs;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Generics {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.lifetimes.is_empty();
            let has_ty_params = !self.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                tokens.append_separated(&self.ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for ImplGenerics<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.0.lifetimes, ",");
                // Leave off the type parameter defaults
                for (i, ty_param) in self.0.ty_params.iter().enumerate() {
                    if i > 0 || has_lifetimes {
                        tokens.append(",");
                    }
                    tokens.append_all(ty_param.attrs.outer());
                    ty_param.ident.to_tokens(tokens);
                    if !ty_param.bounds.is_empty() {
                        tokens.append(":");
                        tokens.append_separated(&ty_param.bounds, "+");
                    }
                }
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for TyGenerics<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                // Leave off the lifetime bounds and attributes
                let lifetimes = self.0.lifetimes.iter().map(|ld| &ld.lifetime);
                tokens.append_separated(lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                // Leave off the type parameter bounds, defaults, and attributes
                let ty_params = self.0.ty_params.iter().map(|tp| &tp.ident);
                tokens.append_separated(ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl ToTokens for Lifetime {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.ident.to_tokens(tokens);
        }
    }

    impl ToTokens for LifetimeDef {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.outer());
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for TyParam {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.outer());
            self.ident.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
            if let Some(ref default) = self.default {
                tokens.append("=");
                default.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for TyParamBound {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                TyParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens),
                TyParamBound::Trait(ref trait_ref, modifier) => {
                    match modifier {
                        TraitBoundModifier::None => {}
                        TraitBoundModifier::Maybe => tokens.append("?"),
                    }
                    trait_ref.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereClause {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.predicates.is_empty() {
                tokens.append("where");
                tokens.append_separated(&self.predicates, ",");
            }
        }
    }

    impl ToTokens for WherePredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                WherePredicate::BoundPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
                WherePredicate::RegionPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereBoundPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.bound_lifetimes.is_empty() {
                tokens.append("for");
                tokens.append("<");
                tokens.append_separated(&self.bound_lifetimes, ",");
                tokens.append(">");
            }
            self.bounded_ty.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for WhereRegionPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }
}
<commit_msg>Allow lifetimes with empty list of bounds<commit_after>use super::*;

/// Represents lifetimes and type parameters attached to a declaration
/// of a function, enum, trait, etc.
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct Generics {
    pub lifetimes: Vec<LifetimeDef>,
    pub ty_params: Vec<TyParam>,
    pub where_clause: WhereClause,
}

#[cfg(feature = "printing")]
/// Returned by `Generics::split_for_impl`.
#[derive(Debug)]
pub struct ImplGenerics<'a>(&'a Generics);

#[cfg(feature = "printing")]
/// Returned by `Generics::split_for_impl`.
#[derive(Debug)]
pub struct TyGenerics<'a>(&'a Generics);

impl Generics {
    #[cfg(feature = "printing")]
    /// Split a type's generics into the pieces required for impl'ing a trait
    /// for that type.
    ///
    /// ```
    /// # extern crate syn;
    /// # #[macro_use]
    /// # extern crate quote;
    /// # fn main() {
    /// # let generics: syn::Generics = Default::default();
    /// # let name = syn::Ident::new("MyType");
    /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
    /// quote! {
    ///     impl #impl_generics MyTrait for #name #ty_generics #where_clause {
    ///         // ...
    ///     }
    /// }
    /// # ;
    /// # }
    /// ```
    pub fn split_for_impl(&self) -> (ImplGenerics, TyGenerics, &WhereClause) {
        (ImplGenerics(self), TyGenerics(self), &self.where_clause)
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Lifetime {
    pub ident: Ident,
}

impl Lifetime {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        let id = Ident::new(t);
        if !id.as_ref().starts_with('\'') {
            panic!("lifetime name must start with apostrophe as in \"'a\", \
                   got {:?}",
                   id.as_ref());
        }
        Lifetime { ident: id }
    }
}

/// A lifetime definition, e.g. `'a: 'b+'c+'d`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct LifetimeDef {
    pub attrs: Vec<Attribute>,
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

impl LifetimeDef {
    pub fn new<T: Into<Ident>>(t: T) -> Self {
        LifetimeDef {
            attrs: Vec::new(),
            lifetime: Lifetime::new(t),
            bounds: Vec::new(),
        }
    }
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct TyParam {
    pub attrs: Vec<Attribute>,
    pub ident: Ident,
    pub bounds: Vec<TyParamBound>,
    pub default: Option<Ty>,
}

/// The AST represents all type param bounds as types.
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects Copy, Send and Sync.
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum TyParamBound {
    Trait(PolyTraitRef, TraitBoundModifier),
    Region(Lifetime),
}

/// A modifier on a bound, currently this is only used for `?Sized`, where the
/// modifier is `Maybe`. Negative bounds should also be handled here.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TraitBoundModifier {
    None,
    Maybe,
}

/// A `where` clause in a definition
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct WhereClause {
    pub predicates: Vec<WherePredicate>,
}

impl WhereClause {
    pub fn none() -> Self {
        WhereClause { predicates: Vec::new() }
    }
}

/// A single predicate in a `where` clause
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum WherePredicate {
    /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
    BoundPredicate(WhereBoundPredicate),
    /// A lifetime predicate, e.g. `'a: 'b+'c`
    RegionPredicate(WhereRegionPredicate),
}

/// A type bound.
///
/// E.g. `for<'c> Foo: Send+Clone+'c`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct WhereBoundPredicate {
    /// Any lifetimes from a `for` binding
    pub bound_lifetimes: Vec<LifetimeDef>,
    /// The type being bounded
    pub bounded_ty: Ty,
    /// Trait and lifetime bounds (`Clone+Send+'static`)
    pub bounds: Vec<TyParamBound>,
}

/// A lifetime predicate.
///
/// E.g. `'a: 'b+'c`
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct WhereRegionPredicate {
    pub lifetime: Lifetime,
    pub bounds: Vec<Lifetime>,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use attr::parsing::outer_attr;
    use ident::parsing::ident;
    use ty::parsing::{ty, poly_trait_ref};

    named!(pub generics -> Generics, map!(
        alt!(
            do_parse!(
                punct!("<") >>
                lifetimes: separated_list!(punct!(","), lifetime_def) >>
                ty_params: opt_vec!(preceded!(
                    cond!(!lifetimes.is_empty(), punct!(",")),
                    separated_nonempty_list!(punct!(","), ty_param)
                )) >>
                punct!(">") >>
                (lifetimes, ty_params)
            )
            |
            epsilon!() => { |_| (Vec::new(), Vec::new()) }
        ),
        |(lifetimes, ty_params)| Generics {
            lifetimes: lifetimes,
            ty_params: ty_params,
            where_clause: Default::default(),
        }
    ));

    named!(pub lifetime -> Lifetime, preceded!(
        punct!("'"),
        alt!(
            map!(ident, |id| Lifetime {
                ident: format!("'{}", id).into(),
            })
            |
            map!(keyword!("static"), |_| Lifetime {
                ident: "'static".into(),
            })
        )
    ));

    named!(pub lifetime_def -> LifetimeDef, do_parse!(
        attrs: many0!(outer_attr) >>
        life: lifetime >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_list!(punct!("+"), lifetime)
        )) >>
        (LifetimeDef {
            attrs: attrs,
            lifetime: life,
            bounds: bounds,
        })
    ));

    named!(pub bound_lifetimes -> Vec<LifetimeDef>, opt_vec!(do_parse!(
        keyword!("for") >>
        punct!("<") >>
        lifetimes: terminated_list!(punct!(","), lifetime_def) >>
        punct!(">") >>
        (lifetimes)
    )));

    named!(ty_param -> TyParam, do_parse!(
        attrs: many0!(outer_attr) >>
        id: ident >>
        bounds: opt_vec!(preceded!(
            punct!(":"),
            separated_nonempty_list!(punct!("+"), ty_param_bound)
        )) >>
        default: option!(preceded!(
            punct!("="),
            ty
        )) >>
        (TyParam {
            attrs: attrs,
            ident: id,
            bounds: bounds,
            default: default,
        })
    ));

    named!(pub ty_param_bound -> TyParamBound, alt!(
        preceded!(punct!("?"), poly_trait_ref) => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::Maybe)
        }
        |
        lifetime => { TyParamBound::Region }
        |
        poly_trait_ref => {
            |poly| TyParamBound::Trait(poly, TraitBoundModifier::None)
        }
    ));

    named!(pub where_clause -> WhereClause, alt!(
        do_parse!(
            keyword!("where") >>
            predicates: separated_nonempty_list!(punct!(","), where_predicate) >>
            option!(punct!(",")) >>
            (WhereClause { predicates: predicates })
        )
        |
        epsilon!() => { |_| Default::default() }
    ));

    named!(where_predicate -> WherePredicate, alt!(
        do_parse!(
            ident: lifetime >>
            bounds: opt_vec!(preceded!(
                punct!(":"),
                separated_list!(punct!("+"), lifetime)
            )) >>
            (WherePredicate::RegionPredicate(WhereRegionPredicate {
                lifetime: ident,
                bounds: bounds,
            }))
        )
        |
        do_parse!(
            bound_lifetimes: bound_lifetimes >>
            bounded_ty: ty >>
            punct!(":") >>
            bounds: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
            (WherePredicate::BoundPredicate(WhereBoundPredicate {
                bound_lifetimes: bound_lifetimes,
                bounded_ty: bounded_ty,
                bounds: bounds,
            }))
        )
    ));
}

#[cfg(feature = "printing")]
mod printing {
    use super::*;
    use attr::FilterAttrs;
    use quote::{Tokens, ToTokens};

    impl ToTokens for Generics {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.lifetimes.is_empty();
            let has_ty_params = !self.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                tokens.append_separated(&self.ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for ImplGenerics<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                tokens.append_separated(&self.0.lifetimes, ",");
                // Leave off the type parameter defaults
                for (i, ty_param) in self.0.ty_params.iter().enumerate() {
                    if i > 0 || has_lifetimes {
                        tokens.append(",");
                    }
                    tokens.append_all(ty_param.attrs.outer());
                    ty_param.ident.to_tokens(tokens);
                    if !ty_param.bounds.is_empty() {
                        tokens.append(":");
                        tokens.append_separated(&ty_param.bounds, "+");
                    }
                }
                tokens.append(">");
            }
        }
    }

    impl<'a> ToTokens for TyGenerics<'a> {
        fn to_tokens(&self, tokens: &mut Tokens) {
            let has_lifetimes = !self.0.lifetimes.is_empty();
            let has_ty_params = !self.0.ty_params.is_empty();
            if has_lifetimes || has_ty_params {
                tokens.append("<");
                // Leave off the lifetime bounds and attributes
                let lifetimes = self.0.lifetimes.iter().map(|ld| &ld.lifetime);
                tokens.append_separated(lifetimes, ",");
                if has_lifetimes && has_ty_params {
                    tokens.append(",");
                }
                // Leave off the type parameter bounds, defaults, and attributes
                let ty_params = self.0.ty_params.iter().map(|tp| &tp.ident);
                tokens.append_separated(ty_params, ",");
                tokens.append(">");
            }
        }
    }

    impl ToTokens for Lifetime {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.ident.to_tokens(tokens);
        }
    }

    impl ToTokens for LifetimeDef {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.outer());
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for TyParam {
        fn to_tokens(&self, tokens: &mut Tokens) {
            tokens.append_all(self.attrs.outer());
            self.ident.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
            if let Some(ref default) = self.default {
                tokens.append("=");
                default.to_tokens(tokens);
            }
        }
    }

    impl ToTokens for TyParamBound {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                TyParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens),
                TyParamBound::Trait(ref trait_ref, modifier) => {
                    match modifier {
                        TraitBoundModifier::None => {}
                        TraitBoundModifier::Maybe => tokens.append("?"),
                    }
                    trait_ref.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereClause {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.predicates.is_empty() {
                tokens.append("where");
                tokens.append_separated(&self.predicates, ",");
            }
        }
    }

    impl ToTokens for WherePredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                WherePredicate::BoundPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
                WherePredicate::RegionPredicate(ref predicate) => {
                    predicate.to_tokens(tokens);
                }
            }
        }
    }

    impl ToTokens for WhereBoundPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            if !self.bound_lifetimes.is_empty() {
                tokens.append("for");
                tokens.append("<");
                tokens.append_separated(&self.bound_lifetimes, ",");
                tokens.append(">");
            }
            self.bounded_ty.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }

    impl ToTokens for WhereRegionPredicate {
        fn to_tokens(&self, tokens: &mut Tokens) {
            self.lifetime.to_tokens(tokens);
            if !self.bounds.is_empty() {
                tokens.append(":");
                tokens.append_separated(&self.bounds, "+");
            }
        }
    }
}
<|endoftext|>


<commit_before>//! **GraphMap\<N, E\>** is an undirected graph where node values are mapping keys.

use std::hash::{Hash};
use std::collections::HashMap;
use std::iter::Map;
use std::collections::hash_map::{
    Keys,
};
use std::collections::hash_map::Entry::{
    Occupied,
    Vacant,
};
use std::slice::{
    Iter,
};
use std::fmt;
use std::ops::{Index, IndexMut};

/// **GraphMap\<N, E\>** is an undirected graph, with generic node values **N** and edge weights **E**.
///
/// It uses an combined adjacency list and sparse adjacency matrix representation, using **O(|V|
/// + |E|)** space, and allows testing for edge existance in constant time.
///
/// The node type **N** must implement **Copy** and will be used as node identifier, duplicated
/// into several places in the data structure.
/// It must be suitable as a hash table key (implementing **Eq + Hash**).
/// The node type must also implement **Ord** so that the implementation can
/// order the pair (**a**, **b**) for an edge connecting any two nodes **a** and **b**.
///
/// **GraphMap** does not allow parallel edges, but self loops are allowed.
#[derive(Clone)]
pub struct GraphMap<N: Eq + Hash, E> {
    nodes: HashMap<N, Vec<N>>,
    edges: HashMap<(N, N), E>,
}

impl<N: Eq + Hash + fmt::Debug, E: fmt::Debug> fmt::Debug for GraphMap<N, E>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.nodes.fmt(f)
    }
}

#[inline]
fn edge_key<N: Copy + Ord>(a: N, b: N) -> (N, N)
{
    if a <= b { (a, b) } else { (b, a) }
}

#[inline]
fn copy<N: Copy>(n: &N) -> N { *n }

/// A trait group for **GraphMap**'s node identifier.
pub trait NodeTrait : Copy + Ord + Eq + Hash {}
impl<N> NodeTrait for N where N: Copy + Ord + Eq + Hash {}

impl<N, E> GraphMap<N, E> where N: NodeTrait
{
    /// Create a new **GraphMap**.
    pub fn new() -> Self
    {
        GraphMap {
            nodes: HashMap::new(),
            edges: HashMap::new(),
        }
    }

    /// Create a new **GraphMap** with estimated capacity.
    pub fn with_capacity(nodes: usize, edges: usize) -> Self
    {
        GraphMap {
            nodes: HashMap::with_capacity(nodes),
            edges: HashMap::with_capacity(edges),
        }
    }

    /// Return the number of nodes in the graph.
    pub fn node_count(&self) -> usize
    {
        self.nodes.len()
    }

    /// Return the number of edges in the graph.
    pub fn edge_count(&self) -> usize
    {
        self.edges.len()
    }

    /// Remove all nodes and edges
    pub fn clear(&mut self)
    {
        self.nodes.clear();
        self.edges.clear();
    }

    /// Add node **n** to the graph.
    pub fn add_node(&mut self, n: N) -> N {
        match self.nodes.entry(n) {
            Occupied(_) => {}
            Vacant(ent) => { ent.insert(Vec::new()); }
        }
        n
    }

    /// Return **true** if node **n** was removed.
    pub fn remove_node(&mut self, n: N) -> bool {
        let successors = match self.nodes.remove(&n) {
            None => return false,
            Some(sus) => sus,
        };
        for succ in successors.into_iter() {
            // remove all successor links
            self.remove_single_edge(&succ, &n);
            // Remove all edge values
            self.edges.remove(&edge_key(n, succ));
        }
        true
    }

    /// Return **true** if the node is contained in the graph.
    pub fn contains_node(&self, n: N) -> bool {
        self.nodes.contains_key(&n)
    }

    /// Add an edge connecting **a** and **b** to the graph.
    ///
    /// Inserts nodes **a** and/or **b** if they aren't already part of the graph.
    ///
    /// Return **true** if edge did not previously exist.
    ///
    /// ## Example
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_edge(1, 2, -1);
    /// assert_eq!(g.node_count(), 2);
    /// assert_eq!(g.edge_count(), 1);
    /// ```
    pub fn add_edge(&mut self, a: N, b: N, edge: E) -> bool
    {
        // Use Ord to order the edges
        match self.nodes.entry(a) {
            Occupied(ent) => { ent.into_mut().push(b); }
            Vacant(ent) => { ent.insert(vec![b]); }
        }
        match self.nodes.entry(b) {
            Occupied(ent) => { ent.into_mut().push(a); }
            Vacant(ent) => { ent.insert(vec![a]); }
        }
        self.edges.insert(edge_key(a, b), edge).is_none()
    }

    /// Remove successor relation from a to b
    ///
    /// Return **true** if it did exist.
    fn remove_single_edge(&mut self, a: &N, b: &N) -> bool
    {
        match self.nodes.get_mut(a) {
            None => false,
            Some(sus) => {
                match sus.iter().position(|elt| elt == b) {
                    Some(index) => { sus.swap_remove(index); true }
                    None => false,
                }
            }
        }
    }

    /// Remove edge from **a** to **b** from the graph and return the edge weight.
    ///
    /// Return **None** if the edge didn't exist.
    ///
    /// ## Example
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_node(1);
    /// g.add_node(2);
    /// g.add_edge(1, 2, -1);
    ///
    /// let edge = g.remove_edge(2, 1);
    /// assert_eq!(edge, Some(-1));
    /// assert_eq!(g.edge_count(), 0);
    /// ```
    pub fn remove_edge(&mut self, a: N, b: N) -> Option<E>
    {
        let exist1 = self.remove_single_edge(&a, &b);
        let exist2 = self.remove_single_edge(&b, &a);
        let weight = self.edges.remove(&edge_key(a, b));
        debug_assert!(exist1 == exist2 && exist1 == weight.is_some());
        weight
    }

    /// Return **true** if the edge connecting **a** with **b** is contained in the graph.
    pub fn contains_edge(&self, a: N, b: N) -> bool {
        self.edges.contains_key(&edge_key(a, b))
    }

    /// Return an iterator over the nodes of the graph.
    ///
    /// Iterator element type is **N**.
    pub fn nodes<'a>(&'a self) -> Nodes<'a, N>
    {
        Nodes{iter: self.nodes.keys().map(copy)}
    }

    /// Return an iterator over the nodes that are connected with **from** by edges.
    ///
    /// If the node **from** does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is **N**.
    pub fn neighbors<'a>(&'a self, from: N) -> Neighbors<'a, N>
    {
        Neighbors{iter:
            match self.nodes.get(&from) {
                Some(neigh) => neigh.iter(),
                None => [].iter(),
            }.map(copy)
        }
    }

    /// Return an iterator over the nodes that are connected with **from** by edges,
    /// paired with the edge weight.
    ///
    /// If the node **from** does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is **(N, &'a E)**.
    pub fn edges<'a>(&'a self, from: N) -> Edges<'a, N, E>
    {
        Edges {
            from: from,
            iter: self.neighbors(from),
            edges: &self.edges,
        }
    }

    /// Return a reference to the edge weight connecting **a** with **b**, or
    /// **None** if the edge does not exist in the graph.
    pub fn edge_weight<'a>(&'a self, a: N, b: N) -> Option<&'a E>
    {
        self.edges.get(&edge_key(a, b))
    }

    /// Return a mutable reference to the edge weight connecting **a** with **b**, or
    /// **None** if the edge does not exist in the graph.
    pub fn edge_weight_mut<'a>(&'a mut self, a: N, b: N) -> Option<&'a mut E>
    {
        self.edges.get_mut(&edge_key(a, b))
    }
}

/// Utitily macro -- reinterpret passed in macro arguments as items
macro_rules! items {
    ($($item:item)*) => ($($item)*);
}

macro_rules! iterator_wrap {
    ($name: ident <$($typarm:tt),*> where { $($bounds: tt)* }
     item: $item: ty,
     iter: $iter: ty,
     ) => (
        items! {
            pub struct $name <$($typarm),*> where $($bounds)* {
                iter: $iter,
            }
            impl<$($typarm),*> Iterator for $name <$($typarm),*>
            {
                type Item = $item;
                #[inline]
                fn next(&mut self) -> Option<Self::Item> {
                    self.iter.next()
                }

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

iterator_wrap! {
    Nodes <'a, N> where { N: 'a }
    item: N,
    iter: Map<Keys<'a, N, Vec<N>>, fn(&N) -> N>,
}

iterator_wrap! {
    Neighbors <'a, N> where { N: 'a }
    item: N,
    iter: Map<Iter<'a, N>, fn(&N) -> N>,
}

pub struct Edges<'a, N, E: 'a> where N: 'a + NodeTrait
{
    pub from: N,
    pub edges: &'a HashMap<(N, N), E>,
    pub iter: Neighbors<'a, N>,
}

impl<'a, N, E> Iterator for Edges<'a, N, E>
    where N: 'a + NodeTrait, E: 'a
{
    type Item = (N, &'a E);
    fn next(&mut self) -> Option<(N, &'a E)>
    {
        match self.iter.next() {
            None => None,
            Some(b) => {
                let a = self.from;
                match self.edges.get(&edge_key(a, b)) {
                    None => unreachable!(),
                    Some(edge) => {
                        Some((b, edge))
                    }
                }
            }
        }
    }
}

/// Index **GraphMap** by node pairs to access edge weights.
impl<N, E> Index<(N, N)> for GraphMap<N, E> where N: NodeTrait
{
    type Output = E;
    fn index(&self, index: (N, N)) -> &E
    {
        self.edge_weight(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}

/// Index **GraphMap** by node pairs to access edge weights.
impl<N, E> IndexMut<(N, N)> for GraphMap<N, E> where N: NodeTrait
{
    fn index_mut(&mut self, index: (N, N)) -> &mut E
    {
        self.edge_weight_mut(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}
<commit_msg>Change entry code to using .or_insert_with()<commit_after>//! **GraphMap\<N, E\>** is an undirected graph where node values are mapping keys.

use std::hash::{Hash};
use std::collections::HashMap;
use std::iter::Map;
use std::collections::hash_map::{
    Keys,
};
use std::slice::{
    Iter,
};
use std::fmt;
use std::ops::{Index, IndexMut};

/// **GraphMap\<N, E\>** is an undirected graph, with generic node values **N** and edge weights **E**.
///
/// It uses an combined adjacency list and sparse adjacency matrix representation, using **O(|V|
/// + |E|)** space, and allows testing for edge existance in constant time.
///
/// The node type **N** must implement **Copy** and will be used as node identifier, duplicated
/// into several places in the data structure.
/// It must be suitable as a hash table key (implementing **Eq + Hash**).
/// The node type must also implement **Ord** so that the implementation can
/// order the pair (**a**, **b**) for an edge connecting any two nodes **a** and **b**.
///
/// **GraphMap** does not allow parallel edges, but self loops are allowed.
#[derive(Clone)]
pub struct GraphMap<N: Eq + Hash, E> {
    nodes: HashMap<N, Vec<N>>,
    edges: HashMap<(N, N), E>,
}

impl<N: Eq + Hash + fmt::Debug, E: fmt::Debug> fmt::Debug for GraphMap<N, E>
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.nodes.fmt(f)
    }
}

#[inline]
fn edge_key<N: Copy + Ord>(a: N, b: N) -> (N, N)
{
    if a <= b { (a, b) } else { (b, a) }
}

#[inline]
fn copy<N: Copy>(n: &N) -> N { *n }

/// A trait group for **GraphMap**'s node identifier.
pub trait NodeTrait : Copy + Ord + Eq + Hash {}
impl<N> NodeTrait for N where N: Copy + Ord + Eq + Hash {}

impl<N, E> GraphMap<N, E> where N: NodeTrait
{
    /// Create a new **GraphMap**.
    pub fn new() -> Self
    {
        GraphMap {
            nodes: HashMap::new(),
            edges: HashMap::new(),
        }
    }

    /// Create a new **GraphMap** with estimated capacity.
    pub fn with_capacity(nodes: usize, edges: usize) -> Self
    {
        GraphMap {
            nodes: HashMap::with_capacity(nodes),
            edges: HashMap::with_capacity(edges),
        }
    }

    /// Return the number of nodes in the graph.
    pub fn node_count(&self) -> usize
    {
        self.nodes.len()
    }

    /// Return the number of edges in the graph.
    pub fn edge_count(&self) -> usize
    {
        self.edges.len()
    }

    /// Remove all nodes and edges
    pub fn clear(&mut self)
    {
        self.nodes.clear();
        self.edges.clear();
    }

    /// Add node **n** to the graph.
    pub fn add_node(&mut self, n: N) -> N {
        self.nodes.entry(n).or_insert_with(|| Vec::new());
        n
    }

    /// Return **true** if node **n** was removed.
    pub fn remove_node(&mut self, n: N) -> bool {
        let successors = match self.nodes.remove(&n) {
            None => return false,
            Some(sus) => sus,
        };
        for succ in successors.into_iter() {
            // remove all successor links
            self.remove_single_edge(&succ, &n);
            // Remove all edge values
            self.edges.remove(&edge_key(n, succ));
        }
        true
    }

    /// Return **true** if the node is contained in the graph.
    pub fn contains_node(&self, n: N) -> bool {
        self.nodes.contains_key(&n)
    }

    /// Add an edge connecting **a** and **b** to the graph.
    ///
    /// Inserts nodes **a** and/or **b** if they aren't already part of the graph.
    ///
    /// Return **true** if edge did not previously exist.
    ///
    /// ## Example
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_edge(1, 2, -1);
    /// assert_eq!(g.node_count(), 2);
    /// assert_eq!(g.edge_count(), 1);
    /// ```
    pub fn add_edge(&mut self, a: N, b: N, edge: E) -> bool
    {
        // Use Ord to order the edges
        self.nodes.entry(a)
                  .or_insert_with(|| Vec::with_capacity(1))
                  .push(b);
        self.nodes.entry(b)
                  .or_insert_with(|| Vec::with_capacity(1))
                  .push(a);
        self.edges.insert(edge_key(a, b), edge).is_none()
    }

    /// Remove successor relation from a to b
    ///
    /// Return **true** if it did exist.
    fn remove_single_edge(&mut self, a: &N, b: &N) -> bool
    {
        match self.nodes.get_mut(a) {
            None => false,
            Some(sus) => {
                match sus.iter().position(|elt| elt == b) {
                    Some(index) => { sus.swap_remove(index); true }
                    None => false,
                }
            }
        }
    }

    /// Remove edge from **a** to **b** from the graph and return the edge weight.
    ///
    /// Return **None** if the edge didn't exist.
    ///
    /// ## Example
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_node(1);
    /// g.add_node(2);
    /// g.add_edge(1, 2, -1);
    ///
    /// let edge = g.remove_edge(2, 1);
    /// assert_eq!(edge, Some(-1));
    /// assert_eq!(g.edge_count(), 0);
    /// ```
    pub fn remove_edge(&mut self, a: N, b: N) -> Option<E>
    {
        let exist1 = self.remove_single_edge(&a, &b);
        let exist2 = self.remove_single_edge(&b, &a);
        let weight = self.edges.remove(&edge_key(a, b));
        debug_assert!(exist1 == exist2 && exist1 == weight.is_some());
        weight
    }

    /// Return **true** if the edge connecting **a** with **b** is contained in the graph.
    pub fn contains_edge(&self, a: N, b: N) -> bool {
        self.edges.contains_key(&edge_key(a, b))
    }

    /// Return an iterator over the nodes of the graph.
    ///
    /// Iterator element type is **N**.
    pub fn nodes<'a>(&'a self) -> Nodes<'a, N>
    {
        Nodes{iter: self.nodes.keys().map(copy)}
    }

    /// Return an iterator over the nodes that are connected with **from** by edges.
    ///
    /// If the node **from** does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is **N**.
    pub fn neighbors<'a>(&'a self, from: N) -> Neighbors<'a, N>
    {
        Neighbors{iter:
            match self.nodes.get(&from) {
                Some(neigh) => neigh.iter(),
                None => [].iter(),
            }.map(copy)
        }
    }

    /// Return an iterator over the nodes that are connected with **from** by edges,
    /// paired with the edge weight.
    ///
    /// If the node **from** does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is **(N, &'a E)**.
    pub fn edges<'a>(&'a self, from: N) -> Edges<'a, N, E>
    {
        Edges {
            from: from,
            iter: self.neighbors(from),
            edges: &self.edges,
        }
    }

    /// Return a reference to the edge weight connecting **a** with **b**, or
    /// **None** if the edge does not exist in the graph.
    pub fn edge_weight<'a>(&'a self, a: N, b: N) -> Option<&'a E>
    {
        self.edges.get(&edge_key(a, b))
    }

    /// Return a mutable reference to the edge weight connecting **a** with **b**, or
    /// **None** if the edge does not exist in the graph.
    pub fn edge_weight_mut<'a>(&'a mut self, a: N, b: N) -> Option<&'a mut E>
    {
        self.edges.get_mut(&edge_key(a, b))
    }
}

/// Utitily macro -- reinterpret passed in macro arguments as items
macro_rules! items {
    ($($item:item)*) => ($($item)*);
}

macro_rules! iterator_wrap {
    ($name: ident <$($typarm:tt),*> where { $($bounds: tt)* }
     item: $item: ty,
     iter: $iter: ty,
     ) => (
        items! {
            pub struct $name <$($typarm),*> where $($bounds)* {
                iter: $iter,
            }
            impl<$($typarm),*> Iterator for $name <$($typarm),*>
            {
                type Item = $item;
                #[inline]
                fn next(&mut self) -> Option<Self::Item> {
                    self.iter.next()
                }

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

iterator_wrap! {
    Nodes <'a, N> where { N: 'a }
    item: N,
    iter: Map<Keys<'a, N, Vec<N>>, fn(&N) -> N>,
}

iterator_wrap! {
    Neighbors <'a, N> where { N: 'a }
    item: N,
    iter: Map<Iter<'a, N>, fn(&N) -> N>,
}

pub struct Edges<'a, N, E: 'a> where N: 'a + NodeTrait
{
    pub from: N,
    pub edges: &'a HashMap<(N, N), E>,
    pub iter: Neighbors<'a, N>,
}

impl<'a, N, E> Iterator for Edges<'a, N, E>
    where N: 'a + NodeTrait, E: 'a
{
    type Item = (N, &'a E);
    fn next(&mut self) -> Option<(N, &'a E)>
    {
        match self.iter.next() {
            None => None,
            Some(b) => {
                let a = self.from;
                match self.edges.get(&edge_key(a, b)) {
                    None => unreachable!(),
                    Some(edge) => {
                        Some((b, edge))
                    }
                }
            }
        }
    }
}

/// Index **GraphMap** by node pairs to access edge weights.
impl<N, E> Index<(N, N)> for GraphMap<N, E> where N: NodeTrait
{
    type Output = E;
    fn index(&self, index: (N, N)) -> &E
    {
        self.edge_weight(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}

/// Index **GraphMap** by node pairs to access edge weights.
impl<N, E> IndexMut<(N, N)> for GraphMap<N, E> where N: NodeTrait
{
    fn index_mut(&mut self, index: (N, N)) -> &mut E
    {
        self.edge_weight_mut(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}
<|endoftext|>


<commit_before>#![feature(path_ext)]
#[cfg(not(windows))]
extern crate pkg_config;
use std::fs::{self, PathExt};
use std::env;
use std::path::Path;
use std::process::Command;

#[cfg(windows)]
static FINAL_LIB:&'static str = "libjit.dll";

#[cfg(not(windows))]
static FINAL_LIB:&'static str = "libjit.a";

static MINGW:&'static str = "c:/mingw";

static INSTALL_AUTOTOOLS_MSG:&'static str = "Failed to generate configuration script. Did you forget to install autotools, bison, flex, and libtool?";

static USE_CARGO_MSG:&'static str = "Build script should be ran with Cargo, run `cargo build` instead";

#[cfg(windows)]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install MinGW and MSYS?";
#[cfg(not(windows))]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install a C compiler?";

fn main() {
	if cfg!(windows) && !Path::new(MINGW).exists() {
		panic!("{}", INSTALL_COMPILER_MSG);
	} else if pkg_config::find_library("jit").is_ok() {
		println!("Copy of LibJIT found on system - no need to build");
		return;
	}
	let out_dir = env::var("OUT_DIR").ok().expect(USE_CARGO_MSG);
	let num_jobs = env::var("NUM_JOBS").ok().expect(USE_CARGO_MSG);
	let target = env::var("TARGET").ok().expect(USE_CARGO_MSG);
	let out_dir = Path::new(&*out_dir);
    let submod_path = Path::new(&env::var("CARGO_MANIFEST_DIR").ok().expect(USE_CARGO_MSG)).join("libjit");
	let final_lib_dir = submod_path.join("jit/.libs");
	if !final_lib_dir.join(FINAL_LIB).exists() {
		Command::new("git")
			.args(&["submodule", "init"])
			.status().unwrap();
		run(Command::new("git")
			.args(&["submodule", "update"]),
			None
		);
		if !submod_path.exists() {
			run(Command::new("git")
				.args(&["clone", "git://git.savannah.gnu.org/libjit.git", submod_path.to_str().unwrap()]),
				None
			)
		}
		run(
			Command::new("sh")
				.current_dir(&submod_path)
				.arg("auto_gen.sh"),
			Some(INSTALL_AUTOTOOLS_MSG)
		);
		run(
			Command::new("sh")
				.current_dir(&submod_path)
				.env("CFLAGS", "-fPIC")
				.args(&[
					"configure", "--enable-static", "--disable-shared", &format!("--host={}", target)
				]),
			Some(INSTALL_COMPILER_MSG)
		);
		run(Command::new("make")
			.arg(&format!("-j{}", num_jobs))
			.current_dir(submod_path),
			None
		);
	} else {
		println!("LibJIT has already been built")
	}
	let from = final_lib_dir.join(FINAL_LIB);
	let to = out_dir.join(FINAL_LIB);
	if let Err(error) = fs::copy(&from, &to) {
		panic!("Failed to copy library from {:?} to {:?} due to {}", from, to, error)
	}
	println!("cargo:rustc-link-search=native={:?}", out_dir);
	println!("cargo:rustc-link-lib=static=jit");
}
fn run(cmd: &mut Command, text: Option<&str>) {
	if !cmd.status().unwrap().success() {
		let text = text.map(|text| format!(" - {}", text)).unwrap_or(String::new());
		panic!("{:?} failed{}", cmd, text)
	}
}
<commit_msg>Don't quote cargo:rustc-link-search argument<commit_after>#![feature(path_ext)]
#[cfg(not(windows))]
extern crate pkg_config;
use std::fs::{self, PathExt};
use std::env;
use std::path::Path;
use std::process::Command;

#[cfg(windows)]
static FINAL_LIB:&'static str = "libjit.dll";

#[cfg(not(windows))]
static FINAL_LIB:&'static str = "libjit.a";

static MINGW:&'static str = "c:/mingw";

static INSTALL_AUTOTOOLS_MSG:&'static str = "Failed to generate configuration script. Did you forget to install autotools, bison, flex, and libtool?";

static USE_CARGO_MSG:&'static str = "Build script should be ran with Cargo, run `cargo build` instead";

#[cfg(windows)]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install MinGW and MSYS?";
#[cfg(not(windows))]
static INSTALL_COMPILER_MSG:&'static str = "Failed to configure the library for your platform. Did you forget to install a C compiler?";

fn main() {
	if cfg!(windows) && !Path::new(MINGW).exists() {
		panic!("{}", INSTALL_COMPILER_MSG);
	} else if pkg_config::find_library("jit").is_ok() {
		println!("Copy of LibJIT found on system - no need to build");
		return;
	}
	let out_dir = env::var("OUT_DIR").ok().expect(USE_CARGO_MSG);
	let num_jobs = env::var("NUM_JOBS").ok().expect(USE_CARGO_MSG);
	let target = env::var("TARGET").ok().expect(USE_CARGO_MSG);
	let out_dir = Path::new(&*out_dir);
    let submod_path = Path::new(&env::var("CARGO_MANIFEST_DIR").ok().expect(USE_CARGO_MSG)).join("libjit");
	let final_lib_dir = submod_path.join("jit/.libs");
	if !final_lib_dir.join(FINAL_LIB).exists() {
		Command::new("git")
			.args(&["submodule", "init"])
			.status().unwrap();
		run(Command::new("git")
			.args(&["submodule", "update"]),
			None
		);
		if !submod_path.exists() {
			run(Command::new("git")
				.args(&["clone", "git://git.savannah.gnu.org/libjit.git", submod_path.to_str().unwrap()]),
				None
			)
		}
		run(
			Command::new("sh")
				.current_dir(&submod_path)
				.arg("auto_gen.sh"),
			Some(INSTALL_AUTOTOOLS_MSG)
		);
		run(
			Command::new("sh")
				.current_dir(&submod_path)
				.env("CFLAGS", "-fPIC")
				.args(&[
					"configure", "--enable-static", "--disable-shared", &format!("--host={}", target)
				]),
			Some(INSTALL_COMPILER_MSG)
		);
		run(Command::new("make")
			.arg(&format!("-j{}", num_jobs))
			.current_dir(submod_path),
			None
		);
	} else {
		println!("LibJIT has already been built")
	}
	let from = final_lib_dir.join(FINAL_LIB);
	let to = out_dir.join(FINAL_LIB);
	if let Err(error) = fs::copy(&from, &to) {
		panic!("Failed to copy library from {:?} to {:?} due to {}", from, to, error)
	}
	println!("cargo:rustc-link-search=native={}",
                 out_dir.to_str().expect("non-unicode characters in path"));
	println!("cargo:rustc-link-lib=static=jit");
}
fn run(cmd: &mut Command, text: Option<&str>) {
	if !cmd.status().unwrap().success() {
		let text = text.map(|text| format!(" - {}", text)).unwrap_or(String::new());
		panic!("{:?} failed{}", cmd, text)
	}
}
<|endoftext|>


<commit_before>/// A cache block number.
///
/// Every cache block is assigned a number which is associated with the block in memory.
type BlockNumber = usize;

/// A cache block.
///
/// This stores a single sector in memory, for more performant reads and writes.
///
/// The terminology "cache block" is similar to "cache lines" in CPUs. They represent a single
/// fixed-size block which is cached in memory.
struct Block {
    /// The sector the block stores.
    sector: disk::Sector,
    /// The data of the sector.
    ///
    /// This shall reflect what is on the disk unless the block is marked dirty.
    data: Box<[u8]>,
    /// Does the data in memory reflect the data on the disk?
    ///
    /// This is called _the dirty flag_ and defines if a flush is needed or if the in-memory data
    /// already matches the on-disk data. Whenever it is written in memory, the flag should be set
    /// so that we're sure that it gets flushed properly to the disk.
    dirty: bool,
    /// Disk sectors that shall be flushed _before_ this block.
    ///
    /// This defines the flush dependencies and is crucial to the consistency of the cache. In
    /// particular, ordering matters, since unexpected crashes should never leave the system in an
    /// inconsistent state.
    ///
    /// To consider flush ordering, we define a poset on the cache blocks. If `A < B`, `A` should
    /// be written prior to `B`. This is represented as an ADG. The algorithm for flushing is:
    /// write the orphan nodes to the disk, until no nodes are dirty.
    ///
    /// In other words, the sectors in this vector are _guaranteed_ to be written before the block
    /// itself.
    flush_dependencies: Vec<disk::Sector>,
}

impl Block {
    /// Reset the cache block.
    ///
    /// This resets the dirty flag and clears the flush dependencies.
    ///
    /// Note that it does not change the data or the sector.
    fn reset(&mut self) {
        // The cache block starts out as clean...
        self.dirty = false;
        // ...and hence has no dependencies.
        self.flush_dependencies.clear();
    }

    /// Add a sector to flush before the block.
    fn add_dependency(&mut self, sector: disk::Sector) {
        // To avoid meta-cycles, we make sure that the dependent sector isn't the sector of the
        // block itself.
        if self.sector != sector {
            self.flush_dependencies.push(sector);
        }
    }
}

/// A cached disk.
///
/// This wrapper manages caching and the consistency issues originating from it.
///
/// It organizes the cache into _cache blocks_ each representing some _disk sector_. The cache
/// blocks are put in a _dependency graph_ which enforces the ordering of flushes (writes to
/// disks).
struct Cache<D> {
    /// The raw disk.
    disk: D,
    /// The cache replacement tracker.
    ///
    /// This tracks the state of the replacement algorithm, which chooses which cache block shall
    /// be replaced in favor of a new cache. It serves to estimate/guess which block is likely not
    /// used in the near future. This guessed block is then replaced by a fresh new cache block.
    cache_tracker: plru::DynamicCache,
    /// The sector-to-cache-block map.
    ///
    /// This associates the disk sector with its respective cache block.
    block_map: RwLock<HashMap<disk::Sector, BlockNumber>>,
    /// The cache blocks.
    blocks: RwLock<Vec<[RwLock<Block>]>>,
    /// The pipeline of writes to-be-committed.
    ///
    /// These are not committed to the block map yet and will not be until `.commit()` is called.
    /// They are ensured to be written to the disk in the order of the pipeline.
    pipeline: Vec<(disk::Sector, Box<[u8]>)>,
}

impl<D: Disk> Cached<D> {
    /// Flush a cache block to the disk.
    ///
    /// This can potentially trigger outer flushes if the cache block has flush dependencies.
    ///
    /// Note that this doesn't commit the pipeline.
    pub fn flush(&mut self, block: BlockNumber) -> Result<(), disk::Error> {
        // Read the block.
        let block = &mut self.blocks[block];

        // Flush all the dependencies. This is important for correct ordering!
        for sector_dep in block.flush_dependencies {
            if let Some(block_dep) = self.block_map.get(sector_dep) {
                self.flush(block_dep)?;
            }
            // It could happen naturally that the dependent sector was not found in the block
            // map. Namely, if the sector was replaced by another cache block. In such case, the
            // sector is naturally already flushed (during replacement) and thus there is no
            // consistency issues.
        }

        // Check if the block is (still) dirty.
        if block.dirty {
            // Write the block to the disk.
            self.disk.write(block.sector, &block.data)?;
            // Unset the dirty flag.
            block.dirty = false;
        }
    }

    /// Read a sector from the disk.
    ///
    /// Note that this does not respond to writes in the pipeline, only committed transactions.
    pub fn read(&self, sector: disk::Sector) -> Result<&[u8], disk::Error> {
        Ok(self.get(sector)?.data)
    }

    /// Queue a write to the pipeline.
    ///
    /// This pushes a transaction to the pipeline, which can be committed through `.commit()`.
    pub fn queue(&mut self, sector: disk::Sector, buf: Box<[u8]>) {
        self.pipeline.push((sector, buf));
    }

    /// Revert the pipeline and drop the transactions.
    ///
    /// This clears the transactions in the pipeline without commiting them. It can be used when an
    /// operation fails and you need to return to a consistent state.
    pub fn revert(&mut self) {
        self.pipeline.clear();
    }

    /// Commit the transactions in the pipeline to the cache.
    ///
    /// This commits the sectors and data given in the pipeline in the specified order enforcing
    /// consistency with respect to the flush order.
    pub fn commit(&mut self) {
        if Some((first_sector, first_buf)) = writes.next() {
            // Write the first block which has no dependencies.
            let mut block = self.commit_write(first_sector, first_buf, None);

            // Write the rest with the previous write as dependency.
            for (sector, buf) in self.pipeline.drain() {
                block = self.commit_write(sector, buf, Some(block.sector));
            }
        }
    }

    /// Commits a sector write with some dependency.
    ///
    /// This writes `buf` into sector `sector` in the cache, ensuring that the sector (if any)
    /// `dependency` is flushed to the disk prior to `sector`.
    fn commit_write(&mut self, sector: cluster::Pointer, buf: Box<[u8]>, dependency: Option<disk::Sector>) -> &mut Block {
        // Allocate a new cache block.
        let block_number = cache.alloc_block();
        let block = &mut cache.blocks[block_number];

        // Put the data into the freshly allocated cache block.
        block.data = buf;

        // Update the sector number.
        block.sector = sector;
        // Add the potential dependency to the cache block.
        if let Some(dependency) = dependency {
            block.add_dependency(dependency)
        }
        // Mark dirty.
        block.dirty = true;

        // Update the cache block map with the new block.
        cache.block_map.insert(sector, block_number);

        block
    }

    /// Allocate (or find replacement) for a new cache block.
    ///
    /// This finds a cache block which can be used for new objects.
    ///
    /// It will reset and flush the block and update the block map.
    fn alloc_block(&mut self) -> BlockNumber {
        // Test if the cache is filled.
        if self.blocks.len() < self.cache_tracker.len() {
            // The cache is not filled, so we don't need to replace any cache block, we can simply
            // push.
            self.blocks.push(Block {
                sector: sector,
                data: vec![0; disk::SECTOR_SIZE],
                dirty: false,
                flush_dependencies: Vec::new(),
            });

            self.blocks.len() - 1
        } else {
            // Find a candidate for replacement.
            let block_number = self.cache_tracker.replace();

            // Flush it to the disk before throwing the data away.
            self.flush(block_number);

            // Remove the old sector from the cache block map.
            let block = &mut self.blocks[block_number];
            self.block_map.remove(block.sector);

            // Reset the cache block.
            block.reset();

            block_number
        }
    }

    /// Fetch an uncached disk sector to the cache.
    ///
    /// This will fetch `sector` from the disk to store it in the in-memory cache structure.
    fn fetch_fresh(&mut self, sector: disk::Sector) -> Result<&mut Block, disk::Error> {
        // Allocate a new cache block.
        let block_number = self.alloc_block();
        let block = &mut self.blocks[block_number];

        // Read the sector from the disk.
        self.disk.read(sector, &mut block.data)?;

        // Update the sector number.
        block.sector = sector;

        // Update the cache block map with the new block.
        self.block_map.insert(sector, block_number);
    }

    /// Get the cache block for a sector.
    ///
    /// This grabs the sector from the cache or from the disk, if necessary.
    fn get(&mut self, sector: disk::Sector) -> Result<&mut Block, disk::Error> {
        // Check if the sector already exists in the cache.
        if let Some(block) = self.block_map.get_mut(sector) {
            // It did!

            // Touch the cache block.
            self.cache_tracker.touch(block);

            // Read the block.
            Ok(&mut self.blocks[block])
        } else {
            // It didn't, so we read it from the disk:
            self.fetch_fresh(sector)
        }
    }
}
<commit_msg>Describe the exact guarantees that the pipeline ordering makes.<commit_after>/// A cache block number.
///
/// Every cache block is assigned a number which is associated with the block in memory.
type BlockNumber = usize;

/// A cache block.
///
/// This stores a single sector in memory, for more performant reads and writes.
///
/// The terminology "cache block" is similar to "cache lines" in CPUs. They represent a single
/// fixed-size block which is cached in memory.
struct Block {
    /// The sector the block stores.
    sector: disk::Sector,
    /// The data of the sector.
    ///
    /// This shall reflect what is on the disk unless the block is marked dirty.
    data: Box<[u8]>,
    /// Does the data in memory reflect the data on the disk?
    ///
    /// This is called _the dirty flag_ and defines if a flush is needed or if the in-memory data
    /// already matches the on-disk data. Whenever it is written in memory, the flag should be set
    /// so that we're sure that it gets flushed properly to the disk.
    dirty: bool,
    /// Disk sectors that shall be flushed _before_ this block.
    ///
    /// This defines the flush dependencies and is crucial to the consistency of the cache. In
    /// particular, ordering matters, since unexpected crashes should never leave the system in an
    /// inconsistent state.
    ///
    /// To consider flush ordering, we define a poset on the cache blocks. If `A < B`, `A` should
    /// be written prior to `B`. This is represented as an ADG. The algorithm for flushing is:
    /// write the orphan nodes to the disk, until no nodes are dirty.
    ///
    /// In other words, the sectors in this vector are _guaranteed_ to be written before the block
    /// itself.
    flush_dependencies: Vec<disk::Sector>,
}

impl Block {
    /// Reset the cache block.
    ///
    /// This resets the dirty flag and clears the flush dependencies.
    ///
    /// Note that it does not change the data or the sector.
    fn reset(&mut self) {
        // The cache block starts out as clean...
        self.dirty = false;
        // ...and hence has no dependencies.
        self.flush_dependencies.clear();
    }

    /// Add a sector to flush before the block.
    fn add_dependency(&mut self, sector: disk::Sector) {
        // To avoid meta-cycles, we make sure that the dependent sector isn't the sector of the
        // block itself.
        if self.sector != sector {
            self.flush_dependencies.push(sector);
        }
    }
}

/// A cached disk.
///
/// This wrapper manages caching and the consistency issues originating from it.
///
/// It organizes the cache into _cache blocks_ each representing some _disk sector_. The cache
/// blocks are put in a _dependency graph_ which enforces the ordering of flushes (writes to
/// disks).
struct Cache<D> {
    /// The raw disk.
    disk: D,
    /// The cache replacement tracker.
    ///
    /// This tracks the state of the replacement algorithm, which chooses which cache block shall
    /// be replaced in favor of a new cache. It serves to estimate/guess which block is likely not
    /// used in the near future. This guessed block is then replaced by a fresh new cache block.
    cache_tracker: plru::DynamicCache,
    /// The sector-to-cache-block map.
    ///
    /// This associates the disk sector with its respective cache block.
    block_map: RwLock<HashMap<disk::Sector, BlockNumber>>,
    /// The cache blocks.
    blocks: RwLock<Vec<[RwLock<Block>]>>,
    /// The pipeline of writes to-be-committed.
    ///
    /// These are not committed to the block map yet and will not be until `.commit()` is called.
    /// They are ensured to be written to the disk in the order of the pipeline.
    pipeline: Vec<(disk::Sector, Box<[u8]>)>,
}

impl<D: Disk> Cached<D> {
    /// Flush a cache block to the disk.
    ///
    /// This can potentially trigger outer flushes if the cache block has flush dependencies.
    ///
    /// Note that this doesn't commit the pipeline.
    pub fn flush(&mut self, block: BlockNumber) -> Result<(), disk::Error> {
        // Read the block.
        let block = &mut self.blocks[block];

        // Flush all the dependencies. This is important for correct ordering!
        for sector_dep in block.flush_dependencies {
            if let Some(block_dep) = self.block_map.get(sector_dep) {
                self.flush(block_dep)?;
            }
            // It could happen naturally that the dependent sector was not found in the block
            // map. Namely, if the sector was replaced by another cache block. In such case, the
            // sector is naturally already flushed (during replacement) and thus there is no
            // consistency issues.
        }

        // Check if the block is (still) dirty.
        if block.dirty {
            // Write the block to the disk.
            self.disk.write(block.sector, &block.data)?;
            // Unset the dirty flag.
            block.dirty = false;
        }
    }

    /// Read a sector from the disk.
    ///
    /// Note that this does not respond to writes in the pipeline, only committed transactions.
    pub fn read(&self, sector: disk::Sector) -> Result<&[u8], disk::Error> {
        Ok(self.get(sector)?.data)
    }

    /// Queue a write to the pipeline.
    ///
    /// This pushes a transaction to the pipeline, which can be committed through `.commit()`.
    pub fn queue(&mut self, sector: disk::Sector, buf: Box<[u8]>) {
        self.pipeline.push((sector, buf));
    }

    /// Revert the pipeline and drop the transactions.
    ///
    /// This clears the transactions in the pipeline without commiting them. It can be used when an
    /// operation fails and you need to return to a consistent state.
    pub fn revert(&mut self) {
        self.pipeline.clear();
    }

    /// Commit the transactions in the pipeline to the cache.
    ///
    /// This commits the sectors and data given in the pipeline in the specified order enforcing
    /// consistency with respect to the flush order. To understand what this means, one must see
    /// writes as a function from a valid state to another together with the constraint that
    /// another function is applied prior to that. In other words, it does not enforce that they're
    /// written sequentially — or even written at all. Transactions can be forwarded backwards and
    /// merged with other transactions, but this should not leave the system inconsistent, since
    /// the _ordering_ is still enforced.
    ///
    /// More formally, we can think of the pipeline as a totally ordered set. When it is committed,
    /// every transaction is put into totally ordered set of transactions, such that the
    /// transactions preserving their order in the pipeline. If two transactions "collide" (are
    /// writing to the same sector), the newest one is picked and the old one is thrown away.
    pub fn commit(&mut self) {
        if Some((first_sector, first_buf)) = writes.next() {
            // Write the first block which has no dependencies.
            let mut block = self.commit_write(first_sector, first_buf, None);

            // Write the rest with the previous write as dependency.
            for (sector, buf) in self.pipeline.drain() {
                block = self.commit_write(sector, buf, Some(block.sector));
            }
        }
    }

    /// Commits a sector write with some dependency.
    ///
    /// This writes `buf` into sector `sector` in the cache, ensuring that the sector (if any)
    /// `dependency` is flushed to the disk prior to `sector`.
    fn commit_write(&mut self, sector: cluster::Pointer, buf: Box<[u8]>, dependency: Option<disk::Sector>) -> &mut Block {
        // Allocate a new cache block.
        let block_number = cache.alloc_block();
        let block = &mut cache.blocks[block_number];

        // Put the data into the freshly allocated cache block.
        block.data = buf;

        // Update the sector number.
        block.sector = sector;
        // Add the potential dependency to the cache block.
        if let Some(dependency) = dependency {
            block.add_dependency(dependency)
        }
        // Mark dirty.
        block.dirty = true;

        // Update the cache block map with the new block.
        cache.block_map.insert(sector, block_number);

        block
    }

    /// Allocate (or find replacement) for a new cache block.
    ///
    /// This finds a cache block which can be used for new objects.
    ///
    /// It will reset and flush the block and update the block map.
    fn alloc_block(&mut self) -> BlockNumber {
        // Test if the cache is filled.
        if self.blocks.len() < self.cache_tracker.len() {
            // The cache is not filled, so we don't need to replace any cache block, we can simply
            // push.
            self.blocks.push(Block {
                sector: sector,
                data: vec![0; disk::SECTOR_SIZE],
                dirty: false,
                flush_dependencies: Vec::new(),
            });

            self.blocks.len() - 1
        } else {
            // Find a candidate for replacement.
            let block_number = self.cache_tracker.replace();

            // Flush it to the disk before throwing the data away.
            self.flush(block_number);

            // Remove the old sector from the cache block map.
            let block = &mut self.blocks[block_number];
            self.block_map.remove(block.sector);

            // Reset the cache block.
            block.reset();

            block_number
        }
    }

    /// Fetch an uncached disk sector to the cache.
    ///
    /// This will fetch `sector` from the disk to store it in the in-memory cache structure.
    fn fetch_fresh(&mut self, sector: disk::Sector) -> Result<&mut Block, disk::Error> {
        // Allocate a new cache block.
        let block_number = self.alloc_block();
        let block = &mut self.blocks[block_number];

        // Read the sector from the disk.
        self.disk.read(sector, &mut block.data)?;

        // Update the sector number.
        block.sector = sector;

        // Update the cache block map with the new block.
        self.block_map.insert(sector, block_number);
    }

    /// Get the cache block for a sector.
    ///
    /// This grabs the sector from the cache or from the disk, if necessary.
    fn get(&mut self, sector: disk::Sector) -> Result<&mut Block, disk::Error> {
        // Check if the sector already exists in the cache.
        if let Some(block) = self.block_map.get_mut(sector) {
            // It did!

            // Touch the cache block.
            self.cache_tracker.touch(block);

            // Read the block.
            Ok(&mut self.blocks[block])
        } else {
            // It didn't, so we read it from the disk:
            self.fetch_fresh(sector)
        }
    }
}
<|endoftext|>