<commit_before>use super::*;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Item {
    pub ident: Ident,
    pub vis: Visibility,
    pub attrs: Vec<Attribute>,
    pub generics: Generics,
    pub body: Body,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Body {
    Enum(Vec<Variant>),
    Struct(Style, Vec<Field>),
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Variant {
    pub ident: Ident,
    pub attrs: Vec<Attribute>,
    pub style: Style,
    pub fields: Vec<Field>,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Style {
    Struct,
    Tuple,
    Unit,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Field {
    pub ident: Option<Ident>,
    pub vis: Visibility,
    pub attrs: Vec<Attribute>,
    pub ty: Ty,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use attr::parsing::attribute;
    use common::parsing::{word, visibility};
    use generics::parsing::generics;
    use ty::parsing::ty;
    use nom::multispace;

    named!(pub item<&str, Item>, do_parse!(
        attrs: many0!(attribute) >>
        vis: visibility >>
        which: alt!(tag_s!("struct") | tag_s!("enum")) >>
        multispace >>
        ident: word >>
        generics: generics >>
        item: switch!(value!(which),
            "struct" => map!(struct_body, move |(style, fields)| Item {
                ident: ident,
                vis: vis,
                attrs: attrs,
                generics: generics,
                body: Body::Struct(style, fields),
            })
            |
            "enum" => map!(enum_body, move |body| Item {
                ident: ident,
                vis: vis,
                attrs: attrs,
                generics: generics,
                body: body,
            })
        ) >>
        opt!(multispace) >>
        (item)
    ));

    named!(struct_body<&str, (Style, Vec<Field>)>, alt!(
        struct_like_body => { |fields| (Style::Struct, fields) }
        |
        terminated!(tuple_like_body, punct!(";")) => { |fields| (Style::Tuple, fields) }
        |
        punct!(";") => { |_| (Style::Unit, Vec::new()) }
    ));

    named!(enum_body<&str, Body>, do_parse!(
        punct!("{") >>
        variants: separated_list!(punct!(","), variant) >>
        opt!(punct!(",")) >>
        punct!("}") >>
        (Body::Enum(variants))
    ));

    named!(variant<&str, Variant>, do_parse!(
        attrs: many0!(attribute) >>
        ident: word >>
        body: alt!(
            struct_like_body => { |fields| (Style::Struct, fields) }
            |
            tuple_like_body => { |fields| (Style::Tuple, fields) }
            |
            epsilon!() => { |_| (Style::Unit, Vec::new()) }
        ) >>
        (Variant {
            ident: ident,
            attrs: attrs,
            style: body.0,
            fields: body.1,
        })
    ));

    named!(struct_like_body<&str, Vec<Field> >, do_parse!(
        punct!("{") >>
        fields: separated_list!(punct!(","), struct_field) >>
        opt!(punct!(",")) >>
        punct!("}") >>
        (fields)
    ));

    named!(tuple_like_body<&str, Vec<Field> >, do_parse!(
        punct!("(") >>
        fields: separated_list!(punct!(","), tuple_field) >>
        opt!(punct!(",")) >>
        punct!(")") >>
        (fields)
    ));

    named!(struct_field<&str, Field>, do_parse!(
        attrs: many0!(attribute) >>
        vis: visibility >>
        ident: word >>
        punct!(":") >>
        ty: ty >>
        (Field {
            ident: Some(ident),
            vis: vis,
            attrs: attrs,
            ty: ty,
        })
    ));

    named!(tuple_field<&str, Field>, do_parse!(
        attrs: many0!(attribute) >>
        vis: visibility >>
        ty: ty >>
        (Field {
            ident: None,
            vis: vis,
            attrs: attrs,
            ty: ty,
        })
    ));
}

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

    impl ToTokens for Item {
        fn to_tokens(&self, tokens: &mut Tokens) {
            for attr in &self.attrs {
                attr.to_tokens(tokens);
            }
            if let Visibility::Public = self.vis {
                tokens.append("pub");
            }
            match self.body {
                Body::Enum(_) => tokens.append("enum"),
                Body::Struct(_, _) => tokens.append("struct"),
            }
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.body.to_tokens(tokens);
        }
    }

    impl ToTokens for Body {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Body::Enum(ref variants) => {
                    tokens.append("{");
                    for variant in variants {
                        variant.to_tokens(tokens);
                    }
                    tokens.append("}");
                }
                Body::Struct(style, ref fields) => {
                    fields_to_tokens(style, fields, tokens);
                    match style {
                        Style::Struct => { /* no semicolon */ }
                        Style::Tuple | Style::Unit => tokens.append(";"),
                    }
                }
            }
        }
    }

    impl ToTokens for Variant {
        fn to_tokens(&self, tokens: &mut Tokens) {
            for attr in &self.attrs {
                attr.to_tokens(tokens);
            }
            self.ident.to_tokens(tokens);
            fields_to_tokens(self.style, &self.fields, tokens);
        }
    }

    impl ToTokens for Field {
        fn to_tokens(&self, tokens: &mut Tokens) {
            for attr in &self.attrs {
                attr.to_tokens(tokens);
            }
            if let Visibility::Public = self.vis {
                tokens.append("pub");
            }
            if let Some(ref ident) = self.ident {
                ident.to_tokens(tokens);
                tokens.append(":");
            }
            self.ty.to_tokens(tokens);
        }
    }

    fn fields_to_tokens(style: Style, fields: &[Field], tokens: &mut Tokens) {
        match style {
            Style::Struct => {
                tokens.append("{");
                tokens.append_separated(fields, ",");
                tokens.append("}");
            }
            Style::Tuple => {
                tokens.append("(");
                tokens.append_separated(fields, ",");
                tokens.append(")");
            }
            Style::Unit => {
                assert!(fields.is_empty(), "unit variant cannot have fields");
            }
        }
    }
}
<commit_msg>Terminate enum variants with commas<commit_after>use super::*;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Item {
    pub ident: Ident,
    pub vis: Visibility,
    pub attrs: Vec<Attribute>,
    pub generics: Generics,
    pub body: Body,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Body {
    Enum(Vec<Variant>),
    Struct(Style, Vec<Field>),
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Variant {
    pub ident: Ident,
    pub attrs: Vec<Attribute>,
    pub style: Style,
    pub fields: Vec<Field>,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Style {
    Struct,
    Tuple,
    Unit,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Field {
    pub ident: Option<Ident>,
    pub vis: Visibility,
    pub attrs: Vec<Attribute>,
    pub ty: Ty,
}

#[cfg(feature = "parsing")]
pub mod parsing {
    use super::*;
    use attr::parsing::attribute;
    use common::parsing::{word, visibility};
    use generics::parsing::generics;
    use ty::parsing::ty;
    use nom::multispace;

    named!(pub item<&str, Item>, do_parse!(
        attrs: many0!(attribute) >>
        vis: visibility >>
        which: alt!(tag_s!("struct") | tag_s!("enum")) >>
        multispace >>
        ident: word >>
        generics: generics >>
        item: switch!(value!(which),
            "struct" => map!(struct_body, move |(style, fields)| Item {
                ident: ident,
                vis: vis,
                attrs: attrs,
                generics: generics,
                body: Body::Struct(style, fields),
            })
            |
            "enum" => map!(enum_body, move |body| Item {
                ident: ident,
                vis: vis,
                attrs: attrs,
                generics: generics,
                body: body,
            })
        ) >>
        opt!(multispace) >>
        (item)
    ));

    named!(struct_body<&str, (Style, Vec<Field>)>, alt!(
        struct_like_body => { |fields| (Style::Struct, fields) }
        |
        terminated!(tuple_like_body, punct!(";")) => { |fields| (Style::Tuple, fields) }
        |
        punct!(";") => { |_| (Style::Unit, Vec::new()) }
    ));

    named!(enum_body<&str, Body>, do_parse!(
        punct!("{") >>
        variants: separated_list!(punct!(","), variant) >>
        opt!(punct!(",")) >>
        punct!("}") >>
        (Body::Enum(variants))
    ));

    named!(variant<&str, Variant>, do_parse!(
        attrs: many0!(attribute) >>
        ident: word >>
        body: alt!(
            struct_like_body => { |fields| (Style::Struct, fields) }
            |
            tuple_like_body => { |fields| (Style::Tuple, fields) }
            |
            epsilon!() => { |_| (Style::Unit, Vec::new()) }
        ) >>
        (Variant {
            ident: ident,
            attrs: attrs,
            style: body.0,
            fields: body.1,
        })
    ));

    named!(struct_like_body<&str, Vec<Field> >, do_parse!(
        punct!("{") >>
        fields: separated_list!(punct!(","), struct_field) >>
        opt!(punct!(",")) >>
        punct!("}") >>
        (fields)
    ));

    named!(tuple_like_body<&str, Vec<Field> >, do_parse!(
        punct!("(") >>
        fields: separated_list!(punct!(","), tuple_field) >>
        opt!(punct!(",")) >>
        punct!(")") >>
        (fields)
    ));

    named!(struct_field<&str, Field>, do_parse!(
        attrs: many0!(attribute) >>
        vis: visibility >>
        ident: word >>
        punct!(":") >>
        ty: ty >>
        (Field {
            ident: Some(ident),
            vis: vis,
            attrs: attrs,
            ty: ty,
        })
    ));

    named!(tuple_field<&str, Field>, do_parse!(
        attrs: many0!(attribute) >>
        vis: visibility >>
        ty: ty >>
        (Field {
            ident: None,
            vis: vis,
            attrs: attrs,
            ty: ty,
        })
    ));
}

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

    impl ToTokens for Item {
        fn to_tokens(&self, tokens: &mut Tokens) {
            for attr in &self.attrs {
                attr.to_tokens(tokens);
            }
            if let Visibility::Public = self.vis {
                tokens.append("pub");
            }
            match self.body {
                Body::Enum(_) => tokens.append("enum"),
                Body::Struct(_, _) => tokens.append("struct"),
            }
            self.ident.to_tokens(tokens);
            self.generics.to_tokens(tokens);
            self.body.to_tokens(tokens);
        }
    }

    impl ToTokens for Body {
        fn to_tokens(&self, tokens: &mut Tokens) {
            match *self {
                Body::Enum(ref variants) => {
                    tokens.append("{");
                    for variant in variants {
                        variant.to_tokens(tokens);
                        tokens.append(",");
                    }
                    tokens.append("}");
                }
                Body::Struct(style, ref fields) => {
                    fields_to_tokens(style, fields, tokens);
                    match style {
                        Style::Struct => { /* no semicolon */ }
                        Style::Tuple | Style::Unit => tokens.append(";"),
                    }
                }
            }
        }
    }

    impl ToTokens for Variant {
        fn to_tokens(&self, tokens: &mut Tokens) {
            for attr in &self.attrs {
                attr.to_tokens(tokens);
            }
            self.ident.to_tokens(tokens);
            fields_to_tokens(self.style, &self.fields, tokens);
        }
    }

    impl ToTokens for Field {
        fn to_tokens(&self, tokens: &mut Tokens) {
            for attr in &self.attrs {
                attr.to_tokens(tokens);
            }
            if let Visibility::Public = self.vis {
                tokens.append("pub");
            }
            if let Some(ref ident) = self.ident {
                ident.to_tokens(tokens);
                tokens.append(":");
            }
            self.ty.to_tokens(tokens);
        }
    }

    fn fields_to_tokens(style: Style, fields: &[Field], tokens: &mut Tokens) {
        match style {
            Style::Struct => {
                tokens.append("{");
                tokens.append_separated(fields, ",");
                tokens.append("}");
            }
            Style::Tuple => {
                tokens.append("(");
                tokens.append_separated(fields, ",");
                tokens.append(")");
            }
            Style::Unit => {
                assert!(fields.is_empty(), "unit variant cannot have fields");
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    convert::TryFrom,
    fmt,
    hash::{Hash, Hasher},
    iter::FromIterator,
    ops::{Deref, DerefMut},
};

use crate::Arc;

const CUTOFF: usize = 22;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

impl Default for IVec {
    fn default() -> Self {
        Self::from(&[])
    }
}

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
    Subslice { base: Arc<[u8]>, offset: usize, len: usize },
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    /// Create a subslice of this `IVec` that shares
    /// the same backing data and reference counter.
    ///
    /// # Panics
    ///
    /// Panics if `self.len() - offset >= len`.
    ///
    /// # Examples
    /// ```
    /// # use sled::IVec;
    /// let iv = IVec::from(vec![1]);
    /// let subslice = iv.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = subslice.subslice(0, 0);
    /// assert_eq!(&subslice, &[]);
    ///
    /// let iv2 = IVec::from(vec![1, 2, 3]);
    /// let subslice = iv2.subslice(3, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = iv2.subslice(2, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = iv2.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = iv2.subslice(0, 3);
    /// assert_eq!(&subslice, &[1, 2, 3]);
    /// let subslice = subslice.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = subslice.subslice(1, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// ```
    pub fn subslice(&self, slice_offset: usize, len: usize) -> Self {
        assert!(self.len().checked_sub(slice_offset).unwrap() >= len);

        let inner = match self.0 {
            IVecInner::Remote(ref base) => IVecInner::Subslice {
                base: base.clone(),
                offset: slice_offset,
                len,
            },
            IVecInner::Inline(_, old_inner) => {
                // old length already checked above in assertion
                let mut new_inner = Inner::default();
                new_inner[..len].copy_from_slice(
                    &old_inner[slice_offset..slice_offset + len],
                );

                IVecInner::Inline(u8::try_from(len).unwrap(), new_inner)
            }
            IVecInner::Subslice { ref base, ref offset, .. } => {
                IVecInner::Subslice {
                    base: base.clone(),
                    offset: offset + slice_offset,
                    len,
                }
            }
        };

        IVec(inner)
    }

    fn inline(slice: &[u8]) -> Self {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        #[allow(unsafe_code)]
        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        Self(IVecInner::Inline(u8::try_from(slice.len()).unwrap(), data))
    }

    fn remote(arc: Arc<[u8]>) -> Self {
        Self(IVecInner::Remote(arc))
    }

    fn make_mut(&mut self) {
        match self.0 {
            IVecInner::Remote(ref mut buf) if Arc::strong_count(buf) != 1 => {
                self.0 = IVecInner::Remote(buf.to_vec().into());
            }
            IVecInner::Subslice { ref mut base, offset, len }
                if Arc::strong_count(base) != 1 =>
            {
                self.0 = IVecInner::Remote(
                    base[offset..offset + len].to_vec().into(),
                );
            }
            _ => {}
        }
    }
}

impl FromIterator<u8> for IVec {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = u8>,
    {
        let bs: Vec<u8> = iter.into_iter().collect();
        bs.into()
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> Self {
        if is_inline_candidate(b.len()) {
            Self::inline(&b)
        } else {
            Self::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> Self {
        if is_inline_candidate(slice.len()) {
            Self::inline(slice)
        } else {
            Self::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> Self {
        if is_inline_candidate(arc.len()) {
            Self::inline(&arc)
        } else {
            Self::remote(arc)
        }
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> Self {
        Self::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &Self) -> Self {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> Self {
        if is_inline_candidate(v.len()) {
            Self::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            Self::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> Self {
                    Self::from(&v[..])
                }
            }
        )*
    }
}

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

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
            IVecInner::Subslice { .. } => self.deref().into(),
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
            IVecInner::Subslice { ref base, offset, len } => {
                &base[*offset..*offset + *len]
            }
        }
    }
}

impl DerefMut for IVec {
    #[inline]
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl AsMut<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_mut(&mut self) -> &mut [u8] {
        self.make_mut();

        match &mut self.0 {
            IVecInner::Inline(ref sz, ref mut buf) => unsafe {
                std::slice::from_raw_parts_mut(buf.as_mut_ptr(), *sz as usize)
            },
            IVecInner::Remote(ref mut buf) => Arc::get_mut(buf).unwrap(),
            IVecInner::Subslice { ref mut base, ref offset, ref len } => {
                &mut Arc::get_mut(base).unwrap()[*offset..*offset + *len]
            }
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
fn boxed_slice_conversion() {
    let boite1: Box<[u8]> = Box::new([1, 2, 3]);
    let iv1: IVec = boite1.into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let boite2: Box<[u8]> = Box::new([4; 128]);
    let iv2: IVec = boite2.into();
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
#[should_panic]
fn subslice_usage_00() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(0, 4);
}

#[test]
#[should_panic]
fn subslice_usage_01() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(3, 1);
}

#[test]
fn ivec_as_mut_identity() {
    let initial = &[1];
    let mut iv = IVec::from(initial);
    assert_eq!(&*initial, &*iv);
    assert_eq!(&*initial, &mut *iv);
    assert_eq!(&*initial, iv.as_mut());
}

#[cfg(test)]
mod qc {
    use quickcheck::{Arbitrary, Gen};
    use rand::Rng;

    use super::IVec;

    fn prop_identity(ivec: IVec) -> bool {
        let mut iv2 = ivec.clone();

        if iv2 != ivec {
            println!("expected clone to equal original");
            return false;
        }

        if &*ivec != &mut *iv2 {
            println!("expected AsMut to equal original");
            return false;
        }

        if &*ivec != iv2.as_mut() {
            println!("expected AsMut to equal original");
            return false;
        }

        true
    }

    quickcheck::quickcheck! {
        #[cfg_attr(miri, ignore)]
        fn bool(item: IVec) -> bool {
            prop_identity(item)
        }
    }
}
<commit_msg>Small cleanup<commit_after>use std::{
    convert::TryFrom,
    fmt,
    hash::{Hash, Hasher},
    iter::FromIterator,
    ops::{Deref, DerefMut},
};

use crate::Arc;

const CUTOFF: usize = 22;

type Inner = [u8; CUTOFF];

/// A buffer that may either be inline or remote and protected
/// by an Arc
#[derive(Clone)]
pub struct IVec(IVecInner);

impl Default for IVec {
    fn default() -> Self {
        Self::from(&[])
    }
}

#[derive(Clone)]
enum IVecInner {
    Inline(u8, Inner),
    Remote(Arc<[u8]>),
    Subslice { base: Arc<[u8]>, offset: usize, len: usize },
}

impl Hash for IVec {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.deref().hash(state);
    }
}

const fn is_inline_candidate(length: usize) -> bool {
    length <= CUTOFF
}

impl IVec {
    /// Create a subslice of this `IVec` that shares
    /// the same backing data and reference counter.
    ///
    /// # Panics
    ///
    /// Panics if `self.len() - offset >= len`.
    ///
    /// # Examples
    /// ```
    /// # use sled::IVec;
    /// let iv = IVec::from(vec![1]);
    /// let subslice = iv.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(0, 1);
    /// assert_eq!(&subslice, &[1]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = subslice.subslice(0, 0);
    /// assert_eq!(&subslice, &[]);
    ///
    /// let iv2 = IVec::from(vec![1, 2, 3]);
    /// let subslice = iv2.subslice(3, 0);
    /// assert_eq!(&subslice, &[]);
    /// let subslice = iv2.subslice(2, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = iv2.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = iv2.subslice(0, 3);
    /// assert_eq!(&subslice, &[1, 2, 3]);
    /// let subslice = subslice.subslice(1, 2);
    /// assert_eq!(&subslice, &[2, 3]);
    /// let subslice = subslice.subslice(1, 1);
    /// assert_eq!(&subslice, &[3]);
    /// let subslice = subslice.subslice(1, 0);
    /// assert_eq!(&subslice, &[]);
    /// ```
    pub fn subslice(&self, slice_offset: usize, len: usize) -> Self {
        assert!(self.len().checked_sub(slice_offset).unwrap() >= len);

        let inner = match self.0 {
            IVecInner::Remote(ref base) => IVecInner::Subslice {
                base: base.clone(),
                offset: slice_offset,
                len,
            },
            IVecInner::Inline(_, old_inner) => {
                // old length already checked above in assertion
                let mut new_inner = Inner::default();
                new_inner[..len].copy_from_slice(
                    &old_inner[slice_offset..slice_offset + len],
                );

                IVecInner::Inline(u8::try_from(len).unwrap(), new_inner)
            }
            IVecInner::Subslice { ref base, ref offset, .. } => {
                IVecInner::Subslice {
                    base: base.clone(),
                    offset: offset + slice_offset,
                    len,
                }
            }
        };

        IVec(inner)
    }

    fn inline(slice: &[u8]) -> Self {
        assert!(is_inline_candidate(slice.len()));

        let mut data = Inner::default();

        #[allow(unsafe_code)]
        unsafe {
            std::ptr::copy_nonoverlapping(
                slice.as_ptr(),
                data.as_mut_ptr(),
                slice.len(),
            );
        }

        Self(IVecInner::Inline(u8::try_from(slice.len()).unwrap(), data))
    }

    fn remote(arc: Arc<[u8]>) -> Self {
        Self(IVecInner::Remote(arc))
    }

    fn make_mut(&mut self) {
        match self.0 {
            IVecInner::Remote(ref mut buf) if Arc::strong_count(buf) != 1 => {
                self.0 = IVecInner::Remote(buf.to_vec().into());
            }
            IVecInner::Subslice { ref mut base, offset, len }
                if Arc::strong_count(base) != 1 =>
            {
                self.0 = IVecInner::Remote(
                    base[offset..offset + len].to_vec().into(),
                );
            }
            _ => {}
        }
    }
}

impl FromIterator<u8> for IVec {
    fn from_iter<T>(iter: T) -> Self
    where
        T: IntoIterator<Item = u8>,
    {
        let bs: Vec<u8> = iter.into_iter().collect();
        bs.into()
    }
}

impl From<Box<[u8]>> for IVec {
    fn from(b: Box<[u8]>) -> Self {
        if is_inline_candidate(b.len()) {
            Self::inline(&b)
        } else {
            Self::remote(Arc::from(b))
        }
    }
}

impl From<&[u8]> for IVec {
    fn from(slice: &[u8]) -> Self {
        if is_inline_candidate(slice.len()) {
            Self::inline(slice)
        } else {
            Self::remote(Arc::from(slice))
        }
    }
}

impl From<Arc<[u8]>> for IVec {
    fn from(arc: Arc<[u8]>) -> Self {
        if is_inline_candidate(arc.len()) {
            Self::inline(&arc)
        } else {
            Self::remote(arc)
        }
    }
}

impl From<&str> for IVec {
    fn from(s: &str) -> Self {
        Self::from(s.as_bytes())
    }
}

impl From<&IVec> for IVec {
    fn from(v: &Self) -> Self {
        v.clone()
    }
}

impl From<Vec<u8>> for IVec {
    fn from(v: Vec<u8>) -> Self {
        if is_inline_candidate(v.len()) {
            Self::inline(&v)
        } else {
            // rely on the Arc From specialization
            // for Vec<T>, which may improve
            // over time
            Self::remote(Arc::from(v))
        }
    }
}

impl std::borrow::Borrow<[u8]> for IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

impl std::borrow::Borrow<[u8]> for &IVec {
    fn borrow(&self) -> &[u8] {
        self.as_ref()
    }
}

macro_rules! from_array {
    ($($s:expr),*) => {
        $(
            impl From<&[u8; $s]> for IVec {
                fn from(v: &[u8; $s]) -> Self {
                    Self::from(&v[..])
                }
            }
        )*
    }
}

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

impl Into<Arc<[u8]>> for IVec {
    fn into(self) -> Arc<[u8]> {
        match self.0 {
            IVecInner::Inline(..) => Arc::from(self.as_ref()),
            IVecInner::Remote(arc) => arc,
            IVecInner::Subslice { .. } => self.deref().into(),
        }
    }
}

impl Deref for IVec {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        self.as_ref()
    }
}

impl AsRef<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_ref(&self) -> &[u8] {
        match &self.0 {
            IVecInner::Inline(sz, buf) => unsafe {
                buf.get_unchecked(..*sz as usize)
            },
            IVecInner::Remote(buf) => buf,
            IVecInner::Subslice { ref base, offset, len } => {
                &base[*offset..*offset + *len]
            }
        }
    }
}

impl DerefMut for IVec {
    #[inline]
    fn deref_mut(&mut self) -> &mut [u8] {
        self.as_mut()
    }
}

impl AsMut<[u8]> for IVec {
    #[inline]
    #[allow(unsafe_code)]
    fn as_mut(&mut self) -> &mut [u8] {
        self.make_mut();

        match &mut self.0 {
            IVecInner::Inline(ref sz, ref mut buf) => unsafe {
                std::slice::from_raw_parts_mut(buf.as_mut_ptr(), *sz as usize)
            },
            IVecInner::Remote(ref mut buf) => Arc::get_mut(buf).unwrap(),
            IVecInner::Subslice { ref mut base, offset, len } => {
                &mut Arc::get_mut(base).unwrap()[*offset..*offset + *len]
            }
        }
    }
}

impl Ord for IVec {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.as_ref().cmp(other.as_ref())
    }
}

impl PartialOrd for IVec {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<T: AsRef<[u8]>> PartialEq<T> for IVec {
    fn eq(&self, other: &T) -> bool {
        self.as_ref() == other.as_ref()
    }
}

impl PartialEq<[u8]> for IVec {
    fn eq(&self, other: &[u8]) -> bool {
        self.as_ref() == other
    }
}

impl Eq for IVec {}

impl fmt::Debug for IVec {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.as_ref().fmt(f)
    }
}

#[test]
fn ivec_usage() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    assert_eq!(iv1, vec![1, 2, 3]);
    let iv2 = IVec::from(&[4; 128][..]);
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
fn boxed_slice_conversion() {
    let boite1: Box<[u8]> = Box::new([1, 2, 3]);
    let iv1: IVec = boite1.into();
    assert_eq!(iv1, vec![1, 2, 3]);
    let boite2: Box<[u8]> = Box::new([4; 128]);
    let iv2: IVec = boite2.into();
    assert_eq!(iv2, vec![4; 128]);
}

#[test]
#[should_panic]
fn subslice_usage_00() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(0, 4);
}

#[test]
#[should_panic]
fn subslice_usage_01() {
    let iv1 = IVec::from(vec![1, 2, 3]);
    let _subslice = iv1.subslice(3, 1);
}

#[test]
fn ivec_as_mut_identity() {
    let initial = &[1];
    let mut iv = IVec::from(initial);
    assert_eq!(&*initial, &*iv);
    assert_eq!(&*initial, &mut *iv);
    assert_eq!(&*initial, iv.as_mut());
}

#[cfg(test)]
mod qc {
    use quickcheck::{Arbitrary, Gen};
    use rand::Rng;

    use super::IVec;

    fn prop_identity(ivec: IVec) -> bool {
        let mut iv2 = ivec.clone();

        if iv2 != ivec {
            println!("expected clone to equal original");
            return false;
        }

        if &*ivec != &mut *iv2 {
            println!("expected AsMut to equal original");
            return false;
        }

        if &*ivec != iv2.as_mut() {
            println!("expected AsMut to equal original");
            return false;
        }

        true
    }

    quickcheck::quickcheck! {
        #[cfg_attr(miri, ignore)]
        fn bool(item: IVec) -> bool {
            prop_identity(item)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016 Cormac O'Brien
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
// and associated documentation files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
use std::io::{BufReader, Read};
use byteorder::{LittleEndian, ReadBytesExt};

pub trait Load: ReadBytesExt {
    fn read_u8(&mut self) -> u8 {
        ReadBytesExt::read_u8(self).unwrap()
    }

    fn read_u16le(&mut self) -> u16 {
        self.read_u16::<LittleEndian>().unwrap()
    }

    fn read_i16le(&mut self) -> i16 {
        self.read_i16::<LittleEndian>().unwrap()
    }

    fn read_u32le(&mut self) -> u32 {
        self.read_u32::<LittleEndian>().unwrap()
    }

    fn read_i32le(&mut self) -> i32 {
        self.read_i32::<LittleEndian>().unwrap()
    }

    fn read_f32le(&mut self) -> f32 {
        self.read_f32::<LittleEndian>().unwrap()
    }
}

impl<R> Load for BufReader<R> where R: Read {
}
<commit_msg>Rename read_* to load_* in Load trait<commit_after>// Copyright © 2016 Cormac O'Brien
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software
// and associated documentation files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

use std::convert::AsRef;
use std::io::{BufReader, Cursor, Read, Seek};
use byteorder::{LittleEndian, ReadBytesExt};

pub trait Load: ReadBytesExt + Seek {
    fn load_u8(&mut self) -> u8 {
        ReadBytesExt::read_u8(self).unwrap()
    }

    fn load_u16le(&mut self) -> u16 {
        self.read_u16::<LittleEndian>().unwrap()
    }

    fn load_i16le(&mut self) -> i16 {
        self.read_i16::<LittleEndian>().unwrap()
    }

    fn load_u32le(&mut self) -> u32 {
        self.read_u32::<LittleEndian>().unwrap()
    }

    fn load_i32le(&mut self) -> i32 {
        self.read_i32::<LittleEndian>().unwrap()
    }

    fn load_f32le(&mut self) -> f32 {
        self.read_f32::<LittleEndian>().unwrap()
    }
}

impl<R> Load for BufReader<R> where R: Read + Seek {
}

impl<T> Load for Cursor<T> where T: AsRef<[u8]> {
}
<|endoftext|>


<commit_before>use unix_socket::UnixStream;

use std::io::{Result, Read, Write};
use std::io::Error;
use std::io::ErrorKind::Other;

use parser::{LvmTextMap, TextMapOps, into_textmap};
use vg;
use parser;

const LVMETAD_PATH: &'static str = "/run/lvm/lvmetad.socket";

fn collect_response(stream: &mut UnixStream) -> Result<Vec<u8>> {
    let mut response = [0; 32];
    let mut v = Vec::new();

    loop {
        let bytes_read = try!(stream.read(&mut response));

        v.extend(&response[..bytes_read]);

        if v.ends_with(b"\n##\n") {
            // drop the end marker
            let len = v.len() - 4;
            v.truncate(len);
            return Ok(v);
        }
    }
}

pub fn _request(s: &[u8], token: Option<&[u8]>, stream: &mut UnixStream, args: Option<&[&[u8]]>) -> Result<Vec<u8>> {
    try!(stream.write_all(b"request = \""));
    try!(stream.write_all(s));
    try!(stream.write_all(b"\"\n"));
    if let Some(token) = token {
        try!(stream.write_all(b"token = \""));
        try!(stream.write_all(token));
        try!(stream.write_all(b"\"\n"));
        try!(stream.write_all(b"\n"));
    }
    if let Some(args) = args {
        for arg in args {
            try!(stream.write_all(arg));
            try!(stream.write_all(b"\n"));
        }
    }

    try!(stream.write_all(b"\n##\n"));

    collect_response(stream)
}

pub fn request(s: &[u8], args: Option<&[&[u8]]>) -> Result<LvmTextMap> {
    let err = || Error::new(Other, "response parsing error");
    let token = b"0";

    let mut stream = try!(UnixStream::connect(LVMETAD_PATH));

    let mut response = try!(_request(s, Some(token), &mut stream, args)
        .and_then(|r| into_textmap(&r)));

    if try!(response.string_from_textmap("response").ok_or(err())) == "token_mismatch" {
        try!(_request(b"token_update", Some(token), &mut stream, None));
        response = try!(_request(s, Some(token), &mut stream, args)
            .and_then(|r| into_textmap(&r)));
    }

    if response.get("global_invalid").is_some() || response.get("vg_invalid").is_some() {
        return Err(Error::new(Other, "cached metadata flagged as invalid"));
    }

    if try!(response.string_from_textmap("response").ok_or(err())) != "OK" {
        let reason = match response.string_from_textmap("reason") {
            Some(x) => x,
            None => "no reason given",
        };
        return Err(Error::new(Other, reason));
    }

    response.remove("response");

    Ok(response)
}

pub fn vgs_from_lvmetad() -> Result<Vec<vg::VG>> {
let err = || Error::new(Other, "response parsing error");
    let mut v = Vec::new();

    let vg_list = try!(request(b"vg_list", None));
    let vgs = try!(vg_list.textmap_from_textmap("volume_groups").ok_or(err()));

    for id in vgs.keys() {
        let name = try!(vgs.textmap_from_textmap(id)
                        .and_then(|val| val.string_from_textmap("name"))
                        .ok_or(err()));

        let mut option: Vec<u8> = Vec::new();
        option.extend(b"uuid = \"");
        option.extend(id.as_bytes());
        option.extend(b"\"");
        let options = vec!(&option[..]);

        let vg_info = try!(request(b"vg_lookup", Some(&options[..])));
        let md = try!(vg_info.textmap_from_textmap("metadata").ok_or(err()));

        let vg = parser::vg_from_textmap(&name, md).expect("didn't get vg!");

        v.push(vg);
    }

    Ok(v)
}
<commit_msg>lvmetad: whitespace<commit_after>use unix_socket::UnixStream;

use std::io::{Result, Read, Write};
use std::io::Error;
use std::io::ErrorKind::Other;

use parser::{LvmTextMap, TextMapOps, into_textmap};
use vg;
use parser;

const LVMETAD_PATH: &'static str = "/run/lvm/lvmetad.socket";

fn collect_response(stream: &mut UnixStream) -> Result<Vec<u8>> {
    let mut response = [0; 32];
    let mut v = Vec::new();

    loop {
        let bytes_read = try!(stream.read(&mut response));

        v.extend(&response[..bytes_read]);

        if v.ends_with(b"\n##\n") {
            // drop the end marker
            let len = v.len() - 4;
            v.truncate(len);
            return Ok(v);
        }
    }
}

pub fn _request(s: &[u8],
                token: Option<&[u8]>,
                stream: &mut UnixStream,
                args: Option<&[&[u8]]>) -> Result<Vec<u8>> {
    try!(stream.write_all(b"request = \""));
    try!(stream.write_all(s));
    try!(stream.write_all(b"\"\n"));

    if let Some(token) = token {
        try!(stream.write_all(b"token = \""));
        try!(stream.write_all(token));
        try!(stream.write_all(b"\"\n"));
        try!(stream.write_all(b"\n"));
    }

    if let Some(args) = args {
        for arg in args {
            try!(stream.write_all(arg));
            try!(stream.write_all(b"\n"));
        }
    }

    try!(stream.write_all(b"\n##\n"));

    collect_response(stream)
}

pub fn request(s: &[u8], args: Option<&[&[u8]]>) -> Result<LvmTextMap> {
    let err = || Error::new(Other, "response parsing error");
    let token = b"0";

    let mut stream = try!(UnixStream::connect(LVMETAD_PATH));

    let mut response = try!(_request(s, Some(token), &mut stream, args)
        .and_then(|r| into_textmap(&r)));

    if try!(response.string_from_textmap("response").ok_or(err())) == "token_mismatch" {
        try!(_request(b"token_update", Some(token), &mut stream, None));
        response = try!(_request(s, Some(token), &mut stream, args)
            .and_then(|r| into_textmap(&r)));
    }

    if response.get("global_invalid").is_some() || response.get("vg_invalid").is_some() {
        return Err(Error::new(Other, "cached metadata flagged as invalid"));
    }

    if try!(response.string_from_textmap("response").ok_or(err())) != "OK" {
        let reason = match response.string_from_textmap("reason") {
            Some(x) => x,
            None => "no reason given",
        };
        return Err(Error::new(Other, reason));
    }

    response.remove("response");

    Ok(response)
}

pub fn vgs_from_lvmetad() -> Result<Vec<vg::VG>> {
    let err = || Error::new(Other, "response parsing error");
    let mut v = Vec::new();

    let vg_list = try!(request(b"vg_list", None));
    let vgs = try!(vg_list.textmap_from_textmap("volume_groups").ok_or(err()));

    for id in vgs.keys() {
        let name = try!(vgs.textmap_from_textmap(id)
                        .and_then(|val| val.string_from_textmap("name"))
                        .ok_or(err()));

        let mut option: Vec<u8> = Vec::new();
        option.extend(b"uuid = \"");
        option.extend(id.as_bytes());
        option.extend(b"\"");
        let options = vec!(&option[..]);

        let vg_info = try!(request(b"vg_lookup", Some(&options[..])));
        let md = try!(vg_info.textmap_from_textmap("metadata").ok_or(err()));

        let vg = parser::vg_from_textmap(&name, md).expect("didn't get vg!");

        v.push(vg);
    }

    Ok(v)
}
<|endoftext|>


<commit_before>extern crate rand;
mod zdt1;
mod gaussian_mutation;
use rand::{random, Closed01};
use zdt1::zdt1;
use gaussian_mutation::gaussian_mutation;

#[derive(Copy, Clone, Debug)]
struct Solution {
    parameters: [f32; 30],
    objectives: [f32; 2],
}

fn initialise_population(initial_population: bool) -> [Solution; 100] {
    let mut population = [Solution {
        parameters: [0_f32; 30],
        objectives: [0_f32; 2],
    }; 100];

    if initial_population {
        for solution in &mut population[..] {
            for parameter in &mut solution.parameters[..] {
                let Closed01(parameter) = random::<Closed01<f32>>();
            }

            solution.objectives = zdt1(solution.parameters);
        }
    }

    return population;
}

fn main() {
    let generations = 10;
    let mutation_rate = 0.2_f32;
    let mut parent_population = initialise_population(true);
    let mut offspring_population = initialise_population(false);

    for gen in 0..generations {
        for solution in &mut parent_population[..] {
            solution.parameters = gaussian_mutation(solution.parameters, mutation_rate);
            solution.objectives = zdt1(solution.parameters);
        }
    }
}
<commit_msg>Corrected randomisation of initial parameters<commit_after>extern crate rand;
mod zdt1;
mod gaussian_mutation;
use rand::{random, Closed01};
use zdt1::zdt1;
use gaussian_mutation::gaussian_mutation;

#[derive(Copy, Clone, Debug)]
struct Solution {
    parameters: [f32; 30],
    objectives: [f32; 2],
}

fn initialise_population(initial_population: bool) -> [Solution; 100] {
    let mut population = [Solution {
        parameters: [0_f32; 30],
        objectives: [0_f32; 2],
    }; 100];

    if initial_population {
        for solution in &mut population[..] {
            for parameter in &mut solution.parameters[..] {
                *parameter = random::<Closed01<f32>>().0;
            }

            solution.objectives = zdt1(solution.parameters);
        }
    }

    return population;
}

fn main() {
    let generations = 10;
    let mutation_rate = 0.2_f32;
    let mut parent_population = initialise_population(true);
    let mut offspring_population = initialise_population(false);

    for gen in 0..generations {
        for solution in &mut parent_population[..] {
            solution.parameters = gaussian_mutation(solution.parameters, mutation_rate);
            solution.objectives = zdt1(solution.parameters);
        }
    }
}
<|endoftext|>


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

pub mod protocol;
pub mod format;
pub mod nbt;
pub mod item;
pub mod gl;
pub mod types;
pub mod resources;
pub mod render;
pub mod ui;
pub mod screen;
#[macro_use]
pub mod console;

extern crate glutin;
extern crate image;
extern crate time;
extern crate byteorder;
extern crate serde_json;
extern crate steven_openssl as openssl;
extern crate hyper;
extern crate flate2;
extern crate rand;
extern crate rustc_serialize;
#[macro_use]
extern crate log;

use std::sync::{Arc, RwLock, Mutex};
use std::marker::PhantomData;

const CL_BRAND: console::CVar<String> = console::CVar {
    ty: PhantomData,
    name: "cl_brand",
    description: "cl_brand has the value of the clients current 'brand'. \
                e.g. \"Steven\" or \"Vanilla\"",
    mutable: false,
    serializable: false,
    default: &|| "steven".to_owned(),
};

pub struct Game {
    renderer: render::Renderer,
    screen_sys: screen::ScreenSystem,
    resource_manager: Arc<RwLock<resources::Manager>>,
    console: Arc<Mutex<console::Console>>,
    should_close: bool,
    mouse_pos: (i32, i32),
}

fn main() {
    let con = Arc::new(Mutex::new(console::Console::new()));
    {
        let mut con = con.lock().unwrap();
        con.register(CL_BRAND);
        con.load_config();
        con.save_config();
    }

    let proxy = console::ConsoleProxy::new(con.clone());

    log::set_logger(|max_log_level| {
        max_log_level.set(log::LogLevelFilter::Trace);
        Box::new(proxy)
    }).unwrap();

    info!("Starting steven");

    let resource_manager = Arc::new(RwLock::new(resources::Manager::new()));
    { resource_manager.write().unwrap().tick(); }

    let mut window = glutin::WindowBuilder::new()
        .with_title("Steven".to_string())
        .with_dimensions(854, 480)
        .with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 2)))
        .with_gl_profile(glutin::GlProfile::Core)
        .with_depth_buffer(24)
        .with_stencil_buffer(0)
        .with_vsync()
        .build().ok().expect("Could not create Glutin window.");

    unsafe {
        window.make_current().ok().expect("Could not set current context.");
    }

    gl::init(&mut window);

    let renderer = render::Renderer::new(resource_manager.clone());
    let mut ui_container = ui::Container::new();

    let mut last_frame = time::now();
    let frame_time = (time::Duration::seconds(1).num_nanoseconds().unwrap() as f64) / 60.0;

    let mut screen_sys = screen::ScreenSystem::new();
    screen_sys.add_screen(Box::new(screen::Login::new()));

    let mut game = Game {
        renderer: renderer,
        screen_sys: screen_sys,
        resource_manager: resource_manager,
        console: con,
        should_close: false,
        mouse_pos: (0, 0),
    };

    while !game.should_close {
        { game.resource_manager.write().unwrap().tick(); }

        let now = time::now();
        let diff = now - last_frame;
        last_frame = now;
        let delta = (diff.num_nanoseconds().unwrap() as f64) / frame_time;
        let (width, height) = window.get_inner_size_pixels().unwrap();

        game.screen_sys.tick(delta, &mut game.renderer, &mut ui_container);
        game.console.lock().unwrap().tick(&mut ui_container, &mut game.renderer, delta, width as f64);
        ui_container.tick(&mut game.renderer, delta, width as f64, height as f64);
        game.renderer.tick(delta, width, height);

        let _ = window.swap_buffers();

        for event in window.poll_events() {
            handle_window_event(&window, &mut game, &mut ui_container, event)
        }
    }
}

fn handle_window_event(window: &glutin::Window, game: &mut Game, ui_container: &mut ui::Container, event: glutin::Event) {
    match event {
        glutin::Event::Closed => game.should_close = true,

        glutin::Event::MouseMoved((x, y)) => {
            game.mouse_pos = (x, y);
            let (width, height) = window.get_inner_size_pixels().unwrap();

            ui_container.hover_at(game, x as f64, y as f64, width as f64, height as f64);
        },

        glutin::Event::MouseInput(glutin::ElementState::Released, glutin::MouseButton::Left) => {
            let (x, y) = game.mouse_pos;
            let (width, height) = window.get_inner_size_pixels().unwrap();

            ui_container.click_at(game, x as f64, y as f64, width as f64, height as f64);
        },

        glutin::Event::MouseWheel(delta) => {
            let (x, y) = match delta {
                glutin::MouseScrollDelta::LineDelta(x, y) => (x, y),
                glutin::MouseScrollDelta::PixelDelta(x, y) => (x, y)
            };

            game.screen_sys.on_scroll(x as f64, y as f64);
        },

        glutin::Event::KeyboardInput(glutin::ElementState::Pressed, 41 /* ` GRAVE */, _) => {
            game.console.lock().unwrap().toggle();
        },

        glutin::Event::KeyboardInput(glutin::ElementState::Pressed, key, _) => {
            println!("Key: {:?}", key);
        },

        _ => ()
    }
}
<commit_msg>Fix the console on linux<commit_after>// Copyright 2015 Matthew Collins
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

pub mod protocol;
pub mod format;
pub mod nbt;
pub mod item;
pub mod gl;
pub mod types;
pub mod resources;
pub mod render;
pub mod ui;
pub mod screen;
#[macro_use]
pub mod console;

extern crate glutin;
extern crate image;
extern crate time;
extern crate byteorder;
extern crate serde_json;
extern crate steven_openssl as openssl;
extern crate hyper;
extern crate flate2;
extern crate rand;
extern crate rustc_serialize;
#[macro_use]
extern crate log;

use std::sync::{Arc, RwLock, Mutex};
use std::marker::PhantomData;

const CL_BRAND: console::CVar<String> = console::CVar {
    ty: PhantomData,
    name: "cl_brand",
    description: "cl_brand has the value of the clients current 'brand'. \
                e.g. \"Steven\" or \"Vanilla\"",
    mutable: false,
    serializable: false,
    default: &|| "steven".to_owned(),
};

pub struct Game {
    renderer: render::Renderer,
    screen_sys: screen::ScreenSystem,
    resource_manager: Arc<RwLock<resources::Manager>>,
    console: Arc<Mutex<console::Console>>,
    should_close: bool,
    mouse_pos: (i32, i32),
}

fn main() {
    let con = Arc::new(Mutex::new(console::Console::new()));
    {
        let mut con = con.lock().unwrap();
        con.register(CL_BRAND);
        con.load_config();
        con.save_config();
    }

    let proxy = console::ConsoleProxy::new(con.clone());

    log::set_logger(|max_log_level| {
        max_log_level.set(log::LogLevelFilter::Trace);
        Box::new(proxy)
    }).unwrap();

    info!("Starting steven");

    let resource_manager = Arc::new(RwLock::new(resources::Manager::new()));
    { resource_manager.write().unwrap().tick(); }

    let mut window = glutin::WindowBuilder::new()
        .with_title("Steven".to_string())
        .with_dimensions(854, 480)
        .with_gl(glutin::GlRequest::Specific(glutin::Api::OpenGl, (3, 2)))
        .with_gl_profile(glutin::GlProfile::Core)
        .with_depth_buffer(24)
        .with_stencil_buffer(0)
        .with_vsync()
        .build().ok().expect("Could not create Glutin window.");

    unsafe {
        window.make_current().ok().expect("Could not set current context.");
    }

    gl::init(&mut window);

    let renderer = render::Renderer::new(resource_manager.clone());
    let mut ui_container = ui::Container::new();

    let mut last_frame = time::now();
    let frame_time = (time::Duration::seconds(1).num_nanoseconds().unwrap() as f64) / 60.0;

    let mut screen_sys = screen::ScreenSystem::new();
    screen_sys.add_screen(Box::new(screen::Login::new()));

    let mut game = Game {
        renderer: renderer,
        screen_sys: screen_sys,
        resource_manager: resource_manager,
        console: con,
        should_close: false,
        mouse_pos: (0, 0),
    };

    while !game.should_close {
        { game.resource_manager.write().unwrap().tick(); }

        let now = time::now();
        let diff = now - last_frame;
        last_frame = now;
        let delta = (diff.num_nanoseconds().unwrap() as f64) / frame_time;
        let (width, height) = window.get_inner_size_pixels().unwrap();

        game.screen_sys.tick(delta, &mut game.renderer, &mut ui_container);
        game.console.lock().unwrap().tick(&mut ui_container, &mut game.renderer, delta, width as f64);
        ui_container.tick(&mut game.renderer, delta, width as f64, height as f64);
        game.renderer.tick(delta, width, height);

        let _ = window.swap_buffers();

        for event in window.poll_events() {
            handle_window_event(&window, &mut game, &mut ui_container, event)
        }
    }
}

fn handle_window_event(window: &glutin::Window, game: &mut Game, ui_container: &mut ui::Container, event: glutin::Event) {
    use glutin::{Event, VirtualKeyCode};
    match event {
        Event::Closed => game.should_close = true,

        Event::MouseMoved((x, y)) => {
            game.mouse_pos = (x, y);
            let (width, height) = window.get_inner_size_pixels().unwrap();

            ui_container.hover_at(game, x as f64, y as f64, width as f64, height as f64);
        },

        Event::MouseInput(glutin::ElementState::Released, glutin::MouseButton::Left) => {
            let (x, y) = game.mouse_pos;
            let (width, height) = window.get_inner_size_pixels().unwrap();

            ui_container.click_at(game, x as f64, y as f64, width as f64, height as f64);
        },

        Event::MouseWheel(delta) => {
            let (x, y) = match delta {
                glutin::MouseScrollDelta::LineDelta(x, y) => (x, y),
                glutin::MouseScrollDelta::PixelDelta(x, y) => (x, y)
            };

            game.screen_sys.on_scroll(x as f64, y as f64);
        },

        Event::KeyboardInput(glutin::ElementState::Pressed, 41 /* ` GRAVE */, _) => {
            game.console.lock().unwrap().toggle();
        },
        Event::KeyboardInput(glutin::ElementState::Pressed, _, Some(VirtualKeyCode::Grave)) => {
            game.console.lock().unwrap().toggle();
        },
        Event::KeyboardInput(glutin::ElementState::Pressed, key, virt) => {
            println!("Key: {:?} {:?}", key, virt);
        },

        _ => ()
    }
}
<|endoftext|>


<commit_before>use std::env;

extern crate git2;
extern crate tiny_http;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";

fn main() {
    println!("Cloning crates.io-index");
    git2::Repository::clone(INDEX_GIT_URL, "crates.io-index").unwrap();

    let port = match env::var("PORT") {
        Ok(p) => p.parse::<u16>().unwrap(),
        Err(..) => 8000,
    };

    let server = tiny_http::ServerBuilder::new().with_port(port).build().unwrap();

    println!("Server listening on port {}", port);
    for request in server.incoming_requests() {
        println!("received request! method: {:?}, url: {:?}, headers: {:?}",
            request.get_method(),
            request.get_url(),
            request.get_headers()
        );

        let response = tiny_http::Response::from_string("hello world".to_string());
        request.respond(response);
    }
}
<commit_msg>Use static str<commit_after>use std::env;

extern crate git2;
extern crate tiny_http;

static INDEX_GIT_URL: &'static str = "https://github.com/rust-lang/crates.io-index";
static INDEX_LOCAL_PATH: &'static str = "crates.io-index";

fn main() {
    println!("Cloning crates.io-index");
    git2::Repository::clone(INDEX_GIT_URL, INDEX_LOCAL_PATH).unwrap();

    let port = match env::var("PORT") {
        Ok(p) => p.parse::<u16>().unwrap(),
        Err(..) => 8000,
    };

    let server = tiny_http::ServerBuilder::new().with_port(port).build().unwrap();

    println!("Server listening on port {}", port);
    for request in server.incoming_requests() {
        println!("received request! method: {:?}, url: {:?}, headers: {:?}",
            request.get_method(),
            request.get_url(),
            request.get_headers()
        );

        let response = tiny_http::Response::from_string("hello world".to_string());
        request.respond(response);
    }
}
<|endoftext|>


<commit_before>extern crate alpm;
#[macro_use]
extern crate clap;
extern crate curl;
extern crate env_logger;
extern crate itertools;
#[macro_use]
extern crate log;
extern crate rustc_serialize;

use clap::App;
use curl::easy::Easy;
use itertools::Itertools;
use rustc_serialize::json::Json;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::default::Default;
use std::process::exit;
use std::str;

#[derive(Debug, Clone)]
struct ASA {
    cve: Vec<String>,
    version: Option<String>,
}

impl Default for ASA {
    fn default() -> ASA {
        ASA {
            cve: vec![],
            version: None,
        }
    }
}

#[derive(Debug)]
struct Options {
    format: Option<String>,
    quiet: u64,
    upgradable_only: bool,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            format: None,
            quiet: 0,
            upgradable_only: false,
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let yaml = load_yaml!("cli.yml");
    let args = App::from_yaml(yaml).get_matches();

    let options = Options {
        format: {
            match args.value_of("format") {
                Some(f) => Some(f.to_string()),
                None => None,
            }
        },
        quiet: args.occurrences_of("quiet"),
        upgradable_only: args.is_present("upgradable"),
    };

    let mut avgs = String::new();
    {
        info!("Downloading AVGs...");
        let avgs_url = "https://security.archlinux.org/json";

        let mut easy = Easy::new();
        easy.url(avgs_url).unwrap();
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
                avgs.push_str(str::from_utf8(data).unwrap());
                Ok(data.len())
            })
            .unwrap();
        match transfer.perform() {
            Ok(_) => {}
            Err(_) => {
                println!("Cannot fetch data, please check your network connection!");
                exit(1)
            }
        };
    }

    let pacman = match args.value_of("dbpath") {
        Some(path) => alpm::Alpm::with_dbpath(path.to_string()).unwrap(),
        None => alpm::Alpm::new().unwrap(),
    };

    let mut cves: HashMap<String, Vec<_>> = HashMap::new();
    {
        let json = Json::from_str(&avgs).unwrap();

        for avg in json.as_array().unwrap() {
            let packages = avg["packages"]
                .as_array()
                .unwrap()
                .iter()
                .map(|s| s.as_string().unwrap().to_string())
                .collect::<Vec<_>>();

            if !package_is_installed(&pacman, &packages) {
                continue;
            }

            let info = ASA {
                cve: avg["issues"]
                    .as_array()
                    .unwrap()
                    .iter()
                    .map(|s| s.as_string().unwrap().to_string())
                    .collect(),
                version: match avg["fixed"].as_string() {
                    Some(s) => Some(s.to_string()),
                    None => None,
                },
            };

            let status = avg["status"].as_string().unwrap();

            if !status.starts_with("Not affected") {
                for p in packages {
                    match cves.entry(p) {
                            Occupied(c) => c.into_mut(),
                            Vacant(c) => c.insert(vec![]),
                        }
                        .push(info.clone());
                }
            }
        }
    }

    let mut affected_cves: HashMap<String, Vec<_>> = HashMap::new();
    for (pkg, asas) in cves {
        for asa in &asas {
            if system_is_affected(&pacman, &pkg, &asa) {
                match affected_cves.entry(pkg.clone()) {
                        Occupied(c) => c.into_mut(),
                        Vacant(c) => c.insert(vec![]),
                    }
                    .push(asa.clone());
            }
        }
    }

    let merged = merge_asas(&pacman, &affected_cves);
    print_asas(&options, &merged);
}

/// Given a package and an ASA, returns true if the system is affected
fn system_is_affected(pacman: &alpm::Alpm, pkg: &String, asa: &ASA) -> bool {
    match pacman.query_package_version(pkg.clone()) {
        Ok(v) => {
            info!("Found installed version {} for package {}", v, pkg);
            match asa.version {
                Some(ref version) => {
                    info!("Comparing with fixed version {}", version);
                    match pacman.vercmp(v.clone(), version.clone()).unwrap() {
                        Ordering::Less => return true,
                        _ => {}
                    };
                }
                None => return true,
            };
        }
        Err(_) => debug!("Package {} not installed", pkg),
    }

    return false;
}

#[test]
fn test_system_is_affected() {
    let pacman = alpm::Alpm::new().unwrap();

    let cve1 = ASA {
        cve: vec!["CVE-1".to_string(), "CVE-2".to_string()],
        version: Some("1.0.0".to_string()),
    };

    assert_eq!(false,
               system_is_affected(&pacman, &"pacman".to_string(), &cve1));

    let cve2 = ASA {
        cve: vec!["CVE-1".to_string(), "CVE-2".to_string()],
        version: Some("7.0.0".to_string()),
    };
    assert!(system_is_affected(&pacman, &"pacman".to_string(), &cve2));
}

/// Given a list of package names, returns true when at least one is installed
fn package_is_installed(pacman: &alpm::Alpm, packages: &Vec<String>) -> bool {
    for pkg in packages {
        match pacman.query_package_version(pkg.as_str()) {
            Ok(_) => {
                info!("Package {} is installed", pkg);
                return true;
            }
            Err(_) => debug!("Package {} not installed", pkg),
        }
    }
    return false;
}

#[test]
fn test_package_is_installed() {
    let pacman = alpm::Alpm::new().unwrap();

    let packages = vec!["pacman".to_string(), "pac".to_string()];
    assert!(package_is_installed(&pacman, &packages));

    let packages = vec!["pac".to_string()];
    assert_eq!(false, package_is_installed(&pacman, &packages));
}

/// Merge a list of ASAs into a single ASA using major version as version
fn merge_asas(pacman: &alpm::Alpm, cves: &HashMap<String, Vec<ASA>>) -> HashMap<String, ASA> {
    let mut asas: HashMap<String, ASA> = HashMap::new();
    for (pkg, list) in cves.iter() {
        let mut asa_cve = vec![];
        let mut asa_version: Option<String> = None;

        for a in list.iter() {
            asa_cve.append(&mut a.cve.clone());

            match asa_version.clone() {
                Some(ref version) => {
                    match a.version {
                        Some(ref v) => {
                            match pacman.vercmp(version.to_string(), v.to_string()).unwrap() {
                                Ordering::Greater => asa_version = a.version.clone(),
                                _ => {}
                            }
                        }
                        None => {}
                    }
                }
                None => asa_version = a.version.clone(),
            }
        }

        let asa = ASA {
            cve: asa_cve,
            version: asa_version,
        };
        asas.insert(pkg.to_string(), asa);
    }

    asas
}

#[test]
fn test_merge_asas() {
    let mut affected_cves: HashMap<String, Vec<_>> = HashMap::new();

    let asa1 = ASA {
        cve: vec!["CVE-1".to_string(), "CVE-2".to_string()],
        version: Some("1.0.0".to_string()),
    };

    let asa2 = ASA {
        cve: vec!["CVE-4".to_string(), "CVE-10".to_string()],
        version: Some("0.9.8".to_string()),
    };

    affected_cves.insert("package".to_string(), vec![asa1.clone(), asa2.clone()]);

    affected_cves.insert("package2".to_string(), vec![asa1, asa2]);

    let pacman = alpm::Alpm::new().unwrap();
    let merged = merge_asas(&pacman, &affected_cves);

    assert_eq!(2, merged.len());
    assert_eq!(4, merged.get(&"package".to_string()).unwrap().cve.len());
}

/// Print a list of ASAs
fn print_asas(options: &Options, cves: &HashMap<String, ASA>) {
    for (pkg, asa) in cves {
        let msg = format!("Package {} is affected by {:?}", pkg, asa.cve);

        match asa.version {
            Some(ref v) => {
                if options.quiet == 1 {
                    println!("{}>={}", pkg, v);
                } else if options.quiet >= 2 {
                    println!("{}", pkg);
                } else {
                    match options.format {
                        Some(ref f) => {
                            println!("{}",
                                     f.replace("%n", pkg.as_str())
                                         .replace("%c", asa.cve.iter().join(",").as_str()))
                        }
                        None => println!("{}. Update to {}!", msg, v),
                    }
                }
            }
            None => {
                if !options.upgradable_only {
                    if options.quiet > 0 {
                        println!("{}", pkg);
                    } else {
                        match options.format {
                            Some(ref f) => {
                                println!("{}",
                                         f.replace("%n", pkg.as_str())
                                             .replace("%c", asa.cve.iter().join(",").as_str()))
                            }
                            None => println!("{}. VULNERABLE!", msg),
                        }
                    }
                }
            }
        }
    }
}
<commit_msg>Sort packages by name<commit_after>extern crate alpm;
#[macro_use]
extern crate clap;
extern crate curl;
extern crate env_logger;
extern crate itertools;
#[macro_use]
extern crate log;
extern crate rustc_serialize;

use clap::App;
use curl::easy::Easy;
use itertools::Itertools;
use rustc_serialize::json::Json;
use std::cmp::Ordering;
use std::collections::BTreeMap;
use std::collections::btree_map::Entry::{Occupied, Vacant};
use std::default::Default;
use std::process::exit;
use std::str;

#[derive(Debug, Clone)]
struct ASA {
    cve: Vec<String>,
    version: Option<String>,
}

impl Default for ASA {
    fn default() -> ASA {
        ASA {
            cve: vec![],
            version: None,
        }
    }
}

#[derive(Debug)]
struct Options {
    format: Option<String>,
    quiet: u64,
    upgradable_only: bool,
}

impl Default for Options {
    fn default() -> Options {
        Options {
            format: None,
            quiet: 0,
            upgradable_only: false,
        }
    }
}

fn main() {
    env_logger::init().unwrap();

    let yaml = load_yaml!("cli.yml");
    let args = App::from_yaml(yaml).get_matches();

    let options = Options {
        format: {
            match args.value_of("format") {
                Some(f) => Some(f.to_string()),
                None => None,
            }
        },
        quiet: args.occurrences_of("quiet"),
        upgradable_only: args.is_present("upgradable"),
    };

    let mut avgs = String::new();
    {
        info!("Downloading AVGs...");
        let avgs_url = "https://security.archlinux.org/json";

        let mut easy = Easy::new();
        easy.url(avgs_url).unwrap();
        let mut transfer = easy.transfer();
        transfer.write_function(|data| {
                avgs.push_str(str::from_utf8(data).unwrap());
                Ok(data.len())
            })
            .unwrap();
        match transfer.perform() {
            Ok(_) => {}
            Err(_) => {
                println!("Cannot fetch data, please check your network connection!");
                exit(1)
            }
        };
    }

    let pacman = match args.value_of("dbpath") {
        Some(path) => alpm::Alpm::with_dbpath(path.to_string()).unwrap(),
        None => alpm::Alpm::new().unwrap(),
    };

    let mut cves: BTreeMap<String, Vec<_>> = BTreeMap::new();
    {
        let json = Json::from_str(&avgs).unwrap();

        for avg in json.as_array().unwrap() {
            let packages = avg["packages"]
                .as_array()
                .unwrap()
                .iter()
                .map(|s| s.as_string().unwrap().to_string())
                .collect::<Vec<_>>();

            if !package_is_installed(&pacman, &packages) {
                continue;
            }

            let info = ASA {
                cve: avg["issues"]
                    .as_array()
                    .unwrap()
                    .iter()
                    .map(|s| s.as_string().unwrap().to_string())
                    .collect(),
                version: match avg["fixed"].as_string() {
                    Some(s) => Some(s.to_string()),
                    None => None,
                },
            };

            let status = avg["status"].as_string().unwrap();

            if !status.starts_with("Not affected") {
                for p in packages {
                    match cves.entry(p) {
                            Occupied(c) => c.into_mut(),
                            Vacant(c) => c.insert(vec![]),
                        }
                        .push(info.clone());
                }
            }
        }
    }

    let mut affected_cves: BTreeMap<String, Vec<_>> = BTreeMap::new();
    for (pkg, asas) in cves {
        for asa in &asas {
            if system_is_affected(&pacman, &pkg, &asa) {
                match affected_cves.entry(pkg.clone()) {
                        Occupied(c) => c.into_mut(),
                        Vacant(c) => c.insert(vec![]),
                    }
                    .push(asa.clone());
            }
        }
    }

    let merged = merge_asas(&pacman, &affected_cves);
    print_asas(&options, &merged);
}

/// Given a package and an ASA, returns true if the system is affected
fn system_is_affected(pacman: &alpm::Alpm, pkg: &String, asa: &ASA) -> bool {
    match pacman.query_package_version(pkg.clone()) {
        Ok(v) => {
            info!("Found installed version {} for package {}", v, pkg);
            match asa.version {
                Some(ref version) => {
                    info!("Comparing with fixed version {}", version);
                    match pacman.vercmp(v.clone(), version.clone()).unwrap() {
                        Ordering::Less => return true,
                        _ => {}
                    };
                }
                None => return true,
            };
        }
        Err(_) => debug!("Package {} not installed", pkg),
    }

    return false;
}

#[test]
fn test_system_is_affected() {
    let pacman = alpm::Alpm::new().unwrap();

    let cve1 = ASA {
        cve: vec!["CVE-1".to_string(), "CVE-2".to_string()],
        version: Some("1.0.0".to_string()),
    };

    assert_eq!(false,
               system_is_affected(&pacman, &"pacman".to_string(), &cve1));

    let cve2 = ASA {
        cve: vec!["CVE-1".to_string(), "CVE-2".to_string()],
        version: Some("7.0.0".to_string()),
    };
    assert!(system_is_affected(&pacman, &"pacman".to_string(), &cve2));
}

/// Given a list of package names, returns true when at least one is installed
fn package_is_installed(pacman: &alpm::Alpm, packages: &Vec<String>) -> bool {
    for pkg in packages {
        match pacman.query_package_version(pkg.as_str()) {
            Ok(_) => {
                info!("Package {} is installed", pkg);
                return true;
            }
            Err(_) => debug!("Package {} not installed", pkg),
        }
    }
    return false;
}

#[test]
fn test_package_is_installed() {
    let pacman = alpm::Alpm::new().unwrap();

    let packages = vec!["pacman".to_string(), "pac".to_string()];
    assert!(package_is_installed(&pacman, &packages));

    let packages = vec!["pac".to_string()];
    assert_eq!(false, package_is_installed(&pacman, &packages));
}

/// Merge a list of ASAs into a single ASA using major version as version
fn merge_asas(pacman: &alpm::Alpm, cves: &BTreeMap<String, Vec<ASA>>) -> BTreeMap<String, ASA> {
    let mut asas: BTreeMap<String, ASA> = BTreeMap::new();
    for (pkg, list) in cves.iter() {
        let mut asa_cve = vec![];
        let mut asa_version: Option<String> = None;

        for a in list.iter() {
            asa_cve.append(&mut a.cve.clone());

            match asa_version.clone() {
                Some(ref version) => {
                    match a.version {
                        Some(ref v) => {
                            match pacman.vercmp(version.to_string(), v.to_string()).unwrap() {
                                Ordering::Greater => asa_version = a.version.clone(),
                                _ => {}
                            }
                        }
                        None => {}
                    }
                }
                None => asa_version = a.version.clone(),
            }
        }

        let asa = ASA {
            cve: asa_cve,
            version: asa_version,
        };
        asas.insert(pkg.to_string(), asa);
    }

    asas
}

#[test]
fn test_merge_asas() {
    let mut affected_cves: BTreeMap<String, Vec<_>> = BTreeMap::new();

    let asa1 = ASA {
        cve: vec!["CVE-1".to_string(), "CVE-2".to_string()],
        version: Some("1.0.0".to_string()),
    };

    let asa2 = ASA {
        cve: vec!["CVE-4".to_string(), "CVE-10".to_string()],
        version: Some("0.9.8".to_string()),
    };

    affected_cves.insert("package".to_string(), vec![asa1.clone(), asa2.clone()]);

    affected_cves.insert("package2".to_string(), vec![asa1, asa2]);

    let pacman = alpm::Alpm::new().unwrap();
    let merged = merge_asas(&pacman, &affected_cves);

    assert_eq!(2, merged.len());
    assert_eq!(4, merged.get(&"package".to_string()).unwrap().cve.len());
}

/// Print a list of ASAs
fn print_asas(options: &Options, cves: &BTreeMap<String, ASA>) {
    for (pkg, asa) in cves {
        let msg = format!("Package {} is affected by {:?}", pkg, asa.cve);

        match asa.version {
            Some(ref v) => {
                if options.quiet == 1 {
                    println!("{}>={}", pkg, v);
                } else if options.quiet >= 2 {
                    println!("{}", pkg);
                } else {
                    match options.format {
                        Some(ref f) => {
                            println!("{}",
                                     f.replace("%n", pkg.as_str())
                                         .replace("%c", asa.cve.iter().join(",").as_str()))
                        }
                        None => println!("{}. Update to {}!", msg, v),
                    }
                }
            }
            None => {
                if !options.upgradable_only {
                    if options.quiet > 0 {
                        println!("{}", pkg);
                    } else {
                        match options.format {
                            Some(ref f) => {
                                println!("{}",
                                         f.replace("%n", pkg.as_str())
                                             .replace("%c", asa.cve.iter().join(",").as_str()))
                            }
                            None => println!("{}. VULNERABLE!", msg),
                        }
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate image;
extern crate toml;
extern crate rustc_serialize;

use std::cmp;
use std::env;
use std::thread;
use std::path::Path;
use image::ImageBuffer;

mod color;
mod math;
mod mesh;
mod primitive;
mod ray_tracer;
mod scene;

use ray_tracer::RayTracer;
use scene::Scene;

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 2 {
        println!("Usage: command <scene.toml>");
        return;
    }

    let path = Path::new(&args[1]);
    let scene = Scene::read(path).prepare();

    let threads = scene.threads;
    let handles: Vec<_> = (0..threads).map(|t| {
        let scene = scene.clone();
        thread::spawn(move || {
            let ray_tracer = RayTracer::new(&scene);
            let extra = if t == threads - 1 { scene.height % threads } else { 0 };
            let (h, w) = (scene.height / threads + extra, scene.width);
            let mut imgbuf = ImageBuffer::new(w, h);
            for y in (0..h) {
                for x in (0..w) {
                    let yy = t * h + y;
                    imgbuf.put_pixel(x, y, ray_tracer.trace_pixel(x, yy).rgb());
                }
            }
            imgbuf
        })
    }).collect();

    let imgbufs: Vec<_> = handles.into_iter().map(|h| h.join().unwrap()).collect();

    let mut imgbuf = ImageBuffer::new(scene.width, scene.height);
    for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
        let chunk_height = scene.height/threads;
        let t = cmp::min(threads-1, y / chunk_height);
        *pixel = *imgbufs[t as usize].get_pixel(x, y - t*chunk_height);
    }

    let fout = Path::new(&scene.image);
    let _ = imgbuf.save(fout);
    println!("Wrote file {:?}", fout);
}
<commit_msg>Clean up writing image<commit_after>extern crate image;
extern crate toml;
extern crate rustc_serialize;

use std::env;
use std::thread;
use std::path::Path;
use image::ImageBuffer;

mod color;
mod math;
mod mesh;
mod primitive;
mod ray_tracer;
mod scene;

use ray_tracer::RayTracer;
use scene::Scene;

fn main() {
    let args: Vec<_> = env::args().collect();
    if args.len() < 2 {
        println!("Usage: command <scene.toml>");
        return;
    }

    let path = Path::new(&args[1]);
    let scene = Scene::read(path).prepare();

    let threads = scene.threads;
    let handles: Vec<_> = (0..threads).map(|t| {
        let scene = scene.clone();
        thread::spawn(move || {
            let ray_tracer = RayTracer::new(&scene);
            let extra = if t == threads - 1 { scene.height % threads } else { 0 };
            let (h, w) = (scene.height / threads + extra, scene.width);
            let mut imgbuf = ImageBuffer::new(w, h);
            for y in (0..h) {
                for x in (0..w) {
                    let yy = t * h + y;
                    imgbuf.put_pixel(x, y, ray_tracer.trace_pixel(x, yy).rgb());
                }
            }
            imgbuf
        })
    }).collect();

    let chunk_bufs: Vec<_> = handles.into_iter().map(|h| { h.join().unwrap() }).collect();

    let mut imgbuf = ImageBuffer::new(scene.width, scene.height);
    let mut y_off = 0;
    for buf in chunk_bufs {
        for (x, y, pixel) in buf.enumerate_pixels() {
            imgbuf.put_pixel(x, y_off + y, *pixel);
        }
        y_off += buf.height();
    }

    let fout = Path::new(&scene.image);
    let _ = imgbuf.save(fout);
    println!("Wrote file {:?}", fout);
}
<|endoftext|>


<commit_before>extern crate case;
extern crate docopt;
extern crate env_logger;
extern crate git2;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate xml;
extern crate toml;

use std::error::Error;
use std::process;

use env::Env;
use library::Library;

//generated by build.rs
mod gir_version;

mod analysis;
mod codegen;
mod config;
mod env;
mod file_saver;
mod git;
mod gobjects;
mod library;
mod nameutil;
mod parser;
mod traits;
mod version;

#[cfg_attr(test, allow(dead_code))]
fn main() {
    if let Err(err) = do_main() {
        println!("{}", err);
        process::exit(1);
    }
}

fn do_main() -> Result<(), Box<Error>> {
    if std::env::var_os("RUST_LOG").is_none() {
        std::env::set_var("RUST_LOG", "gir=warn");
    }
    try!(env_logger::init());

    let cfg = match config::Config::new() {
        Ok(cfg) => cfg,
        Err(config::Error::CommandLine(ref err)) if !err.fatal() => return Ok(()),
        Err(err) => return Err(Box::new(err)),
    };

    let mut library = Library::new(&cfg.library_name);
    library.read_file(&cfg.girs_dir, &cfg.library_full_name());
    library.fill_in();

    let env = Env{ library: library, config: cfg };
    codegen::generate(&env);

    Ok(())
}
<commit_msg>Fix `--help` handling<commit_after>extern crate case;
extern crate docopt;
extern crate env_logger;
extern crate git2;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate xml;
extern crate toml;

use std::error::Error;
use std::process;

use env::Env;
use library::Library;

//generated by build.rs
mod gir_version;

mod analysis;
mod codegen;
mod config;
mod env;
mod file_saver;
mod git;
mod gobjects;
mod library;
mod nameutil;
mod parser;
mod traits;
mod version;

#[cfg_attr(test, allow(dead_code))]
fn main() {
    if let Err(err) = do_main() {
        println!("{}", err);
        process::exit(1);
    }
}

fn do_main() -> Result<(), Box<Error>> {
    if std::env::var_os("RUST_LOG").is_none() {
        std::env::set_var("RUST_LOG", "gir=warn");
    }
    try!(env_logger::init());

    let cfg = match config::Config::new() {
        Ok(cfg) => cfg,
        Err(config::Error::CommandLine(ref err)) if !err.fatal() => {
            println!("{}", err);
            return Ok(());
        }
        Err(err) => return Err(Box::new(err)),
    };

    let mut library = Library::new(&cfg.library_name);
    library.read_file(&cfg.girs_dir, &cfg.library_full_name());
    library.fill_in();

    let env = Env{ library: library, config: cfg };
    codegen::generate(&env);

    Ok(())
}
<|endoftext|>