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

use std::fmt;
use std::io::Write;
use std::mem;

use syn;

use bindgen::config::{Config, Language};
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
use bindgen::ir::{
    AnnotationSet, Cfg, ConditionWrite, Documentation, Item, ItemContainer, Path, ToCondition, Type, GenericParams,
};
use bindgen::writer::{Source, SourceWriter};

#[derive(Debug, Clone)]
pub enum Literal {
    Expr(String),
    Struct {
        name: String,
        export_name: String,
        fields: Vec<(String, Literal)>,
    },
}

impl fmt::Display for Literal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Literal::Expr(v) => write!(f, "{}", v),
            Literal::Struct {
                name: _,
                export_name,
                fields,
            } => write!(
                f,
                "({}){{ {} }}",
                export_name,
                fields
                    .iter()
                    .map(|(key, lit)| format!(".{} = {}", key, lit))
                    .collect::<Vec<String>>()
                    .join(", "),
            ),
        }
    }
}

impl Literal {
    pub fn rename_for_config(&mut self, config: &Config) {
        match self {
            Literal::Struct {
                name: _,
                ref mut export_name,
                fields: _,
            } => config.export.rename(export_name),
            Literal::Expr(_) => {}
        }
    }

    pub fn load(expr: &syn::Expr) -> Result<Literal, String> {
        match expr {
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Str(ref value),
                ..
            }) => Ok(Literal::Expr(format!("u8\"{}\"", value.value()))),
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Byte(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Char(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Int(ref value),
                ..
            }) => match value.suffix() {
                syn::IntSuffix::Usize
                | syn::IntSuffix::U8
                | syn::IntSuffix::U16
                | syn::IntSuffix::U32
                | syn::IntSuffix::U64
                | syn::IntSuffix::U128
                | syn::IntSuffix::None => Ok(Literal::Expr(format!("{}", value.value()))),
                syn::IntSuffix::Isize
                | syn::IntSuffix::I8
                | syn::IntSuffix::I16
                | syn::IntSuffix::I32
                | syn::IntSuffix::I64
                | syn::IntSuffix::I128 => unsafe {
                    Ok(Literal::Expr(format!(
                        "{}",
                        mem::transmute::<u64, i64>(value.value())
                    )))
                },
            },
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Float(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Bool(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value))),

            &syn::Expr::Struct(syn::ExprStruct {
                ref path,
                ref fields,
                ..
            }) => {
                let struct_name = path.segments[0].ident.to_string();
                let mut field_pairs: Vec<(String, Literal)> = Vec::new();
                for field in fields {
                    let ident = match field.member {
                        syn::Member::Named(ref name) => name.to_string(),
                        syn::Member::Unnamed(ref index) => format!("_{}", index.index),
                    };
                    let key = ident.to_string();
                    let value = Literal::load(&field.expr)?;
                    field_pairs.push((key, value));
                }
                Ok(Literal::Struct {
                    name: struct_name.clone(),
                    export_name: struct_name,
                    fields: field_pairs,
                })
            }
            _ => Err("Unsupported literal expression.".to_owned()),
        }
    }
}

#[derive(Debug, Clone)]
pub struct Constant {
    pub path: Path,
    pub export_name: String,
    pub ty: Type,
    pub value: Literal,
    pub cfg: Option<Cfg>,
    pub annotations: AnnotationSet,
    pub documentation: Documentation,
}

impl Constant {
    pub fn load(
        path: Path,
        item: &syn::ItemConst,
        mod_cfg: &Option<Cfg>,
    ) -> Result<Constant, String> {
        let ty = Type::load(&item.ty)?;

        if ty.is_none() {
            return Err("Cannot have a zero sized const definition.".to_owned());
        }

        let ty = ty.unwrap();

        if !ty.is_primitive_or_ptr_primitive() && match *item.expr {
            syn::Expr::Struct(_) => false,
            _ => true,
        } {
            return Err("Unhanded const definition".to_owned());
        }

        Ok(Constant::new(
            path,
            ty,
            Literal::load(&item.expr)?,
            Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
            AnnotationSet::load(&item.attrs)?,
            Documentation::load(&item.attrs),
        ))
    }

    pub fn load_assoc(
        name: String,
        item: &syn::ImplItemConst,
        impl_ty: &syn::Type,
        mod_cfg: &Option<Cfg>,
    ) -> Result<Constant, String> {
        let ty = Type::load(&item.ty)?;

        if ty.is_none() {
            return Err("Cannot have a zero sized const definition.".to_owned());
        }
        let ty = ty.unwrap();
        if !ty.is_primitive_or_ptr_primitive() && match item.expr {
            syn::Expr::Struct(_) => false,
            _ => true,
        } {
            return Err("Unhanded const definition".to_owned());
        }

        let impl_ty = Type::load(impl_ty)?;
        if impl_ty.is_none() {
            return Err("impl has an empty type".to_owned());
        }
        let impl_ty = impl_ty.unwrap();

        let struct_path = impl_ty.get_root_path().unwrap();
        let full_name = Path::new(format!("{}_{}", struct_path, name));

        Ok(Constant::new(
            full_name,
            ty,
            Literal::load(&item.expr)?,
            Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
            AnnotationSet::load(&item.attrs)?,
            Documentation::load(&item.attrs),
        ))
    }

    pub fn new(
        path: Path,
        ty: Type,
        value: Literal,
        cfg: Option<Cfg>,
        annotations: AnnotationSet,
        documentation: Documentation,
    ) -> Self {
        let export_name = path.name().to_owned();
        Self {
            path,
            export_name,
            ty,
            value,
            cfg,
            annotations,
            documentation,
        }
    }
}

impl Item for Constant {
    fn path(&self) -> &Path {
        &self.path
    }

    fn export_name(&self) -> &str {
        &self.export_name
    }

    fn cfg(&self) -> &Option<Cfg> {
        &self.cfg
    }

    fn annotations(&self) -> &AnnotationSet {
        &self.annotations
    }

    fn annotations_mut(&mut self) -> &mut AnnotationSet {
        &mut self.annotations
    }

    fn container(&self) -> ItemContainer {
        ItemContainer::Constant(self.clone())
    }

    fn rename_for_config(&mut self, config: &Config) {
        config.export.rename(&mut self.export_name);
        self.value.rename_for_config(config);
        self.ty.rename_for_config(config, &GenericParams::default());// FIXME: should probably propagate something here
    }

    fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
        self.ty.resolve_declaration_types(resolver);
    }
}

impl Source for Constant {
    fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
        let condition = (&self.cfg).to_condition(config);
        condition.write_before(config, out);
        if config.constant.allow_static_const && config.language == Language::Cxx {
            if let Type::ConstPtr(..) = self.ty {
                out.write("static ");
            } else {
                out.write("static const ");
            }
            self.ty.write(config, out);
            write!(out, " {} = {};", self.export_name(), self.value)
        } else {
            write!(out, "#define {} {}", self.export_name(), self.value)
        }
        condition.write_after(config, out);
    }
}
<commit_msg>Formatting<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::fmt;
use std::io::Write;
use std::mem;

use syn;

use bindgen::config::{Config, Language};
use bindgen::declarationtyperesolver::DeclarationTypeResolver;
use bindgen::ir::{
    AnnotationSet, Cfg, ConditionWrite, Documentation, GenericParams, Item, ItemContainer, Path,
    ToCondition, Type,
};
use bindgen::writer::{Source, SourceWriter};

#[derive(Debug, Clone)]
pub enum Literal {
    Expr(String),
    Struct {
        name: String,
        export_name: String,
        fields: Vec<(String, Literal)>,
    },
}

impl fmt::Display for Literal {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Literal::Expr(v) => write!(f, "{}", v),
            Literal::Struct {
                name: _,
                export_name,
                fields,
            } => write!(
                f,
                "({}){{ {} }}",
                export_name,
                fields
                    .iter()
                    .map(|(key, lit)| format!(".{} = {}", key, lit))
                    .collect::<Vec<String>>()
                    .join(", "),
            ),
        }
    }
}

impl Literal {
    pub fn rename_for_config(&mut self, config: &Config) {
        match self {
            Literal::Struct {
                name: _,
                ref mut export_name,
                fields: _,
            } => config.export.rename(export_name),
            Literal::Expr(_) => {}
        }
    }

    pub fn load(expr: &syn::Expr) -> Result<Literal, String> {
        match expr {
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Str(ref value),
                ..
            }) => Ok(Literal::Expr(format!("u8\"{}\"", value.value()))),
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Byte(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Char(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Int(ref value),
                ..
            }) => match value.suffix() {
                syn::IntSuffix::Usize
                | syn::IntSuffix::U8
                | syn::IntSuffix::U16
                | syn::IntSuffix::U32
                | syn::IntSuffix::U64
                | syn::IntSuffix::U128
                | syn::IntSuffix::None => Ok(Literal::Expr(format!("{}", value.value()))),
                syn::IntSuffix::Isize
                | syn::IntSuffix::I8
                | syn::IntSuffix::I16
                | syn::IntSuffix::I32
                | syn::IntSuffix::I64
                | syn::IntSuffix::I128 => unsafe {
                    Ok(Literal::Expr(format!(
                        "{}",
                        mem::transmute::<u64, i64>(value.value())
                    )))
                },
            },
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Float(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value()))),
            &syn::Expr::Lit(syn::ExprLit {
                lit: syn::Lit::Bool(ref value),
                ..
            }) => Ok(Literal::Expr(format!("{}", value.value))),

            &syn::Expr::Struct(syn::ExprStruct {
                ref path,
                ref fields,
                ..
            }) => {
                let struct_name = path.segments[0].ident.to_string();
                let mut field_pairs: Vec<(String, Literal)> = Vec::new();
                for field in fields {
                    let ident = match field.member {
                        syn::Member::Named(ref name) => name.to_string(),
                        syn::Member::Unnamed(ref index) => format!("_{}", index.index),
                    };
                    let key = ident.to_string();
                    let value = Literal::load(&field.expr)?;
                    field_pairs.push((key, value));
                }
                Ok(Literal::Struct {
                    name: struct_name.clone(),
                    export_name: struct_name,
                    fields: field_pairs,
                })
            }
            _ => Err("Unsupported literal expression.".to_owned()),
        }
    }
}

#[derive(Debug, Clone)]
pub struct Constant {
    pub path: Path,
    pub export_name: String,
    pub ty: Type,
    pub value: Literal,
    pub cfg: Option<Cfg>,
    pub annotations: AnnotationSet,
    pub documentation: Documentation,
}

impl Constant {
    pub fn load(
        path: Path,
        item: &syn::ItemConst,
        mod_cfg: &Option<Cfg>,
    ) -> Result<Constant, String> {
        let ty = Type::load(&item.ty)?;

        if ty.is_none() {
            return Err("Cannot have a zero sized const definition.".to_owned());
        }

        let ty = ty.unwrap();

        if !ty.is_primitive_or_ptr_primitive()
            && match *item.expr {
                syn::Expr::Struct(_) => false,
                _ => true,
            } {
            return Err("Unhanded const definition".to_owned());
        }

        Ok(Constant::new(
            path,
            ty,
            Literal::load(&item.expr)?,
            Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
            AnnotationSet::load(&item.attrs)?,
            Documentation::load(&item.attrs),
        ))
    }

    pub fn load_assoc(
        name: String,
        item: &syn::ImplItemConst,
        impl_ty: &syn::Type,
        mod_cfg: &Option<Cfg>,
    ) -> Result<Constant, String> {
        let ty = Type::load(&item.ty)?;

        if ty.is_none() {
            return Err("Cannot have a zero sized const definition.".to_owned());
        }
        let ty = ty.unwrap();
        if !ty.is_primitive_or_ptr_primitive()
            && match item.expr {
                syn::Expr::Struct(_) => false,
                _ => true,
            } {
            return Err("Unhanded const definition".to_owned());
        }

        let impl_ty = Type::load(impl_ty)?;
        if impl_ty.is_none() {
            return Err("impl has an empty type".to_owned());
        }
        let impl_ty = impl_ty.unwrap();

        let struct_path = impl_ty.get_root_path().unwrap();
        let full_name = Path::new(format!("{}_{}", struct_path, name));

        Ok(Constant::new(
            full_name,
            ty,
            Literal::load(&item.expr)?,
            Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
            AnnotationSet::load(&item.attrs)?,
            Documentation::load(&item.attrs),
        ))
    }

    pub fn new(
        path: Path,
        ty: Type,
        value: Literal,
        cfg: Option<Cfg>,
        annotations: AnnotationSet,
        documentation: Documentation,
    ) -> Self {
        let export_name = path.name().to_owned();
        Self {
            path,
            export_name,
            ty,
            value,
            cfg,
            annotations,
            documentation,
        }
    }
}

impl Item for Constant {
    fn path(&self) -> &Path {
        &self.path
    }

    fn export_name(&self) -> &str {
        &self.export_name
    }

    fn cfg(&self) -> &Option<Cfg> {
        &self.cfg
    }

    fn annotations(&self) -> &AnnotationSet {
        &self.annotations
    }

    fn annotations_mut(&mut self) -> &mut AnnotationSet {
        &mut self.annotations
    }

    fn container(&self) -> ItemContainer {
        ItemContainer::Constant(self.clone())
    }

    fn rename_for_config(&mut self, config: &Config) {
        config.export.rename(&mut self.export_name);
        self.value.rename_for_config(config);
        self.ty.rename_for_config(config, &GenericParams::default()); // FIXME: should probably propagate something here
    }

    fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
        self.ty.resolve_declaration_types(resolver);
    }
}

impl Source for Constant {
    fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
        let condition = (&self.cfg).to_condition(config);
        condition.write_before(config, out);
        if config.constant.allow_static_const && config.language == Language::Cxx {
            if let Type::ConstPtr(..) = self.ty {
                out.write("static ");
            } else {
                out.write("static const ");
            }
            self.ty.write(config, out);
            write!(out, " {} = {};", self.export_name(), self.value)
        } else {
            write!(out, "#define {} {}", self.export_name(), self.value)
        }
        condition.write_after(config, out);
    }
}
<|endoftext|>


<commit_before>//! Module containing a few common error wrappers which allows more information to be saved for
//! later display to the user

use std::any::Any;
use std::error::Error as StdError;
use std::fmt;

use pos::{BytePos, Location, Span, Spanned};
use source::Source;

/// An error type which can represent multiple errors.
#[derive(Debug, PartialEq)]
pub struct Errors<T> {
    pub errors: Vec<T>,
}

impl<T> Errors<T> {
    /// Creates a new, empty `Errors` instance.
    pub fn new() -> Errors<T> {
        Errors { errors: Vec::new() }
    }

    /// Returns true if `self` contains any errors
    pub fn has_errors(&self) -> bool {
        !self.errors.is_empty()
    }

    /// Adds an error to `self`
    pub fn error(&mut self, t: T) {
        self.errors.push(t);
    }
}

impl<T: fmt::Display> fmt::Display for Errors<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for error in &self.errors {
            try!(write!(f, "{}\n", error));
        }
        Ok(())
    }
}

impl<T: fmt::Display + fmt::Debug + Any> StdError for Errors<T> {
    fn description(&self) -> &str {
        "Errors"
    }
}

#[derive(Debug)]
struct SourceContext<E> {
    line: String,
    error: Spanned<E, Location>,
}

impl<E> SourceContext<E> {
    fn new(source: &Source, error: Spanned<E, BytePos>) -> SourceContext<E> {
        let start = source.location(error.span.start).unwrap();
        let end = source.location(error.span.end).unwrap();
        let (_, line) = source.line_at_byte(error.span.start).unwrap();

        SourceContext {
            line: line.to_string(),
            error: Spanned {
                span: Span {
                    start: start,
                    end: end,
                },
                value: error.value,
            },
        }
    }
}

/// Error type which contains information of which file and where in the file the error occured
#[derive(Debug)]
pub struct InFile<E> {
    source_name: String,
    error: Errors<SourceContext<E>>,
}

impl<E: fmt::Display> InFile<E> {
    /// Creates a new `InFile` error which states that the error occured in `file` using the file
    /// contents in `source` to provide a context to the span.
    pub fn new(source_name: &str, source: &str, error: Errors<Spanned<E, BytePos>>) -> InFile<E> {
        let source = Source::new(source);

        InFile {
            source_name: source_name.to_string(),
            error: Errors {
                errors: error.errors
                    .into_iter()
                    .map(|error| SourceContext::new(&source, error))
                    .collect(),
            },
        }
    }
}

impl<E: fmt::Display> fmt::Display for InFile<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for error in &self.error.errors {
            let Span { start, end } = error.error.span;

            try!(write!(f, "{}:{}\n{}\n", self.source_name, error.error, error.line));

            for _ in 0..start.column.to_usize() {
                try!(write!(f, " "));
            }

            try!(write!(f, "^"));
            for _ in (start.column.to_usize() + 1)..end.column.to_usize() {
                try!(write!(f, "~"));
            }

            try!(writeln!(f, ""));
        }
        Ok(())
    }
}

impl<E: fmt::Display + fmt::Debug + Any> StdError for InFile<E> {
    fn description(&self) -> &str {
        "Error in file"
    }
}
<commit_msg>feat: Re-add `InFile::errors`<commit_after>//! Module containing a few common error wrappers which allows more information to be saved for
//! later display to the user

use std::any::Any;
use std::error::Error as StdError;
use std::fmt;

use pos::{BytePos, Location, Span, Spanned};
use source::Source;

/// An error type which can represent multiple errors.
#[derive(Debug, PartialEq)]
pub struct Errors<T> {
    pub errors: Vec<T>,
}

impl<T> Errors<T> {
    /// Creates a new, empty `Errors` instance.
    pub fn new() -> Errors<T> {
        Errors { errors: Vec::new() }
    }

    /// Returns true if `self` contains any errors
    pub fn has_errors(&self) -> bool {
        !self.errors.is_empty()
    }

    /// Adds an error to `self`
    pub fn error(&mut self, t: T) {
        self.errors.push(t);
    }
}

impl<T: fmt::Display> fmt::Display for Errors<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for error in &self.errors {
            try!(write!(f, "{}\n", error));
        }
        Ok(())
    }
}

impl<T: fmt::Display + fmt::Debug + Any> StdError for Errors<T> {
    fn description(&self) -> &str {
        "Errors"
    }
}

#[derive(Debug)]
struct SourceContext<E> {
    line: String,
    error: Spanned<E, Location>,
}

impl<E> SourceContext<E> {
    fn new(source: &Source, error: Spanned<E, BytePos>) -> SourceContext<E> {
        let start = source.location(error.span.start).unwrap();
        let end = source.location(error.span.end).unwrap();
        let (_, line) = source.line_at_byte(error.span.start).unwrap();

        SourceContext {
            line: line.to_string(),
            error: Spanned {
                span: Span {
                    start: start,
                    end: end,
                },
                value: error.value,
            },
        }
    }
}

/// Error type which contains information of which file and where in the file the error occured
#[derive(Debug)]
pub struct InFile<E> {
    pub source_name: String,
    error: Errors<SourceContext<E>>,
}

impl<E: fmt::Display> InFile<E> {
    /// Creates a new `InFile` error which states that the error occured in `file` using the file
    /// contents in `source` to provide a context to the span.
    pub fn new(source_name: &str, source: &str, error: Errors<Spanned<E, BytePos>>) -> InFile<E> {
        let source = Source::new(source);

        InFile {
            source_name: source_name.to_string(),
            error: Errors {
                errors: error.errors
                    .into_iter()
                    .map(|error| SourceContext::new(&source, error))
                    .collect(),
            },
        }
    }

    pub fn errors(self) -> Errors<Spanned<E, Location>> {
        Errors { errors: self.error.errors.into_iter().map(|err| err.error).collect() }
    }
}

impl<E: fmt::Display> fmt::Display for InFile<E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for error in &self.error.errors {
            let Span { start, end } = error.error.span;

            try!(write!(f, "{}:{}\n{}\n", self.source_name, error.error, error.line));

            for _ in 0..start.column.to_usize() {
                try!(write!(f, " "));
            }

            try!(write!(f, "^"));
            for _ in (start.column.to_usize() + 1)..end.column.to_usize() {
                try!(write!(f, "~"));
            }

            try!(writeln!(f, ""));
        }
        Ok(())
    }
}

impl<E: fmt::Display + fmt::Debug + Any> StdError for InFile<E> {
    fn description(&self) -> &str {
        "Error in file"
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use buffer::Buffered;
use stream::*;
use demuxer::demux::*;

use std::io::{BufRead,Error};

pub struct GlobalInfo {
    duration: Option<u64>,
    streams: Vec<Stream>,
//    programs: Vec<StreamGroup>,
//    chapters: Vec<StreamGroup>,
}

pub struct DemuxerContext<'a> {
    demuxer: Box<Demuxer+'a>,
    reader: Box<Buffered>,
    info: GlobalInfo,
}

impl<'a> DemuxerContext<'a> {
    pub fn new<R: Buffered+'static>(demuxer: Box<Demuxer + 'a>, reader: Box<R>) -> Self {
        DemuxerContext {
            demuxer:  demuxer,
            reader:   reader,
            info: GlobalInfo {
                duration: None,
                streams:  Vec::with_capacity(2),
            }
        }
    }

    pub fn read_headers(&mut self) -> Result<(), Error> {
        let ref mut demux = self.demuxer;

        let res = demux.read_headers(&self.reader, &mut self.info);
        match res {
            Err(e)   => Err(e),
            Ok(seek) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                try!(self.reader.fill_buf());
                println!("stream now at index: {:?}", res);
                Ok(())
            }
        }
    }

    pub fn read_packet(&mut self) -> Result<Event, Error> {
        let ref mut demux = self.demuxer;

        let res = demux.read_packet(&self.reader);
        match res {
            Err(e)   => Err(e),
            Ok((seek, event)) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                try!(self.reader.fill_buf());
                /* TODO: update the global info here?
                 * if let Event::NewStream(st) = event {
                    self.info.streams.push(st);
                } */
                println!("stream now at index: {:?}", res);
                Ok(event)
            }
        }
    }
}

<commit_msg>demux: Update the global info according to the received events<commit_after>#![allow(dead_code)]

use buffer::Buffered;
use stream::*;
use demuxer::demux::*;

use std::io::{BufRead,Error};

pub struct GlobalInfo {
    duration: Option<u64>,
    streams: Vec<Stream>,
//    programs: Vec<StreamGroup>,
//    chapters: Vec<StreamGroup>,
}

pub struct DemuxerContext<'a> {
    demuxer: Box<Demuxer+'a>,
    reader: Box<Buffered>,
    info: GlobalInfo,
}

impl<'a> DemuxerContext<'a> {
    pub fn new<R: Buffered+'static>(demuxer: Box<Demuxer + 'a>, reader: Box<R>) -> Self {
        DemuxerContext {
            demuxer:  demuxer,
            reader:   reader,
            info: GlobalInfo {
                duration: None,
                streams:  Vec::with_capacity(2),
            }
        }
    }

    pub fn read_headers(&mut self) -> Result<(), Error> {
        let ref mut demux = self.demuxer;

        let res = demux.read_headers(&self.reader, &mut self.info);
        match res {
            Err(e)   => Err(e),
            Ok(seek) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                try!(self.reader.fill_buf());
                println!("stream now at index: {:?}", res);
                Ok(())
            }
        }
    }

    pub fn read_packet(&mut self) -> Result<Event, Error> {
        let ref mut demux = self.demuxer;

        let res = demux.read_packet(&self.reader);
        match res {
            Err(e)   => Err(e),
            Ok((seek, event)) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                try!(self.reader.fill_buf());
                if let &Event::NewStream(ref st) = &event {
                    self.info.streams.push(st.clone());
                }
                println!("stream now at index: {:?}", res);
                Ok(event)
            }
        }
    }
}

<|endoftext|>


<commit_before>#![feature(test)]

extern crate test;

use liquid;

static TEXT_ONLY: &'static str = "Hello World";

#[bench]
fn bench_parse_text(b: &mut test::Bencher) {
    let parser = liquid::ParserBuilder::with_stdlib()
        .extra_filters()
        .build()
        .unwrap();
    b.iter(|| parser.parse(TEXT_ONLY));
}

#[bench]
fn bench_render_text(b: &mut test::Bencher) {
    let parser = liquid::ParserBuilder::with_stdlib()
        .extra_filters()
        .build()
        .unwrap();
    let template = parser
        .parse(TEXT_ONLY)
        .expect("Benchmark template parsing failed");

    let data = liquid::Object::new();

    template.render(&data).unwrap();
    b.iter(|| template.render(&data));
}
<commit_msg>fix(bench): Didn't update benches<commit_after>#![feature(test)]

extern crate test;

use liquid;

static TEXT_ONLY: &'static str = "Hello World";

#[bench]
fn bench_parse_text(b: &mut test::Bencher) {
    let parser = liquid::ParserBuilder::with_stdlib().build().unwrap();
    b.iter(|| parser.parse(TEXT_ONLY));
}

#[bench]
fn bench_render_text(b: &mut test::Bencher) {
    let parser = liquid::ParserBuilder::with_stdlib().build().unwrap();
    let template = parser
        .parse(TEXT_ONLY)
        .expect("Benchmark template parsing failed");

    let data = liquid::Object::new();

    template.render(&data).unwrap();
    b.iter(|| template.render(&data));
}
<|endoftext|>


<commit_before>use std::rc::*;
use std::ops::*;

use super::super::tree::*;

pub type PublisherRef = Box<Publisher>;
pub type ConsumerRef = Box<Consumer>;

///
/// A publisher reports changes to a tree
///
pub trait Publisher {

}

///
/// A consumer subscribes to published changes to a tree
///
pub trait Consumer {
    ///
    /// Calls a function whenever a particular section of the tree has changed
    ///
    fn subscribe(&mut self, address: TreeAddress, extent: TreeExtent, callback: Fn(TreeChange) -> ());
}

///
/// A component consumes a tree and publishes a tree.
///
pub trait Component : Drop {
}

///
/// References to components are used to keep track of the components that are currently active
///
pub type ComponentRef = Rc<Component>;

///
/// A component subscribes consumes a tree and publishes a transformed version. Components are built from
/// a factory.
///
pub trait ComponentFactory {
    ///
    /// Creates a component that consumes from a particular tree and publishes to a different tree
    ///
    fn create(&self, consumer: ConsumerRef, publisher: PublisherRef) -> ComponentRef;
}
<commit_msg>Can now define how a publisher works<commit_after>use std::rc::*;
use std::ops::*;

use super::super::tree::*;

pub type PublisherRef = Box<Publisher>;
pub type ConsumerRef = Box<Consumer>;

///
/// A publisher reports changes to a tree
///
pub trait Publisher {
    ///
    /// Publishes a change to the consumers of this component
    ///
    fn publish(&mut self, change: TreeChange);
}

///
/// A consumer subscribes to published changes to a tree
///
pub trait Consumer {
    ///
    /// Calls a function whenever a particular section of the tree has changed
    ///
    fn subscribe(&mut self, address: TreeAddress, extent: TreeExtent, callback: Fn(TreeChange) -> ());
}

///
/// A component consumes a tree and publishes a tree.
///
pub trait Component : Drop {
}

///
/// References to components are used to keep track of the components that are currently active
///
pub type ComponentRef = Rc<Component>;

///
/// A component subscribes consumes a tree and publishes a transformed version. Components are built from
/// a factory.
///
pub trait ComponentFactory {
    ///
    /// Creates a component that consumes from a particular tree and publishes to a different tree
    ///
    fn create(&self, consumer: ConsumerRef, publisher: PublisherRef) -> ComponentRef;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! Sequence of bytes.

use crate::private::layout::{PointerBuilder, PointerReader};
use crate::Result;

#[derive(Copy, Clone)]
pub struct Owned(());

impl<'a> crate::traits::Owned<'a> for Owned {
    type Reader = Reader<'a>;
    type Builder = Builder<'a>;
}

pub type Reader<'a> = &'a [u8];

#[deprecated(since = "0.13.4", note = "This function is unsafe and was never intended for external use")]
pub fn new_reader<'a>(p : *const u8, len : u32) -> Reader<'a> {
    unsafe { ::core::slice::from_raw_parts(p, len as usize) }
}

pub(crate) unsafe fn reader_from_raw_parts<'a>(p: *const u8, len: u32) -> Reader<'a> {
    ::core::slice::from_raw_parts(p, len as usize)
}

impl <'a> crate::traits::FromPointerReader<'a> for Reader<'a> {
    fn get_from_pointer(reader: &PointerReader<'a>, default: Option<&'a [crate::Word]>) -> Result<Reader<'a>> {
        reader.get_data(default)
    }
}

pub type Builder<'a> = &'a mut [u8];

#[deprecated(since = "0.13.4", note = "This function is unsafe and was never intended for external use")]
pub fn new_builder<'a>(p : *mut u8, len : u32) -> Builder<'a> {
    unsafe { ::core::slice::from_raw_parts_mut(p, len as usize) }
}

pub(crate) unsafe fn builder_from_raw_parts<'a>(p: *mut u8, len: u32) -> Builder<'a> {
    ::core::slice::from_raw_parts_mut(p, len as usize)
}

impl <'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> {
    fn init_pointer(builder : PointerBuilder<'a>, size : u32) -> Builder<'a> {
        builder.init_data(size)
    }
    fn get_from_pointer(builder :PointerBuilder<'a>, default: Option<&'a [crate::Word]>) -> Result<Builder<'a>> {
        builder.get_data(default)
    }
}

impl <'a> crate::traits::SetPointerBuilder for Reader<'a> {
    fn set_pointer_builder<'b>(pointer: PointerBuilder<'b>,
                               value: Reader<'a>,
                               _canonicalize: bool) -> Result<()> {
        pointer.set_data(value);
        Ok(())
    }
}

<commit_msg>remove deprecated functions<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! Sequence of bytes.

use crate::private::layout::{PointerBuilder, PointerReader};
use crate::Result;

#[derive(Copy, Clone)]
pub struct Owned(());

impl<'a> crate::traits::Owned<'a> for Owned {
    type Reader = Reader<'a>;
    type Builder = Builder<'a>;
}

pub type Reader<'a> = &'a [u8];

pub(crate) unsafe fn reader_from_raw_parts<'a>(p: *const u8, len: u32) -> Reader<'a> {
    ::core::slice::from_raw_parts(p, len as usize)
}

impl <'a> crate::traits::FromPointerReader<'a> for Reader<'a> {
    fn get_from_pointer(reader: &PointerReader<'a>, default: Option<&'a [crate::Word]>) -> Result<Reader<'a>> {
        reader.get_data(default)
    }
}

pub type Builder<'a> = &'a mut [u8];

pub(crate) unsafe fn builder_from_raw_parts<'a>(p: *mut u8, len: u32) -> Builder<'a> {
    ::core::slice::from_raw_parts_mut(p, len as usize)
}

impl <'a> crate::traits::FromPointerBuilder<'a> for Builder<'a> {
    fn init_pointer(builder : PointerBuilder<'a>, size : u32) -> Builder<'a> {
        builder.init_data(size)
    }
    fn get_from_pointer(builder :PointerBuilder<'a>, default: Option<&'a [crate::Word]>) -> Result<Builder<'a>> {
        builder.get_data(default)
    }
}

impl <'a> crate::traits::SetPointerBuilder for Reader<'a> {
    fn set_pointer_builder<'b>(pointer: PointerBuilder<'b>,
                               value: Reader<'a>,
                               _canonicalize: bool) -> Result<()> {
        pointer.set_data(value);
        Ok(())
    }
}

<|endoftext|>


<commit_before>extern crate libc;
extern crate x11;

use std::ptr;
use x11::xlib;
use x11::xlib::Window;
use super::super::libx;

use super::config::Config;
use super::container::{self, Container};
use super::layout;
use super::Workspaces;
use super::handler;

unsafe extern fn error_handler(display: *mut xlib::Display, event: *mut xlib::XErrorEvent) -> libc::c_int {
    // match event.error_code {
    //     xlib::BadAtom => {
    //         println!("bad atom");
    //     }
    //     _ => {}
    // }
    // x11::xmu::XmuSimpleErrorHandler(display, event);
    1
}

extern "C" {
    fn setlocale(category: i32, locale: *const i8) -> *mut i8;
}

fn load_resource(mut context: &mut libx::Context) {
    use std::mem;
    use std::ffi;
    let screen = context.screen_num;
    let root = context.root;
    let display = context.display;
    let mut values: xlib::XGCValues = unsafe{ mem::zeroed() };
    // let gc = libx::create_gc(self.context, self.id, 0, values);
    let gc = libx::default_gc(*context, screen);

    unsafe {
        let black = xlib::XBlackPixel(display, screen);
        let white = xlib::XWhitePixel(display, screen);

        xlib::XSetLineAttributes(display, gc, 5, 0, 0, 0);

        let cmap = xlib::XDefaultColormap(display, screen);
        let mut color: xlib::XColor = mem::zeroed();
        let name = ffi::CString::new("blue").unwrap().as_ptr();
        let r = xlib::XParseColor(display, cmap, name, &mut color);
        xlib::XAllocColor(display, cmap, &mut color);

        context.gc = gc;
        context.focus_bg = black;
        context.focus_fg = color.pixel;
        context.unfocus_bg = black;
        context.unfocus_fg = black;
        context.font_color = white;

        let s = ffi::CString::new("").unwrap().as_ptr();
        let p = setlocale(6, s);
        let res = xlib::XSupportsLocale();
        let res = xlib::XSetLocaleModifiers(s);

        let mut missing_charsets = ptr::null_mut();
        let mut num_missing_charsets: i32 = 0;
        let mut default_string = ptr::null_mut();
        // let name = "-misc-fixed-*-*-*-*-*-130-75-75-*-*-*-*";
        let name = "*";
        let fontbase = ffi::CString::new(name).unwrap().as_ptr();
        let fontset = xlib::XCreateFontSet(display,
                                           fontbase,
                                           &mut missing_charsets,
                                           &mut num_missing_charsets,
                                           &mut default_string);
        if num_missing_charsets > 0 {
            xlib::XFreeStringList(missing_charsets);
        }
        context.fontset = fontset;
    }
}

pub struct WindowManager {
    pub context: libx::Context,
    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	let res = libx::open_display(None);
        let mut context = match res {
            Some(c) => {
                c
            }
            None => {
                panic!("can't open display")
            }
        };

	context.screen_num  = libx::default_screen(context);
	context.root = libx::root_window(context, context.screen_num);
        load_resource(&mut context);

	let mut wm = WindowManager {
            context: context,
            config: Config::new(),
            workspaces: Workspaces::new(context)
        };
        wm
    }

    pub fn clean(&mut self) {
        libx::close_display(self.context);
    }

    pub fn handle_create(&mut self, event: &xlib::XCreateWindowEvent) {
        if event.override_redirect != 0 {
            return;
        }

        let attrs = libx::get_window_attributes(self.context, event.window);
        println!("{} attr {} {}", event.window, attrs.width, attrs.height);
        // get window property
        let n = libx::get_text_property(self.context, event.window, xlib::XA_WM_NAME);
        match n {
            Some(s) => {debug!("create window {} for {}", event.window, s);}
            None => {}
        }

        // let atoms = libx::get_wm_protocols(self.context, event.window);
        // for a in atoms.iter() {
        //     println!("atom {}", a);
        //     let name = libx::get_atom_name(self.context, *a);
        //     match name {
        //         Some(n) => println!("name {}", n),
        //         None => println!("name {}", a),
        //     };
        // }
    }

    pub fn handle_destroy(&mut self, event: &xlib::XDestroyWindowEvent) {
        self.workspaces.remove_window(event.window);
        if self.workspaces.get_focus().is_none() {
            let id = self.workspaces.current().raw_id();
            self.workspaces.set_focus(id);
        }
    }

    pub fn handle_map_request(&mut self, event: &xlib::XMapRequestEvent) {
        // add app top-level window to workspace
        // let window = Window::new(self.context, event.window);
        let manage = Workspaces::can_manage(self.context, event.window);

        if manage {
            debug!("top level window");
            let mut container = Container::from_id(self.context, event.window);
            container.map();
            // container.focus();
            // change attributes before display
            let mask = 0x420010;
            let mask = xlib::EnterWindowMask | xlib::PropertyChangeMask;
            libx::select_input(self.context, container.raw_id(), mask);

            if self.config.titlebar_height > 0 {
                container.titlebar_height = self.config.titlebar_height;
            }
            self.workspaces.insert_window(container);
        }
        else {
            libx::map_window(self.context, event.window);
        }
    }

    pub fn handle_client_message(&mut self, event: &xlib::XClientMessageEvent) {
        println!("message type {}", event.message_type);
        let s = libx::get_atom_name(self.context, event.message_type);
        match s {
            Some(v) => println!("{}", &v),
            None => {}
        }

        match event.format {
            8 => {
                for i in 0..20 {
                    println!("{}", event.data.get_byte(i));
                }
            }
            16 => {
                for i in 0..10 {
                    println!("{}", event.data.get_short(i))
                }
            }
            32 => {
                for i in 0..5 {
                    let a = event.data.get_long(i);
                    if a != 0{
                        let s = libx::get_atom_name(self.context, a as xlib::Atom);
                        match s {
                            Some(v) => println!("{}", v),
                            None => {}
                        }
                    }
                }
            }
            _ => {}
        }
    }

    pub fn handle_button_motion(&mut self, event: &xlib::XMotionEvent) {

    }

    pub fn handle_button_press(&mut self, event: &xlib::XButtonEvent) {

        let id = match self.workspaces.get_container(event.window) {
            Some((_,c)) => {
                let client = c.query_point(event.x, event.y);
                match client {
                    Some(c) => {
                        c.raw_id()
                    }
                    None => { c.raw_id() }
                }
            }
            None => { return }
        };
        self.workspaces.set_focus(id);

        // test if press on boarder
        match self.workspaces.get_container(event.window) {
            Some((_,c)) => {
                let res = c.query_border(event.x, event.y);
                match res {
                    Some(i) => {
                        match c.mode {
                            container::Mode::Normal => {
                                c.mode = container::Mode::Resize(i, event.x, event.y)
                            }
                            container::Mode::Resize(index, x, y) => {

                            }
                            _ => {}
                        }
                    }
                    None => {}
                }
            }
            None => {}
        }
    }

    pub fn handle_button_release(&mut self, event: &xlib::XButtonEvent) {
        match self.workspaces.get_container(event.window) {
            Some((_, c)) => {
                match c.mode {
                    container::Mode::Resize(index, x, y) => {
                        let dx = event.x - x;
                        let dy = event.y - y;
                        let rec = c.rec();
                        let step = match c.direction {
                            layout::Direction::Vertical => {
                                dy as f32 / rec.height as f32
                            }
                            layout::Direction::Horizontal => {
                                dx as f32 / rec.width as f32
                            }
                            _ => { 0.05 }
                        };

                        c.resize_children(index-1, index, step);
                        c.update_layout();
                        c.mode = container::Mode::Normal;
                    }
                    _ => {}
                }
            }
            None => {}
        }
    }

    pub fn handle_key_release(&mut self, event: &xlib::XKeyEvent) {
        if event.state > 0 {
            let sym = libx::lookup_keysym(*event, 0);
            let b = handler::KeyBind {
                key: sym,
                mask: event.state,
            };
            debug!("key {} {}", event.state, sym);

            match self.config.bindsyms.get_mut(&b) {
                Some(handler) => {
                    handler.handle(&mut self.workspaces, self.context);
                }
                None => {
                    println!("no bind");
                }
            }
        }
    }

    pub fn handle_property(&mut self, event: &xlib::XPropertyEvent) {
        let usertime = libx::get_atom(self.context, "_NET_WM_USER_TIME");
        match event.atom {
            usertime => {
                self.workspaces.set_focus(event.window);
            }
        }
    }

    pub fn handle_configure_request(&mut self, event: &xlib::XConfigureRequestEvent) {
        let mut change = xlib::XWindowChanges {
            x: event.x,
            y: event.y,
            width: event.width,
            height: event.height,
            border_width: event.border_width,
            sibling: event.above,
            stack_mode: event.detail
        };
        debug!("config x: {}, y: {}, width: {}, height: {}",
               change.x, change.y, change.width, change.height);
        libx::configure_window(self.context, event.window, event.value_mask as u32, change);
    }

    pub fn handle_focus_in(&mut self, event: &xlib::XFocusChangeEvent) {
        self.workspaces.set_focus(event.window);
    }

    pub fn handle_enter(&mut self, event: &xlib::XCrossingEvent){
        if event.focus == 0 {
            self.workspaces.set_focus(event.window);
        }
    }

    pub fn handle(&mut self, e: xlib::XEvent) {
        let t = e.get_type();
        match t {
            xlib::CreateNotify => {
                let event: xlib::XCreateWindowEvent = From::from(e);
                debug!("create notify {}", event.window);
                self.handle_create(&event);
            }
            xlib::DestroyNotify => {
                let event: xlib::XDestroyWindowEvent = From::from(e);
                debug!("destroy notify {}", event.window);
                self.handle_destroy(&event);
            }
            xlib::MapNotify => {
                let event: xlib::XMapEvent = From::from(e);
                debug!("map notify {}", event.window);
            }
            xlib::UnmapNotify => {
                let event: xlib::XUnmapEvent = From::from(e);
                debug!("unmap notify {}", event.window);
            }
            xlib::MapRequest => {
                let event: xlib::XMapRequestEvent = From::from(e);
                debug!("map request {}", event.window);
                self.handle_map_request(&event);
            }
            xlib::ClientMessage => {
                debug!("client message");
                // let event = cast_event::<xlib::XClientMessageEvent>(&e);
                let event: xlib::XClientMessageEvent = From::from(e);
                self.handle_client_message(&event);
            }
            xlib::KeyRelease => {
                debug!("key release");
                let mut event: xlib::XKeyEvent = From::from(e);
                self.handle_key_release(&mut event);
            }
            xlib::MotionNotify => {
                let mut event: xlib::XMotionEvent = From::from(e);
                debug!("button motion {}", event.window);
                self.handle_button_motion(&event);
            }
            xlib::ButtonRelease => {
                let mut event: xlib::XButtonEvent = From::from(e);
                debug!("button release {}", event.window);
                self.handle_button_release(&event);
            }
            xlib::ButtonPress => {
                let mut event: xlib::XButtonEvent = From::from(e);
                debug!("button press {}", event.window);
                self.handle_button_press(&event);
            }
            xlib::ConfigureNotify => {
                debug!("configure notify");
            }
            xlib::ConfigureRequest =>{
                let mut event: xlib::XConfigureRequestEvent = From::from(e);
                debug!("configure request {}", event.window);
                self.handle_configure_request(&event);
            }
            xlib::FocusIn => {
                let mut event: xlib::XFocusChangeEvent = From::from(e);
                debug!("focus in {}", event.window);
                self.handle_focus_in(&event);

            }
            xlib::FocusOut => {
                let mut event: xlib::XFocusChangeEvent = From::from(e);
                debug!("focus out {}", event.window);
            }
            xlib::EnterNotify => {
                let mut event: xlib::XCrossingEvent = From::from(e);
                debug!("enter window {}", event.window);
                self.handle_enter(&event);
            }
            xlib::PropertyNotify => {
                let mut event: xlib::XPropertyEvent = From::from(e);
                debug!("property notify {}", event.window);
                self.handle_property(&event);
            }
            _ => {
                debug!("unhandled event {}", t);
            }
        }
    }
    pub fn run(&mut self) {
        loop {
            //handle events here
            let mut e = libx::next_event(self.context);
            self.handle(e);
        }
    }

    pub fn init(&mut self) {
        // init connection setting
        let mask = 0x1A0034;
        let mask = xlib::SubstructureRedirectMask | xlib::SubstructureNotifyMask | xlib::ButtonPressMask;

        unsafe{
            xlib::XSetErrorHandler(Some(error_handler));
        }
        let left_ptr: u32 = 68;
        libx::define_cursor(self.context, self.context.root, left_ptr);

        libx::ungrab_button(self.context, 0, 0x8000, self.context.root);
        libx::select_input(self.context, self.context.root,
                           mask);

        // init workspace
        self.init_workspaces();

        // load config file, run exec in config
        self.config.load();

        for bind in self.config.bindsyms.keys() {
            let code = libx::keysym_to_keycode(self.context, bind.key);
            libx::grab_key(self.context, code, bind.mask, self.context.root);
        }
        libx::sync(self.context, 0);
    }

    fn init_workspaces(&mut self) {
        self.workspaces.switch_workspace('1', self.context);
    }
}
<commit_msg>remove useless code<commit_after>extern crate libc;
extern crate x11;

use std::ptr;
use x11::xlib;
use x11::xlib::Window;
use super::super::libx;

use super::config::Config;
use super::container::{self, Container};
use super::layout;
use super::Workspaces;
use super::handler;

unsafe extern fn error_handler(display: *mut xlib::Display, event: *mut xlib::XErrorEvent) -> libc::c_int {
    // match event.error_code {
    //     xlib::BadAtom => {
    //         println!("bad atom");
    //     }
    //     _ => {}
    // }
    // x11::xmu::XmuSimpleErrorHandler(display, event);
    1
}

extern "C" {
    fn setlocale(category: i32, locale: *const i8) -> *mut i8;
}

fn load_resource(mut context: &mut libx::Context) {
    use std::mem;
    use std::ffi;
    let screen = context.screen_num;
    let root = context.root;
    let display = context.display;
    let mut values: xlib::XGCValues = unsafe{ mem::zeroed() };
    // let gc = libx::create_gc(self.context, self.id, 0, values);
    let gc = libx::default_gc(*context, screen);

    unsafe {
        let black = xlib::XBlackPixel(display, screen);
        let white = xlib::XWhitePixel(display, screen);

        xlib::XSetLineAttributes(display, gc, 5, 0, 0, 0);

        let cmap = xlib::XDefaultColormap(display, screen);
        let mut color: xlib::XColor = mem::zeroed();
        let name = ffi::CString::new("blue").unwrap().as_ptr();
        let r = xlib::XParseColor(display, cmap, name, &mut color);
        xlib::XAllocColor(display, cmap, &mut color);

        context.gc = gc;
        context.focus_bg = black;
        context.focus_fg = color.pixel;
        context.unfocus_bg = black;
        context.unfocus_fg = black;
        context.font_color = white;

        let s = ffi::CString::new("").unwrap().as_ptr();
        let p = setlocale(6, s);
        let res = xlib::XSupportsLocale();
        let res = xlib::XSetLocaleModifiers(s);

        let mut missing_charsets = ptr::null_mut();
        let mut num_missing_charsets: i32 = 0;
        let mut default_string = ptr::null_mut();
        // let name = "-misc-fixed-*-*-*-*-*-130-75-75-*-*-*-*";
        let name = "*";
        let fontbase = ffi::CString::new(name).unwrap().as_ptr();
        let fontset = xlib::XCreateFontSet(display,
                                           fontbase,
                                           &mut missing_charsets,
                                           &mut num_missing_charsets,
                                           &mut default_string);
        if num_missing_charsets > 0 {
            xlib::XFreeStringList(missing_charsets);
        }
        context.fontset = fontset;
    }
}

pub struct WindowManager {
    pub context: libx::Context,
    pub workspaces: Workspaces,
    config: Config
}

impl WindowManager {
    pub fn new() -> WindowManager {
	let res = libx::open_display(None);
        let mut context = match res {
            Some(c) => {
                c
            }
            None => {
                panic!("can't open display")
            }
        };

	context.screen_num  = libx::default_screen(context);
	context.root = libx::root_window(context, context.screen_num);
        load_resource(&mut context);

	let mut wm = WindowManager {
            context: context,
            config: Config::new(),
            workspaces: Workspaces::new(context)
        };
        wm
    }

    pub fn clean(&mut self) {
        libx::close_display(self.context);
    }

    pub fn handle_create(&mut self, event: &xlib::XCreateWindowEvent) {
        if event.override_redirect != 0 {
            return;
        }

        let attrs = libx::get_window_attributes(self.context, event.window);
        println!("{} attr {} {}", event.window, attrs.width, attrs.height);
        // get window property
        let n = libx::get_text_property(self.context, event.window, xlib::XA_WM_NAME);
        match n {
            Some(s) => {debug!("create window {} for {}", event.window, s);}
            None => {}
        }

        // let atoms = libx::get_wm_protocols(self.context, event.window);
        // for a in atoms.iter() {
        //     println!("atom {}", a);
        //     let name = libx::get_atom_name(self.context, *a);
        //     match name {
        //         Some(n) => println!("name {}", n),
        //         None => println!("name {}", a),
        //     };
        // }
    }

    pub fn handle_destroy(&mut self, event: &xlib::XDestroyWindowEvent) {
        self.workspaces.remove_window(event.window);
        if self.workspaces.get_focus().is_none() {
            let id = self.workspaces.current().raw_id();
            self.workspaces.set_focus(id);
        }
    }

    pub fn handle_map_request(&mut self, event: &xlib::XMapRequestEvent) {
        // add app top-level window to workspace
        // let window = Window::new(self.context, event.window);
        let manage = Workspaces::can_manage(self.context, event.window);

        if manage {
            debug!("top level window");
            let mut container = Container::from_id(self.context, event.window);
            container.map();
            // container.focus();
            // change attributes before display
            let mask = 0x420010;
            let mask = xlib::EnterWindowMask | xlib::PropertyChangeMask;
            libx::select_input(self.context, container.raw_id(), mask);

            if self.config.titlebar_height > 0 {
                container.titlebar_height = self.config.titlebar_height;
            }
            self.workspaces.insert_window(container);
        }
        else {
            libx::map_window(self.context, event.window);
        }
    }

    pub fn handle_client_message(&mut self, event: &xlib::XClientMessageEvent) {
        println!("message type {}", event.message_type);
        let s = libx::get_atom_name(self.context, event.message_type);
        match s {
            Some(v) => println!("{}", &v),
            None => {}
        }

        match event.format {
            8 => {
                for i in 0..20 {
                    println!("{}", event.data.get_byte(i));
                }
            }
            16 => {
                for i in 0..10 {
                    println!("{}", event.data.get_short(i))
                }
            }
            32 => {
                for i in 0..5 {
                    let a = event.data.get_long(i);
                    if a != 0{
                        let s = libx::get_atom_name(self.context, a as xlib::Atom);
                        match s {
                            Some(v) => println!("{}", v),
                            None => {}
                        }
                    }
                }
            }
            _ => {}
        }
    }

    pub fn handle_button_motion(&mut self, event: &xlib::XMotionEvent) {

    }

    pub fn handle_button_press(&mut self, event: &xlib::XButtonEvent) {

        let id = match self.workspaces.get_container(event.window) {
            Some((_,c)) => {
                let client = c.query_point(event.x, event.y);
                match client {
                    Some(c) => {
                        c.raw_id()
                    }
                    None => { c.raw_id() }
                }
            }
            None => { return }
        };
        self.workspaces.set_focus(id);

        // test if press on boarder
        match self.workspaces.get_container(event.window) {
            Some((_,c)) => {
                let res = c.query_border(event.x, event.y);
                match res {
                    Some(i) => {
                        match c.mode {
                            container::Mode::Normal => {
                                c.mode = container::Mode::Resize(i, event.x, event.y)
                            }
                            container::Mode::Resize(index, x, y) => {

                            }
                            _ => {}
                        }
                    }
                    None => {}
                }
            }
            None => {}
        }
    }

    pub fn handle_button_release(&mut self, event: &xlib::XButtonEvent) {
        match self.workspaces.get_container(event.window) {
            Some((_, c)) => {
                match c.mode {
                    container::Mode::Resize(index, x, y) => {
                        let dx = event.x - x;
                        let dy = event.y - y;
                        let rec = c.rec();
                        let step = match c.direction {
                            layout::Direction::Vertical => {
                                dy as f32 / rec.height as f32
                            }
                            layout::Direction::Horizontal => {
                                dx as f32 / rec.width as f32
                            }
                            _ => { 0.05 }
                        };

                        c.resize_children(index-1, index, step);
                        c.update_layout();
                        c.mode = container::Mode::Normal;
                    }
                    _ => {}
                }
            }
            None => {}
        }
    }

    pub fn handle_key_release(&mut self, event: &xlib::XKeyEvent) {
        if event.state > 0 {
            let sym = libx::lookup_keysym(*event, 0);
            let b = handler::KeyBind {
                key: sym,
                mask: event.state,
            };
            debug!("key {} {}", event.state, sym);

            match self.config.bindsyms.get_mut(&b) {
                Some(handler) => {
                    handler.handle(&mut self.workspaces, self.context);
                }
                None => {
                    println!("no bind");
                }
            }
        }
    }

    pub fn handle_property(&mut self, event: &xlib::XPropertyEvent) {
        let usertime = libx::get_atom(self.context, "_NET_WM_USER_TIME");
        match event.atom {
            usertime => {
                self.workspaces.set_focus(event.window);
            }
        }
    }

    pub fn handle_configure_request(&mut self, event: &xlib::XConfigureRequestEvent) {
        let mut change = xlib::XWindowChanges {
            x: event.x,
            y: event.y,
            width: event.width,
            height: event.height,
            border_width: event.border_width,
            sibling: event.above,
            stack_mode: event.detail
        };
        debug!("config x: {}, y: {}, width: {}, height: {}",
               change.x, change.y, change.width, change.height);
        libx::configure_window(self.context, event.window, event.value_mask as u32, change);
    }

    pub fn handle_focus_in(&mut self, event: &xlib::XFocusChangeEvent) {
        self.workspaces.set_focus(event.window);
    }

    pub fn handle_enter(&mut self, event: &xlib::XCrossingEvent){
        if event.focus == 0 {
            self.workspaces.set_focus(event.window);
        }
    }

    pub fn handle(&mut self, e: xlib::XEvent) {
        let t = e.get_type();
        match t {
            xlib::CreateNotify => {
                let event: xlib::XCreateWindowEvent = From::from(e);
                debug!("create notify {}", event.window);
                self.handle_create(&event);
            }
            xlib::DestroyNotify => {
                let event: xlib::XDestroyWindowEvent = From::from(e);
                debug!("destroy notify {}", event.window);
                self.handle_destroy(&event);
            }
            xlib::MapNotify => {
                let event: xlib::XMapEvent = From::from(e);
                debug!("map notify {}", event.window);
            }
            xlib::UnmapNotify => {
                let event: xlib::XUnmapEvent = From::from(e);
                debug!("unmap notify {}", event.window);
            }
            xlib::MapRequest => {
                let event: xlib::XMapRequestEvent = From::from(e);
                debug!("map request {}", event.window);
                self.handle_map_request(&event);
            }
            xlib::ClientMessage => {
                debug!("client message");
                // let event = cast_event::<xlib::XClientMessageEvent>(&e);
                let event: xlib::XClientMessageEvent = From::from(e);
                self.handle_client_message(&event);
            }
            xlib::KeyRelease => {
                debug!("key release");
                let mut event: xlib::XKeyEvent = From::from(e);
                self.handle_key_release(&mut event);
            }
            xlib::MotionNotify => {
                let mut event: xlib::XMotionEvent = From::from(e);
                self.handle_button_motion(&event);
            }
            xlib::ButtonRelease => {
                let mut event: xlib::XButtonEvent = From::from(e);
                self.handle_button_release(&event);
            }
            xlib::ButtonPress => {
                let mut event: xlib::XButtonEvent = From::from(e);
                self.handle_button_press(&event);
            }
            xlib::ConfigureNotify => {
                debug!("configure notify");
            }
            xlib::ConfigureRequest =>{
                let mut event: xlib::XConfigureRequestEvent = From::from(e);
                debug!("configure request {}", event.window);
                self.handle_configure_request(&event);
            }
            xlib::FocusIn => {
                let mut event: xlib::XFocusChangeEvent = From::from(e);
                debug!("focus in {}", event.window);
                self.handle_focus_in(&event);

            }
            xlib::FocusOut => {
                let mut event: xlib::XFocusChangeEvent = From::from(e);
                debug!("focus out {}", event.window);
            }
            xlib::EnterNotify => {
                let mut event: xlib::XCrossingEvent = From::from(e);
                debug!("enter window {}", event.window);
                self.handle_enter(&event);
            }
            xlib::PropertyNotify => {
                let mut event: xlib::XPropertyEvent = From::from(e);
                debug!("property notify {}", event.window);
                self.handle_property(&event);
            }
            _ => {
                debug!("unhandled event {}", t);
            }
        }
    }
    pub fn run(&mut self) {
        loop {
            //handle events here
            let mut e = libx::next_event(self.context);
            self.handle(e);
        }
    }

    pub fn init(&mut self) {
        // init connection setting
        let mask = 0x1A0034;
        let mask = xlib::SubstructureRedirectMask | xlib::SubstructureNotifyMask | xlib::ButtonPressMask;

        unsafe{
            xlib::XSetErrorHandler(Some(error_handler));
        }
        let left_ptr: u32 = 68;
        libx::define_cursor(self.context, self.context.root, left_ptr);

        libx::select_input(self.context, self.context.root,
                           mask);

        self.init_workspaces();

        // load config file, run exec in config
        self.config.load();

        for bind in self.config.bindsyms.keys() {
            let code = libx::keysym_to_keycode(self.context, bind.key);
            libx::grab_key(self.context, code, bind.mask, self.context.root);
        }
        libx::sync(self.context, 0);
    }

    fn init_workspaces(&mut self) {
        self.workspaces.switch_workspace('1', self.context);
    }
}
<|endoftext|>


<commit_before>#![feature(test)]

extern crate quick_protobuf;
extern crate test;

mod perftest_data;

use test::{Bencher, black_box};
use perftest_data::*;
use std::cmp::min;

use quick_protobuf::{Reader, Writer};
use quick_protobuf::message::{MessageRead, MessageWrite};

#[bench]
fn read_file(b: &mut Bencher) {
    b.iter(|| {
        let _ = black_box(::perftest_data::PerftestData::from_file("benches/rust-protobuf/perftest_data.pbbin").unwrap());
    })
}

macro_rules! perfbench {
    ($gen: ident, $m:ident, $write:ident, $read:ident) => {
#[bench]
fn $write(b: &mut Bencher) {
    let v = $gen();
    b.iter(|| {
        let mut buf = black_box(Vec::new());
        let mut w = Writer::new(&mut buf);
        for i in &v {
            i.write_message(&mut w).unwrap();
        }
    })
}

#[bench]
fn $read(b: &mut Bencher) {
    let v = $gen();
    let mut buf = Vec::new();
    {
        let mut w = Writer::new(&mut buf);
        for i in &v {
            i.write_message(&mut w).unwrap();
        }
    }
    let len = buf.len();
    b.iter(|| {
        let mut buf = &*buf;
        let mut r = Reader::from_reader(&mut buf, len);
        while !r.is_eof() {
            let _ = black_box($m::from_reader(&mut r).unwrap());
        }
    })
}
    }
}

fn generate_test1() -> Vec<Test1> {
    (0..500).map(|i| Test1 { value: Some(i) })
        .chain((0..200).map(|_| Test1 { value: None }))
        .collect()
}

perfbench!(generate_test1, Test1, write_test1, read_test1);

fn generate_repeated_bool() -> Vec<TestRepeatedBool> {
    (1..10).map(|j| TestRepeatedBool { values: (0..100).map(|i| i % j == 0).collect() })
        .collect()
}

perfbench!(generate_repeated_bool, TestRepeatedBool, write_repeated_bool, read_repeated_bool);

fn generate_repeated_packed_int32() -> Vec<TestRepeatedPackedInt32> {
    (1..40).map(|j| TestRepeatedPackedInt32 { values: (0..100).map(|i| i * j).collect() })
        .collect()
}

perfbench!(generate_repeated_packed_int32, TestRepeatedPackedInt32, write_repeated_packed_int32, read_repeated_packed_int32);

fn generate_repeated_messages() -> Vec<TestRepeatedMessages> {
    let mut messages = Vec::new();
    messages.push(TestRepeatedMessages {
        messages1: vec![],
        messages2: vec![],
        messages3: vec![],
    });

    for _ in 0..10 {
        let i1 = min(messages.len() % 3, messages.len() - 1);
        let i2 = min(messages.len() % 6, messages.len() - 1);
        let i3 = min(messages.len() % 9, messages.len() - 1);
        let m1 = messages[i1].clone();
        let m2 = messages[i2].clone();
        let m3 = messages[i3].clone();
        messages.push(TestRepeatedMessages {
            messages1: vec![m1.clone()],
            messages2: vec![m1.clone(), m2.clone()],
            messages3: vec![m1.clone(), m2.clone(), m3.clone()],
        });
    }
    messages
}

perfbench!(generate_repeated_messages, TestRepeatedMessages, write_repeated_messages, read_repeated_messages);

fn generate_optional_messages() -> Vec<TestOptionalMessages> {
    let mut messages = Vec::new();
    messages.push(TestOptionalMessages {
        message1: None,
        message2: None,
        message3: None,
    });

    for _ in 0..10 {
        let i1 = min(messages.len() % 3, messages.len() - 1);
        let i2 = min(messages.len() % 6, messages.len() - 1);
        let i3 = min(messages.len() % 9, messages.len() - 1);
        let m1 = messages[i1].clone();
        let m2 = messages[i2].clone();
        let m3 = messages[i3].clone();
        messages.push(TestOptionalMessages {
            message1: Some(Box::new(m1.clone())),
            message2: Some(Box::new(m2.clone())),
            message3: Some(Box::new(m3.clone())),
        });
    }
    messages
}

perfbench!(generate_optional_messages, TestOptionalMessages, write_optional_messages, read_optional_messages);

fn generate_strings() -> Vec<TestStrings> {
    let mut s = "hello world from quick-protobuf!!!".split('_').cycle().map(|s| s.to_string());
    (1..100).map(|_| TestStrings {
        s1: s.by_ref().next(),
        s2: s.by_ref().next(),
        s3: s.by_ref().next(),
    }).collect()
}

perfbench!(generate_strings, TestStrings, write_strings, read_strings);

fn generate_small_bytes() -> Vec<TestBytes> {
    let mut s = "hello world from quick-protobuf!!!".split('_').cycle()
        .map(|s| s.as_bytes().to_vec());
    (1..800).map(|_| TestBytes { b1: s.by_ref().next() })
        .collect()
}

perfbench!(generate_small_bytes, TestBytes, write_small_bytes, read_small_bytes);

fn generate_large_bytes() -> Vec<TestBytes> {
    let mut s = "hello world from quick-protobuf!!!".split('_').cycle().map(|s| s.as_bytes());
    (1..30).map(|_| TestBytes {
        b1: Some(s.by_ref().take(500).fold(Vec::new(), |mut cur, nxt| {
                cur.extend_from_slice(nxt);
                cur
            }))
    }).collect()
}

perfbench!(generate_large_bytes, TestBytes, write_large_bytes, read_large_bytes);

fn generate_all() -> Vec<PerftestData> {
    vec![PerftestData {
        test1: generate_test1(),
        test_repeated_bool: generate_repeated_bool(),
        test_repeated_messages: generate_repeated_messages(),
        test_optional_messages: generate_optional_messages(),
        test_strings: generate_strings(),
        test_repeated_packed_int32: generate_repeated_packed_int32(),
        test_small_bytearrays: generate_small_bytes(),
        test_large_bytearrays: generate_large_bytes(),
    }]
}

perfbench!(generate_all, PerftestData, write_all, read_all);
<commit_msg>fix unit benches<commit_after>#![feature(test)]

extern crate quick_protobuf;
extern crate test;

mod perftest_data;

use test::{Bencher, black_box};
use perftest_data::*;

use std::cmp::min;
use std::borrow::Cow;
use std::fs::File;
use std::io::Read;

use quick_protobuf::{Reader, Writer};
use quick_protobuf::message::{MessageWrite};

#[bench]
fn read_file(b: &mut Bencher) {
    b.iter(|| {
        let mut f = File::open("benches/rust-protobuf/perftest_data.pbbin").unwrap();
        let len = f.metadata().unwrap().len() as usize;
        let mut bytes = Vec::with_capacity(len);
        f.read_to_end(&mut bytes).unwrap();
        let mut reader = Reader::from_bytes(&bytes);
        let _ = black_box(::perftest_data::PerftestData::from_reader(&mut reader, &bytes).unwrap());
    })
}

macro_rules! perfbench {
    ($gen: ident, $m:ident, $write:ident, $read:ident) => {
#[bench]
fn $write(b: &mut Bencher) {
    let v = $gen();
    b.iter(|| {
        let mut buf = black_box(Vec::new());
        let mut w = Writer::new(&mut buf);
        for i in &v {
            i.write_message(&mut w).unwrap();
        }
    })
}

#[bench]
fn $read(b: &mut Bencher) {
    let v = $gen();
    let mut buf = Vec::new();
    {
        let mut w = Writer::new(&mut buf);
        for i in &v {
            i.write_message(&mut w).unwrap();
        }
    }
    b.iter(|| {
        let mut r = Reader::from_bytes(&buf);
        while !r.is_eof() {
            let _ = black_box($m::from_reader(&mut r, &buf).unwrap());
        }
    })
}
    }
}

fn generate_test1() -> Vec<Test1> {
    (0..500).map(|i| Test1 { value: Some(i) })
        .chain((0..200).map(|_| Test1 { value: None }))
        .collect()
}

perfbench!(generate_test1, Test1, write_test1, read_test1);

fn generate_repeated_bool() -> Vec<TestRepeatedBool> {
    (1..10).map(|j| TestRepeatedBool { values: (0..100).map(|i| i % j == 0).collect() })
        .collect()
}

perfbench!(generate_repeated_bool, TestRepeatedBool, write_repeated_bool, read_repeated_bool);

fn generate_repeated_packed_int32() -> Vec<TestRepeatedPackedInt32> {
    (1..40).map(|j| TestRepeatedPackedInt32 { values: (0..100).map(|i| i * j).collect() })
        .collect()
}

perfbench!(generate_repeated_packed_int32, TestRepeatedPackedInt32, write_repeated_packed_int32, read_repeated_packed_int32);

fn generate_repeated_messages() -> Vec<TestRepeatedMessages> {
    let mut messages = Vec::new();
    messages.push(TestRepeatedMessages {
        messages1: vec![],
        messages2: vec![],
        messages3: vec![],
    });

    for _ in 0..10 {
        let i1 = min(messages.len() % 3, messages.len() - 1);
        let i2 = min(messages.len() % 6, messages.len() - 1);
        let i3 = min(messages.len() % 9, messages.len() - 1);
        let m1 = messages[i1].clone();
        let m2 = messages[i2].clone();
        let m3 = messages[i3].clone();
        messages.push(TestRepeatedMessages {
            messages1: vec![m1.clone()],
            messages2: vec![m1.clone(), m2.clone()],
            messages3: vec![m1.clone(), m2.clone(), m3.clone()],
        });
    }
    messages
}

perfbench!(generate_repeated_messages, TestRepeatedMessages, write_repeated_messages, read_repeated_messages);

fn generate_optional_messages() -> Vec<TestOptionalMessages> {
    let mut messages = Vec::new();
    messages.push(TestOptionalMessages {
        message1: None,
        message2: None,
        message3: None,
    });

    for _ in 0..10 {
        let i1 = min(messages.len() % 3, messages.len() - 1);
        let i2 = min(messages.len() % 6, messages.len() - 1);
        let i3 = min(messages.len() % 9, messages.len() - 1);
        let m1 = messages[i1].clone();
        let m2 = messages[i2].clone();
        let m3 = messages[i3].clone();
        messages.push(TestOptionalMessages {
            message1: Some(Box::new(m1.clone())),
            message2: Some(Box::new(m2.clone())),
            message3: Some(Box::new(m3.clone())),
        });
    }
    messages
}

perfbench!(generate_optional_messages, TestOptionalMessages, write_optional_messages, read_optional_messages);

fn generate_strings() -> Vec<TestStrings<'static>> {
    let mut s = "hello world from quick-protobuf!!!".split('_').cycle().map(|s| Cow::Borrowed(s));
    (1..100).map(|_| TestStrings {
        s1: s.by_ref().next(),
        s2: s.by_ref().next(),
        s3: s.by_ref().next(),
    }).collect()
}

perfbench!(generate_strings, TestStrings, write_strings, read_strings);

fn generate_small_bytes() -> Vec<TestBytes<'static>> {
    let mut s = "hello world from quick-protobuf!!!".split('_').cycle()
        .map(|s| Cow::Borrowed(s.as_bytes()));
    (1..800).map(|_| TestBytes { b1: s.by_ref().next() })
        .collect()
}

perfbench!(generate_small_bytes, TestBytes, write_small_bytes, read_small_bytes);

fn generate_large_bytes() -> Vec<TestBytes<'static>> {
    let mut s = "hello world from quick-protobuf!!!".split('_').cycle().map(|s| s.as_bytes());
    (1..30).map(|_| TestBytes {
        b1: Some(Cow::Owned(s.by_ref().take(500).fold(Vec::new(), |mut cur, nxt| {
                cur.extend_from_slice(nxt);
                cur
            })))
    }).collect()
}

perfbench!(generate_large_bytes, TestBytes, write_large_bytes, read_large_bytes);

fn generate_all() -> Vec<PerftestData<'static>> {
    vec![PerftestData {
        test1: generate_test1(),
        test_repeated_bool: generate_repeated_bool(),
        test_repeated_messages: generate_repeated_messages(),
        test_optional_messages: generate_optional_messages(),
        test_strings: generate_strings(),
        test_repeated_packed_int32: generate_repeated_packed_int32(),
        test_small_bytearrays: generate_small_bytes(),
        test_large_bytearrays: generate_large_bytes(),
    }]
}

perfbench!(generate_all, PerftestData, write_all, read_all);
<|endoftext|>


<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::convert::TryFrom;
use std::fs::File;
use std::io::{Stderr, Stdin, Stdout};
use std::mem;
use std::net::UdpSocket;
use std::ops::Drop;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::net::{UnixDatagram, UnixStream};

use serde::{Deserialize, Serialize};

use crate::net::UnlinkUnixSeqpacketListener;
use crate::{errno_result, PollToken, Result};

pub type RawDescriptor = RawFd;

/// Trait for forfeiting ownership of the current raw descriptor, and returning the raw descriptor
pub trait IntoRawDescriptor {
    fn into_raw_descriptor(self) -> RawDescriptor;
}

/// Trait for returning the underlying raw descriptor, without giving up ownership of the
/// descriptor.
pub trait AsRawDescriptor {
    fn as_raw_descriptor(&self) -> RawDescriptor;
}

pub trait FromRawDescriptor {
    /// # Safety
    /// Safe only if the caller ensures nothing has access to the descriptor after passing it to
    /// `from_raw_descriptor`
    unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self;
}

/// Clones `descriptor`, returning a new `RawDescriptor` that refers to the same open file
/// description as `descriptor`. The cloned descriptor will have the `FD_CLOEXEC` flag set but will
/// not share any other file descriptor flags with `descriptor`.
pub fn clone_descriptor(descriptor: &dyn AsRawDescriptor) -> Result<RawDescriptor> {
    clone_fd(&descriptor.as_raw_descriptor())
}

/// Clones `fd`, returning a new file descriptor that refers to the same open file description as
/// `fd`. The cloned fd will have the `FD_CLOEXEC` flag set but will not share any other file
/// descriptor flags with `fd`.
pub fn clone_fd(fd: &dyn AsRawFd) -> Result<RawFd> {
    // Safe because this doesn't modify any memory and we check the return value.
    let ret = unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_DUPFD_CLOEXEC, 0) };
    if ret < 0 {
        errno_result()
    } else {
        Ok(ret)
    }
}

/// Wraps a RawDescriptor and safely closes it when self falls out of scope.
#[derive(Serialize, Deserialize, Debug, Eq)]
#[serde(transparent)]
pub struct SafeDescriptor {
    #[serde(with = "crate::with_raw_descriptor")]
    descriptor: RawDescriptor,
}

const KCMP_FILE: u32 = 0;

impl PartialEq for SafeDescriptor {
    fn eq(&self, other: &Self) -> bool {
        // If RawFd numbers match then we can return early without calling kcmp
        if self.descriptor == other.descriptor {
            return true;
        }

        // safe because we only use the return value and libc says it's always successful
        let pid = unsafe { libc::getpid() };
        // safe because we are passing everything by value and checking the return value
        let ret = unsafe {
            libc::syscall(
                libc::SYS_kcmp,
                pid,
                pid,
                KCMP_FILE,
                self.descriptor,
                other.descriptor,
            )
        };

        ret == 0
    }
}

impl Drop for SafeDescriptor {
    fn drop(&mut self) {
        let _ = unsafe { libc::close(self.descriptor) };
    }
}

impl AsRawDescriptor for SafeDescriptor {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.descriptor
    }
}

impl IntoRawDescriptor for SafeDescriptor {
    fn into_raw_descriptor(self) -> RawDescriptor {
        let descriptor = self.descriptor;
        mem::forget(self);
        descriptor
    }
}

impl FromRawDescriptor for SafeDescriptor {
    unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
        SafeDescriptor { descriptor }
    }
}

impl AsRawFd for SafeDescriptor {
    fn as_raw_fd(&self) -> RawFd {
        self.as_raw_descriptor()
    }
}

impl TryFrom<&dyn AsRawFd> for SafeDescriptor {
    type Error = std::io::Error;

    fn try_from(fd: &dyn AsRawFd) -> std::result::Result<Self, Self::Error> {
        Ok(SafeDescriptor {
            descriptor: clone_fd(fd)?,
        })
    }
}

impl SafeDescriptor {
    /// Clones this descriptor, internally creating a new descriptor. The new SafeDescriptor will
    /// share the same underlying count within the kernel.
    pub fn try_clone(&self) -> Result<SafeDescriptor> {
        // Safe because this doesn't modify any memory and we check the return value.
        let descriptor = unsafe { libc::fcntl(self.descriptor, libc::F_DUPFD_CLOEXEC, 0) };
        if descriptor < 0 {
            errno_result()
        } else {
            Ok(SafeDescriptor { descriptor })
        }
    }
}

impl From<SafeDescriptor> for File {
    fn from(s: SafeDescriptor) -> File {
        // Safe because we own the SafeDescriptor at this point.
        unsafe { File::from_raw_fd(s.into_raw_descriptor()) }
    }
}

impl From<File> for SafeDescriptor {
    fn from(f: File) -> SafeDescriptor {
        // Safe because we own the File at this point.
        unsafe { SafeDescriptor::from_raw_descriptor(f.into_raw_descriptor()) }
    }
}

impl From<SafeDescriptor> for UnixStream {
    fn from(s: SafeDescriptor) -> Self {
        // Safe because we own the SafeDescriptor at this point.
        unsafe { Self::from_raw_fd(s.into_raw_descriptor()) }
    }
}

/// For use cases where a simple wrapper around a RawDescriptor is needed.
/// This is a simply a wrapper and does not manage the lifetime of the descriptor.
/// Most usages should prefer SafeDescriptor or using a RawDescriptor directly
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Descriptor(pub RawDescriptor);
impl AsRawDescriptor for Descriptor {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.0
    }
}

// AsRawFd for interoperability with interfaces that require it. Within crosvm,
// always use AsRawDescriptor when possible.
impl AsRawFd for Descriptor {
    fn as_raw_fd(&self) -> RawFd {
        self.0
    }
}

/// Implement token for implementations that wish to use this struct as such
impl PollToken for Descriptor {
    fn as_raw_token(&self) -> u64 {
        self.0 as u64
    }

    fn from_raw_token(data: u64) -> Self {
        Descriptor(data as RawDescriptor)
    }
}

macro_rules! AsRawDescriptor {
    ($name:ident) => {
        impl AsRawDescriptor for $name {
            fn as_raw_descriptor(&self) -> RawDescriptor {
                self.as_raw_fd()
            }
        }
    };
}

macro_rules! FromRawDescriptor {
    ($name:ident) => {
        impl FromRawDescriptor for $name {
            unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
                $name::from_raw_fd(descriptor)
            }
        }
    };
}

macro_rules! IntoRawDescriptor {
    ($name:ident) => {
        impl IntoRawDescriptor for $name {
            fn into_raw_descriptor(self) -> RawDescriptor {
                self.into_raw_fd()
            }
        }
    };
}

// Implementations for File. This enables the File-type to use
// RawDescriptor, but does not mean File should be used as a generic
// descriptor container. That should go to either SafeDescriptor or another more
// relevant container type.
AsRawDescriptor!(File);
AsRawDescriptor!(UnlinkUnixSeqpacketListener);
FromRawDescriptor!(File);
IntoRawDescriptor!(File);
AsRawDescriptor!(Stdin);
AsRawDescriptor!(Stdout);
AsRawDescriptor!(Stderr);

impl AsRawDescriptor for UdpSocket {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.as_raw_fd()
    }
}

impl AsRawDescriptor for UnixStream {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.as_raw_fd()
    }
}

impl AsRawDescriptor for UnixDatagram {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.as_raw_fd()
    }
}

impl FromRawDescriptor for UnixDatagram {
    unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
        Self::from_raw_fd(descriptor)
    }
}

impl IntoRawDescriptor for UnixDatagram {
    fn into_raw_descriptor(self) -> RawDescriptor {
        self.into_raw_fd()
    }
}

#[test]
fn clone_equality() {
    let ret = unsafe { libc::eventfd(0, 0) };
    if ret < 0 {
        panic!("failed to create eventfd");
    }
    let descriptor = unsafe { SafeDescriptor::from_raw_descriptor(ret) };

    assert_eq!(descriptor, descriptor);

    assert_eq!(
        descriptor,
        descriptor.try_clone().expect("failed to clone eventfd")
    );

    let ret = unsafe { libc::eventfd(0, 0) };
    if ret < 0 {
        panic!("failed to create eventfd");
    }
    let another = unsafe { SafeDescriptor::from_raw_descriptor(ret) };

    assert_ne!(descriptor, another);
}
<commit_msg>Use macros for trait implementations.<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::convert::TryFrom;
use std::fs::File;
use std::io::{Stderr, Stdin, Stdout};
use std::mem;
use std::net::UdpSocket;
use std::ops::Drop;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::net::{UnixDatagram, UnixStream};

use serde::{Deserialize, Serialize};

use crate::net::UnlinkUnixSeqpacketListener;
use crate::{errno_result, PollToken, Result};

pub type RawDescriptor = RawFd;

/// Trait for forfeiting ownership of the current raw descriptor, and returning the raw descriptor
pub trait IntoRawDescriptor {
    fn into_raw_descriptor(self) -> RawDescriptor;
}

/// Trait for returning the underlying raw descriptor, without giving up ownership of the
/// descriptor.
pub trait AsRawDescriptor {
    fn as_raw_descriptor(&self) -> RawDescriptor;
}

pub trait FromRawDescriptor {
    /// # Safety
    /// Safe only if the caller ensures nothing has access to the descriptor after passing it to
    /// `from_raw_descriptor`
    unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self;
}

/// Clones `descriptor`, returning a new `RawDescriptor` that refers to the same open file
/// description as `descriptor`. The cloned descriptor will have the `FD_CLOEXEC` flag set but will
/// not share any other file descriptor flags with `descriptor`.
pub fn clone_descriptor(descriptor: &dyn AsRawDescriptor) -> Result<RawDescriptor> {
    clone_fd(&descriptor.as_raw_descriptor())
}

/// Clones `fd`, returning a new file descriptor that refers to the same open file description as
/// `fd`. The cloned fd will have the `FD_CLOEXEC` flag set but will not share any other file
/// descriptor flags with `fd`.
pub fn clone_fd(fd: &dyn AsRawFd) -> Result<RawFd> {
    // Safe because this doesn't modify any memory and we check the return value.
    let ret = unsafe { libc::fcntl(fd.as_raw_fd(), libc::F_DUPFD_CLOEXEC, 0) };
    if ret < 0 {
        errno_result()
    } else {
        Ok(ret)
    }
}

/// Wraps a RawDescriptor and safely closes it when self falls out of scope.
#[derive(Serialize, Deserialize, Debug, Eq)]
#[serde(transparent)]
pub struct SafeDescriptor {
    #[serde(with = "crate::with_raw_descriptor")]
    descriptor: RawDescriptor,
}

const KCMP_FILE: u32 = 0;

impl PartialEq for SafeDescriptor {
    fn eq(&self, other: &Self) -> bool {
        // If RawFd numbers match then we can return early without calling kcmp
        if self.descriptor == other.descriptor {
            return true;
        }

        // safe because we only use the return value and libc says it's always successful
        let pid = unsafe { libc::getpid() };
        // safe because we are passing everything by value and checking the return value
        let ret = unsafe {
            libc::syscall(
                libc::SYS_kcmp,
                pid,
                pid,
                KCMP_FILE,
                self.descriptor,
                other.descriptor,
            )
        };

        ret == 0
    }
}

impl Drop for SafeDescriptor {
    fn drop(&mut self) {
        let _ = unsafe { libc::close(self.descriptor) };
    }
}

impl AsRawDescriptor for SafeDescriptor {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.descriptor
    }
}

impl IntoRawDescriptor for SafeDescriptor {
    fn into_raw_descriptor(self) -> RawDescriptor {
        let descriptor = self.descriptor;
        mem::forget(self);
        descriptor
    }
}

impl FromRawDescriptor for SafeDescriptor {
    unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
        SafeDescriptor { descriptor }
    }
}

impl AsRawFd for SafeDescriptor {
    fn as_raw_fd(&self) -> RawFd {
        self.as_raw_descriptor()
    }
}

impl TryFrom<&dyn AsRawFd> for SafeDescriptor {
    type Error = std::io::Error;

    fn try_from(fd: &dyn AsRawFd) -> std::result::Result<Self, Self::Error> {
        Ok(SafeDescriptor {
            descriptor: clone_fd(fd)?,
        })
    }
}

impl SafeDescriptor {
    /// Clones this descriptor, internally creating a new descriptor. The new SafeDescriptor will
    /// share the same underlying count within the kernel.
    pub fn try_clone(&self) -> Result<SafeDescriptor> {
        // Safe because this doesn't modify any memory and we check the return value.
        let descriptor = unsafe { libc::fcntl(self.descriptor, libc::F_DUPFD_CLOEXEC, 0) };
        if descriptor < 0 {
            errno_result()
        } else {
            Ok(SafeDescriptor { descriptor })
        }
    }
}

impl From<SafeDescriptor> for File {
    fn from(s: SafeDescriptor) -> File {
        // Safe because we own the SafeDescriptor at this point.
        unsafe { File::from_raw_fd(s.into_raw_descriptor()) }
    }
}

impl From<File> for SafeDescriptor {
    fn from(f: File) -> SafeDescriptor {
        // Safe because we own the File at this point.
        unsafe { SafeDescriptor::from_raw_descriptor(f.into_raw_descriptor()) }
    }
}

impl From<SafeDescriptor> for UnixStream {
    fn from(s: SafeDescriptor) -> Self {
        // Safe because we own the SafeDescriptor at this point.
        unsafe { Self::from_raw_fd(s.into_raw_descriptor()) }
    }
}

/// For use cases where a simple wrapper around a RawDescriptor is needed.
/// This is a simply a wrapper and does not manage the lifetime of the descriptor.
/// Most usages should prefer SafeDescriptor or using a RawDescriptor directly
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Descriptor(pub RawDescriptor);
impl AsRawDescriptor for Descriptor {
    fn as_raw_descriptor(&self) -> RawDescriptor {
        self.0
    }
}

// AsRawFd for interoperability with interfaces that require it. Within crosvm,
// always use AsRawDescriptor when possible.
impl AsRawFd for Descriptor {
    fn as_raw_fd(&self) -> RawFd {
        self.0
    }
}

/// Implement token for implementations that wish to use this struct as such
impl PollToken for Descriptor {
    fn as_raw_token(&self) -> u64 {
        self.0 as u64
    }

    fn from_raw_token(data: u64) -> Self {
        Descriptor(data as RawDescriptor)
    }
}

macro_rules! AsRawDescriptor {
    ($name:ident) => {
        impl AsRawDescriptor for $name {
            fn as_raw_descriptor(&self) -> RawDescriptor {
                self.as_raw_fd()
            }
        }
    };
}

macro_rules! FromRawDescriptor {
    ($name:ident) => {
        impl FromRawDescriptor for $name {
            unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
                $name::from_raw_fd(descriptor)
            }
        }
    };
}

macro_rules! IntoRawDescriptor {
    ($name:ident) => {
        impl IntoRawDescriptor for $name {
            fn into_raw_descriptor(self) -> RawDescriptor {
                self.into_raw_fd()
            }
        }
    };
}

// Implementations for File. This enables the File-type to use
// RawDescriptor, but does not mean File should be used as a generic
// descriptor container. That should go to either SafeDescriptor or another more
// relevant container type.
AsRawDescriptor!(File);
AsRawDescriptor!(UnlinkUnixSeqpacketListener);
AsRawDescriptor!(UdpSocket);
AsRawDescriptor!(UnixDatagram);
AsRawDescriptor!(UnixStream);
FromRawDescriptor!(File);
FromRawDescriptor!(UnixDatagram);
IntoRawDescriptor!(File);
IntoRawDescriptor!(UnixDatagram);
AsRawDescriptor!(Stdin);
AsRawDescriptor!(Stdout);
AsRawDescriptor!(Stderr);

#[test]
fn clone_equality() {
    let ret = unsafe { libc::eventfd(0, 0) };
    if ret < 0 {
        panic!("failed to create eventfd");
    }
    let descriptor = unsafe { SafeDescriptor::from_raw_descriptor(ret) };

    assert_eq!(descriptor, descriptor);

    assert_eq!(
        descriptor,
        descriptor.try_clone().expect("failed to clone eventfd")
    );

    let ret = unsafe { libc::eventfd(0, 0) };
    if ret < 0 {
        panic!("failed to create eventfd");
    }
    let another = unsafe { SafeDescriptor::from_raw_descriptor(ret) };

    assert_ne!(descriptor, another);
}
<|endoftext|>