<commit_before>extern crate tensorflow_sys as tf;

use super::Graph;
use super::GraphTrait;
use super::Output;
use super::Result;
use super::Status;
use std::ffi::CString;
use std::ffi::NulError;
use std::mem;
use std::os::raw::c_int;
use std::ptr;
use std::result;
use std::slice;

// This exists purely to ensure TF_AbortWhile gets called properly, even on panic.
#[derive(Debug)]
struct CWhileParams {
    inner: tf::TF_WhileParams,
    finished: bool,
}

impl Drop for CWhileParams {
    fn drop(&mut self) {
        if !self.finished {
            unsafe {
                tf::TF_AbortWhile(&self.inner);
            }
        }
    }
}

/// A WhileParams is used to build a while loop.
#[derive(Debug)]
pub struct WhileParams<'a> {
    graph: &'a mut Graph,
    inner: CWhileParams,
    name: Option<CString>,
    c_inputs: Vec<tf::TF_Output>, // must live until TF_FinishWhile
}

impl<'a> WhileParams<'a> {
    /// Creates a WhileParams for creating a while loop.
    ///
    /// The loop is not actually added to the graph until `finish` is called.
    ///
    /// # Arguments
    ///
    /// * `graph` - graph to create the while loop in
    /// * `cond` - takes the condition subgraph and loop variables and returns a
    ///   scalar boolean
    /// * `body` - takes the body subgraph and loop variables and returns the new
    ///   values of the loop variables
    /// * `inputs` - outputs that already exist in `graph` used as initial values
    ///   for the loop variables
    ///
    /// # Returns
    ///
    /// A unfinished WhileParams.
    pub fn new<
        CF: Fn(&mut Graph, &[Output]) -> Result<Output>,
        BF: Fn(&mut Graph, &[Output]) -> Result<Vec<Output>>,
    >(
        graph: &'a mut Graph,
        cond: CF,
        body: BF,
        inputs: &[Output],
    ) -> Result<Self> {
        let mut status = Status::new();
        let c_inputs: Vec<_> = inputs.iter().map(Output::to_c).collect();
        let mut inner = CWhileParams {
            inner: unsafe {
                tf::TF_NewWhile(
                    graph.inner(),
                    c_inputs.as_ptr() as *mut _,
                    c_inputs.len() as c_int,
                    status.inner(),
                    )
            },
            finished: false,
        };
        if let Err(e) = status.into_result() {
            inner.finished = true; // used by Drop impl
            return Err(e);
        }

        // Fill in the condition graph
        let mut cond_graph = unsafe { Graph::from_c(inner.inner.cond_graph as *mut _) };
        let cond_inputs: Vec<_> = unsafe {
            slice::from_raw_parts(inner.inner.cond_inputs, inputs.len())
                .iter()
                .map(|out| Output::from_c(graph, out))
                .collect()
        };
        let cond_out = cond(&mut cond_graph, &cond_inputs)?;
        inner.inner.cond_output = cond_out.to_c();

        // Fill in the body graph
        let mut body_graph = unsafe { Graph::from_c(inner.inner.body_graph as *mut _) };
        let body_inputs: Vec<_> = unsafe {
            slice::from_raw_parts(inner.inner.body_inputs, inputs.len())
                .iter()
                .map(|out| Output::from_c(graph, out))
                .collect()
        };
        let body_out = body(&mut body_graph, &body_inputs)?;
        if body_out.len() != inputs.len() {
            return Err(invalid_arg!(
                "Expected {} outputs, but got {}",
                inputs.len(),
                body_out.len()
            ));
        }
        let c_body_out =
            unsafe { slice::from_raw_parts_mut(inner.inner.body_outputs as *mut _, inputs.len()) };
        for i in 0..inputs.len() {
            c_body_out[i] = body_out[i].to_c();
        }

        Ok(WhileParams {
            graph,
            inner,
            name: None,
            c_inputs,
        })
    }

    /// Sets a unique name for this while loop. This is used as a prefix
    /// for created operations. If not set, a unique prefix will be generated.
    pub fn set_name(&mut self, name: &str) -> result::Result<(), NulError> {
        self.name = Some(CString::new(name)?);
        Ok(())
    }

    /// Builds the while loop and returns the output tensors of the while loop.
    pub fn finish(mut self) -> Result<Vec<Output>> {
        let status = Status::new();
        let mut c_outputs: Vec<tf::TF_Output> =
            Vec::with_capacity(self.inner.inner.ninputs as usize);

        let mut name = None;
        mem::swap(&mut self.name, &mut name);
        let name = match name {
            None => {
                // Include /Merge because while_loop_{} doesn't describe an
                // operation on its own.
                let while_loop_index = self.graph.generate_operation_name("while_loop_{}/Merge")?;
                CString::new(format!("while_loop_{}", while_loop_index))?
            }
            Some(name) => name,
        };
        self.inner.inner.name = name.as_ptr();

        unsafe {
            c_outputs.set_len(self.inner.inner.ninputs as usize);
            for i in 0..c_outputs.len() {
                // For some reason, these have to be initialized to {null, -1},
                // even though they're output parameters.
                c_outputs[i].oper = ptr::null_mut();
                c_outputs[i].index = -1;
            }
            self.inner.finished = true; // used by Drop impl
            tf::TF_FinishWhile(&self.inner.inner, status.inner, c_outputs.as_mut_ptr());
        }
        status.into_result()?;
        Ok(c_outputs
            .iter()
            .map(|out| Output::from_c(self.graph, out))
            .collect())
    }
}

////////////////////////

#[cfg(test)]
mod tests {
    use super::super::DataType;
    use super::super::Operation;
    use super::super::Session;
    use super::super::SessionOptions;
    use super::super::StepWithGraph;
    use super::super::Tensor;
    use super::*;

    fn constant(graph: &mut Graph, name: &str, value: i32) -> Operation {
        let value = Tensor::<i32>::new(&[]).with_values(&[value]).unwrap();
        let mut nd = graph.new_operation("Const", name).unwrap();
        nd.set_attr_type("dtype", DataType::Int32).unwrap();
        nd.set_attr_tensor("value", value).unwrap();
        nd.finish().unwrap()
    }

    fn while_cond(graph: &mut Graph, inputs: &[Output]) -> Result<Output> {
        let ten = constant(graph, "ten", 10);
        let counter = inputs[0].clone();
        let less = {
            let mut nd = graph.new_operation("Less", "less").unwrap();
            nd.add_input(Output {
                operation: counter.operation.clone(),
                index: 0,
            });
            nd.add_input(Output {
                operation: ten,
                index: 0,
            });
            nd.finish().unwrap()
        };
        Ok(Output {
            operation: less,
            index: 0,
        })
    }

    fn while_body(graph: &mut Graph, inputs: &[Output]) -> Result<Vec<Output>> {
        let two = constant(graph, "two", 2);
        let counter = inputs[0].clone();
        let mul = {
            let mut nd = graph.new_operation("Mul", "mul").unwrap();
            nd.add_input(counter);
            nd.add_input(Output {
                operation: two,
                index: 0,
            });
            nd.finish().unwrap()
        };
        Ok(vec![
            Output {
                operation: mul,
                index: 0,
            },
        ])
    }

    fn while_loop<
        CF: Fn(&mut Graph, &[Output]) -> Result<Output>,
        BF: Fn(&mut Graph, &[Output]) -> Result<Vec<Output>>,
    >(
        graph: &mut Graph,
        cond: CF,
        body: BF,
        inputs: &[Output],
        name: Option<&str>,
    ) -> Result<Vec<Output>> {
        let mut params = WhileParams::new(graph, cond, body, inputs)?;
        if let Some(name) = name {
            params.set_name(name)?;
        }
        params.finish()
    }

    #[test]
    fn simple_while() {
        let mut main_graph = Graph::new();
        let one = constant(&mut main_graph, "one", 1);
        let output = while_loop(
            &mut main_graph,
            while_cond,
            while_body,
            &[
                Output {
                    operation: one.clone(),
                    index: 0,
                },
            ],
            Some("foo"),
        ).unwrap();
        assert_eq!(1, output.len());
        let options = SessionOptions::new();
        let mut session = Session::new(&options, &main_graph).unwrap();
        let mut step = StepWithGraph::new();
        let output_token = step.request_output(&output[0].operation, 0);
        session.run(&mut step).unwrap();
        let output_tensor = step.take_output::<i32>(output_token).unwrap();
        assert_eq!(&output_tensor[..], &[16i32]);
    }

    #[test]
    fn generated_name_while() {
        // Make sure that TensorFlow doesn't complain about duplicate names
        let mut main_graph = Graph::new();
        let one = constant(&mut main_graph, "one", 1);
        while_loop(
            &mut main_graph,
            while_cond,
            while_body,
            &[
                Output {
                    operation: one.clone(),
                    index: 0,
                },
            ],
            None,
        ).unwrap();
        while_loop(
            &mut main_graph,
            while_cond,
            while_body,
            &[
                Output {
                    operation: one,
                    index: 0,
                },
            ],
            None,
        ).unwrap();
    }
}
<commit_msg>Use a more standard builder pattern for WhileBuilder<commit_after>extern crate tensorflow_sys as tf;

use super::Graph;
use super::GraphTrait;
use super::Output;
use super::Result;
use super::Status;
use std::ffi::CString;
use std::ffi::NulError;
use std::mem;
use std::os::raw::c_int;
use std::ptr;
use std::result;
use std::slice;

// This exists purely to ensure TF_AbortWhile gets called properly, even on panic.
#[derive(Debug)]
struct CWhileParams {
    inner: tf::TF_WhileParams,
    finished: bool,
}

impl Drop for CWhileParams {
    fn drop(&mut self) {
        if !self.finished {
            unsafe {
                tf::TF_AbortWhile(&self.inner);
            }
        }
    }
}

/// A WhileBuilder is used to build a while loop.
#[derive(Debug)]
pub struct WhileBuilder<'a> {
    graph: &'a mut Graph,
    inner: CWhileParams,
    name: Option<CString>,
    c_inputs: Vec<tf::TF_Output>, // must live until TF_FinishWhile
}

impl<'a> WhileBuilder<'a> {
    /// Creates a WhileBuilder for creating a while loop.
    ///
    /// The loop is not actually added to the graph until `finish` is called.
    ///
    /// # Arguments
    ///
    /// * `graph` - graph to create the while loop in
    /// * `cond` - takes the condition subgraph and loop variables and returns a
    ///   scalar boolean
    /// * `body` - takes the body subgraph and loop variables and returns the new
    ///   values of the loop variables
    /// * `inputs` - outputs that already exist in `graph` used as initial values
    ///   for the loop variables
    ///
    /// # Returns
    ///
    /// A unfinished WhileBuilder.
    pub fn new<
        CF: Fn(&mut Graph, &[Output]) -> Result<Output>,
        BF: Fn(&mut Graph, &[Output]) -> Result<Vec<Output>>,
    >(
        graph: &'a mut Graph,
        cond: CF,
        body: BF,
        inputs: &[Output],
    ) -> Result<Self> {
        let mut status = Status::new();
        let c_inputs: Vec<_> = inputs.iter().map(Output::to_c).collect();
        let mut inner = CWhileParams {
            inner: unsafe {
                tf::TF_NewWhile(
                    graph.inner(),
                    c_inputs.as_ptr() as *mut _,
                    c_inputs.len() as c_int,
                    status.inner(),
                    )
            },
            finished: false,
        };
        if let Err(e) = status.into_result() {
            inner.finished = true; // used by Drop impl
            return Err(e);
        }

        // Fill in the condition graph
        let mut cond_graph = unsafe { Graph::from_c(inner.inner.cond_graph as *mut _) };
        let cond_inputs: Vec<_> = unsafe {
            slice::from_raw_parts(inner.inner.cond_inputs, inputs.len())
                .iter()
                .map(|out| Output::from_c(graph, out))
                .collect()
        };
        let cond_out = cond(&mut cond_graph, &cond_inputs)?;
        inner.inner.cond_output = cond_out.to_c();

        // Fill in the body graph
        let mut body_graph = unsafe { Graph::from_c(inner.inner.body_graph as *mut _) };
        let body_inputs: Vec<_> = unsafe {
            slice::from_raw_parts(inner.inner.body_inputs, inputs.len())
                .iter()
                .map(|out| Output::from_c(graph, out))
                .collect()
        };
        let body_out = body(&mut body_graph, &body_inputs)?;
        if body_out.len() != inputs.len() {
            return Err(invalid_arg!(
                "Expected {} outputs, but got {}",
                inputs.len(),
                body_out.len()
            ));
        }
        let c_body_out =
            unsafe { slice::from_raw_parts_mut(inner.inner.body_outputs as *mut _, inputs.len()) };
        for i in 0..inputs.len() {
            c_body_out[i] = body_out[i].to_c();
        }

        Ok(WhileBuilder {
            graph,
            inner,
            name: None,
            c_inputs,
        })
    }

    /// Sets a unique name for this while loop. This is used as a prefix
    /// for created operations. If not set, a unique prefix will be generated.
    pub fn name(mut self, name: &str) -> result::Result<Self, NulError> {
        self.name = Some(CString::new(name)?);
        Ok(self)
    }

    /// Builds the while loop and returns the output tensors of the while loop.
    pub fn finish(mut self) -> Result<Vec<Output>> {
        let status = Status::new();
        let mut c_outputs: Vec<tf::TF_Output> =
            Vec::with_capacity(self.inner.inner.ninputs as usize);

        let mut name = None;
        mem::swap(&mut self.name, &mut name);
        let name = match name {
            None => {
                // Include /Merge because while_loop_{} doesn't describe an
                // operation on its own.
                let while_loop_index = self.graph.generate_operation_name("while_loop_{}/Merge")?;
                CString::new(format!("while_loop_{}", while_loop_index))?
            }
            Some(name) => name,
        };
        self.inner.inner.name = name.as_ptr();

        unsafe {
            c_outputs.set_len(self.inner.inner.ninputs as usize);
            for i in 0..c_outputs.len() {
                // For some reason, these have to be initialized to {null, -1},
                // even though they're output parameters.
                c_outputs[i].oper = ptr::null_mut();
                c_outputs[i].index = -1;
            }
            self.inner.finished = true; // used by Drop impl
            tf::TF_FinishWhile(&self.inner.inner, status.inner, c_outputs.as_mut_ptr());
        }
        status.into_result()?;
        Ok(c_outputs
            .iter()
            .map(|out| Output::from_c(self.graph, out))
            .collect())
    }
}

////////////////////////

#[cfg(test)]
mod tests {
    use super::super::DataType;
    use super::super::Operation;
    use super::super::Session;
    use super::super::SessionOptions;
    use super::super::StepWithGraph;
    use super::super::Tensor;
    use super::*;

    fn constant(graph: &mut Graph, name: &str, value: i32) -> Operation {
        let value = Tensor::<i32>::new(&[]).with_values(&[value]).unwrap();
        let mut nd = graph.new_operation("Const", name).unwrap();
        nd.set_attr_type("dtype", DataType::Int32).unwrap();
        nd.set_attr_tensor("value", value).unwrap();
        nd.finish().unwrap()
    }

    fn while_cond(graph: &mut Graph, inputs: &[Output]) -> Result<Output> {
        let ten = constant(graph, "ten", 10);
        let counter = inputs[0].clone();
        let less = {
            let mut nd = graph.new_operation("Less", "less").unwrap();
            nd.add_input(Output {
                operation: counter.operation.clone(),
                index: 0,
            });
            nd.add_input(Output {
                operation: ten,
                index: 0,
            });
            nd.finish().unwrap()
        };
        Ok(Output {
            operation: less,
            index: 0,
        })
    }

    fn while_body(graph: &mut Graph, inputs: &[Output]) -> Result<Vec<Output>> {
        let two = constant(graph, "two", 2);
        let counter = inputs[0].clone();
        let mul = {
            let mut nd = graph.new_operation("Mul", "mul").unwrap();
            nd.add_input(counter);
            nd.add_input(Output {
                operation: two,
                index: 0,
            });
            nd.finish().unwrap()
        };
        Ok(vec![
            Output {
                operation: mul,
                index: 0,
            },
        ])
    }

    #[test]
    fn simple_while() {
        let mut main_graph = Graph::new();
        let one = constant(&mut main_graph, "one", 1);
        let output = WhileBuilder::new(
            &mut main_graph,
            while_cond,
            while_body,
            &[
                Output {
                    operation: one.clone(),
                    index: 0,
                },
            ],
        ).unwrap()
            .name("foo")
            .unwrap()
            .finish()
            .unwrap();
        assert_eq!(1, output.len());
        let options = SessionOptions::new();
        let mut session = Session::new(&options, &main_graph).unwrap();
        let mut step = StepWithGraph::new();
        let output_token = step.request_output(&output[0].operation, 0);
        session.run(&mut step).unwrap();
        let output_tensor = step.take_output::<i32>(output_token).unwrap();
        assert_eq!(&output_tensor[..], &[16i32]);
    }

    #[test]
    fn generated_name_while() {
        // Make sure that TensorFlow doesn't complain about duplicate names
        let mut main_graph = Graph::new();
        let one = constant(&mut main_graph, "one", 1);
        WhileBuilder::new(
            &mut main_graph,
            while_cond,
            while_body,
            &[
                Output {
                    operation: one.clone(),
                    index: 0,
                },
            ],
        ).unwrap()
            .finish()
            .unwrap();
        WhileBuilder::new(
            &mut main_graph,
            while_cond,
            while_body,
            &[
                Output {
                    operation: one,
                    index: 0,
                },
            ],
        ).unwrap()
            .finish()
            .unwrap();
    }
}
<|endoftext|>


<commit_before>use std::error;
use std::fmt;

use cssparser::BasicParseError;

use attributes::Attribute;
use parsers::ParseError;

#[derive(Debug, Clone, PartialEq)]
pub enum AttributeError {
    // parse error
    Parse(ParseError),

    // invalid value
    Value(String),
}

#[derive(Debug, Clone, PartialEq)]
pub struct NodeError {
    attr: Attribute,
    err: AttributeError,
}

impl NodeError {
    pub fn parse_error(attr: Attribute, error: ParseError) -> NodeError {
        NodeError {
            attr,
            err: AttributeError::Parse(error),
        }
    }

    pub fn value_error(attr: Attribute, description: &str) -> NodeError {
        NodeError {
            attr,
            err: AttributeError::Value(description.to_string()),
        }
    }

    pub fn attribute_error(attr: Attribute, error: AttributeError) -> NodeError {
        NodeError { attr, err: error }
    }
}

impl error::Error for NodeError {
    fn description(&self) -> &str {
        match self.err {
            AttributeError::Parse(_) => "parse error",
            AttributeError::Value(_) => "invalid attribute value",
        }
    }
}

impl fmt::Display for NodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            AttributeError::Parse(ref n) => write!(
                f,
                "error parsing value for attribute \"{}\": {}",
                self.attr.to_str(),
                n.display
            ),

            AttributeError::Value(ref s) => write!(
                f,
                "invalid value for attribute \"{}\": {}",
                self.attr.to_str(),
                s
            ),
        }
    }
}

impl From<ParseError> for AttributeError {
    fn from(pe: ParseError) -> AttributeError {
        AttributeError::Parse(pe)
    }
}

impl<'a> From<BasicParseError<'a>> for AttributeError {
    fn from(e: BasicParseError) -> AttributeError {
        AttributeError::from(ParseError::from(e))
    }
}

#[cfg(test)]
pub fn is_parse_error<T>(r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err(AttributeError::Parse(_)) => true,
        _ => false,
    }
}

#[cfg(test)]
pub fn is_value_error<T>(r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err(AttributeError::Value(_)) => true,
        _ => false,
    }
}
<commit_msg>Add a RenderingError enum<commit_after>use std::error;
use std::fmt;

use cairo;
use cssparser::BasicParseError;

use attributes::Attribute;
use parsers::ParseError;

#[derive(Debug, Clone, PartialEq)]
pub enum AttributeError {
    // parse error
    Parse(ParseError),

    // invalid value
    Value(String),
}

#[derive(Debug, Clone, PartialEq)]
pub struct NodeError {
    attr: Attribute,
    err: AttributeError,
}

impl NodeError {
    pub fn parse_error(attr: Attribute, error: ParseError) -> NodeError {
        NodeError {
            attr,
            err: AttributeError::Parse(error),
        }
    }

    pub fn value_error(attr: Attribute, description: &str) -> NodeError {
        NodeError {
            attr,
            err: AttributeError::Value(description.to_string()),
        }
    }

    pub fn attribute_error(attr: Attribute, error: AttributeError) -> NodeError {
        NodeError { attr, err: error }
    }
}

impl error::Error for NodeError {
    fn description(&self) -> &str {
        match self.err {
            AttributeError::Parse(_) => "parse error",
            AttributeError::Value(_) => "invalid attribute value",
        }
    }
}

impl fmt::Display for NodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            AttributeError::Parse(ref n) => write!(
                f,
                "error parsing value for attribute \"{}\": {}",
                self.attr.to_str(),
                n.display
            ),

            AttributeError::Value(ref s) => write!(
                f,
                "invalid value for attribute \"{}\": {}",
                self.attr.to_str(),
                s
            ),
        }
    }
}

impl From<ParseError> for AttributeError {
    fn from(pe: ParseError) -> AttributeError {
        AttributeError::Parse(pe)
    }
}

impl<'a> From<BasicParseError<'a>> for AttributeError {
    fn from(e: BasicParseError) -> AttributeError {
        AttributeError::from(ParseError::from(e))
    }
}

#[derive(Clone)]
pub enum RenderingError {
    Cairo(cairo::Status),
    CircularReference,
}

impl From<cairo::Status> for RenderingError {
    fn from(e: cairo::Status) -> RenderingError {
        assert!(e != cairo::Status::Success);

        RenderingError::Cairo(e)
    }
}

#[cfg(test)]
pub fn is_parse_error<T>(r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err(AttributeError::Parse(_)) => true,
        _ => false,
    }
}

#[cfg(test)]
pub fn is_value_error<T>(r: &Result<T, AttributeError>) -> bool {
    match *r {
        Err(AttributeError::Value(_)) => true,
        _ => false,
    }
}
<|endoftext|>


<commit_before>#![ warn( rust_2018_idioms ) ]
#![ warn( missing_debug_implementations ) ]
#![ warn( missing_docs ) ]

// #![ feature( type_name_of_val ) ]

//!
//! Tools for writing procedural macroses.
//!

#![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/Readme.md" ) ) ]

/// Container kind.
pub mod container_kind;
/// Helpers.
pub mod helper;
/// Trait name.
pub mod name;
/// Split with name.
pub mod split_with_name;
/// Syntax.
pub mod syntax;

///
/// Dependencies of the module.
///

pub mod dependencies
{
  pub use ::syn;
  pub use ::quote;
  pub use ::proc_macro2;
}

/// Own namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
}

pub use protected::*;

/// Parented namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;

  pub use super::container_kind::exposed::*;
  pub use super::helper::exposed::*;
  pub use super::name::exposed::*;
  pub use super::split_with_name::exposed::*;
  pub use super::syntax::exposed::*;

}

/// Prelude to use: `use wtools::prelude::*`.
pub mod prelude
{
  pub use super::container_kind::prelude::*;
  pub use super::helper::prelude::*;
  pub use super::name::prelude::*;
  pub use super::split_with_name::prelude::*;
  pub use super::syntax::prelude::*;

  pub use ::syn;
  pub use ::proc_macro2;
  pub use quote;
  pub use quote::quote as qt;
  pub use syn::
  {
    parse::ParseStream,
    Token,
    braced,
    bracketed,
    custom_keyword,
    custom_punctuation,
    parenthesized,
    parse_macro_input,
    parse_quote,
    parse_quote_spanned,
  };

}
<commit_msg>Fix module `proc_macro`, remove import that not allowed by list of features<commit_after>#![ warn( rust_2018_idioms ) ]
#![ warn( missing_debug_implementations ) ]
#![ warn( missing_docs ) ]

// #![ feature( type_name_of_val ) ]

//!
//! Tools for writing procedural macroses.
//!

#![ doc = include_str!( concat!( env!( "CARGO_MANIFEST_DIR" ), "/Readme.md" ) ) ]

/// Container kind.
pub mod container_kind;
/// Helpers.
pub mod helper;
/// Trait name.
pub mod name;
/// Split with name.
pub mod split_with_name;
/// Syntax.
pub mod syntax;

///
/// Dependencies of the module.
///

pub mod dependencies
{
  pub use ::syn;
  pub use ::quote;
  pub use ::proc_macro2;
}

/// Own namespace of the module.
pub mod protected
{
  pub use super::orphan::*;
}

pub use protected::*;

/// Parented namespace of the module.
pub mod orphan
{
  pub use super::exposed::*;
}

/// Exposed namespace of the module.
pub mod exposed
{
  pub use super::prelude::*;

  pub use super::container_kind::exposed::*;
  pub use super::helper::exposed::*;
  pub use super::name::exposed::*;
  pub use super::split_with_name::exposed::*;
  pub use super::syntax::exposed::*;

}

/// Prelude to use: `use wtools::prelude::*`.
pub mod prelude
{
  pub use super::container_kind::prelude::*;
  pub use super::helper::prelude::*;
  pub use super::name::prelude::*;
  pub use super::split_with_name::prelude::*;
  pub use super::syntax::prelude::*;

  pub use ::syn;
  pub use ::proc_macro2;
  pub use quote;
  pub use quote::quote as qt;
  pub use syn::
  {
    parse::ParseStream,
    Token,
    braced,
    bracketed,
    custom_keyword,
    custom_punctuation,
    parenthesized,
    parse_macro_input,
    parse_quote,
    // parse_quote_spanned,
  };

}
<|endoftext|>


<commit_before>// This example uses `main()` at the top so it can be read top to
// bottom. `main()` is usually at the bottom.
fn main() {
    // Create variables which will be borrowed.
    let (four, nine) = (4, 9);

    // Borrows (`&`) of both variables are passed into the function.
    // If a borrow is truly a borrow, the variable must be returned,
    // otherwise a borrow would be transferring ownership. This means
    // no matter what, *any* input which is borrowed via function or
    // otherwise, *must* still exist after the borrower ceases. In
    // other words, *Rule 2* must be true.
    print_refs(&four, &nine);

    // Note that there is no input even though the function specifies
    // a lifetime. The sizedness of that lifetime will be determined
    // by the caller (which is here) from available lifetimes (scopes).
    // Any lifetime chosen will then be larger than that of the function.
    failed_borrow();
}

// `print_refs` takes two references to `i32` which have different
// lifetimes `'a` and `'b`. These two lifetimes must both be at
// least as long as the function `print_refs`.
fn print_refs<'a, 'b>(x: &'a i32, y: &'b i32) {
    println!("x is {} and y is {}", x, y);
}

// There are no references to force `'a` to be larger than the
// function yet, `'a` remains larger than the function.
fn failed_borrow<'a>() {
    let _x = 12;

    // Attempting to use the lifetime `'a` as an explicit type
    // annotation inside the function will fail because the
    // lifetime of `&_x` is smaller than `y` has. A small lifetime
    // cannot be coerced into a larger one.
    //
    //let y: &'a i32 = &_x;
    // ERROR: `_x` does not live long enough
}
<commit_msg>scope/lifetime/explicit: fixing comma position<commit_after>// This example uses `main()` at the top so it can be read top to
// bottom. `main()` is usually at the bottom.
fn main() {
    // Create variables which will be borrowed.
    let (four, nine) = (4, 9);

    // Borrows (`&`) of both variables are passed into the function.
    // If a borrow is truly a borrow, the variable must be returned,
    // otherwise a borrow would be transferring ownership. This means
    // no matter what, *any* input which is borrowed via function or
    // otherwise, *must* still exist after the borrower ceases. In
    // other words, *Rule 2* must be true.
    print_refs(&four, &nine);

    // Note that there is no input even though the function specifies
    // a lifetime. The sizedness of that lifetime will be determined
    // by the caller (which is here) from available lifetimes (scopes).
    // Any lifetime chosen will then be larger than that of the function.
    failed_borrow();
}

// `print_refs` takes two references to `i32` which have different
// lifetimes `'a` and `'b`. These two lifetimes must both be at
// least as long as the function `print_refs`.
fn print_refs<'a, 'b>(x: &'a i32, y: &'b i32) {
    println!("x is {} and y is {}", x, y);
}

// There are no references to force `'a` to be larger than the
// function, yet `'a` remains larger than the function.
fn failed_borrow<'a>() {
    let _x = 12;

    // Attempting to use the lifetime `'a` as an explicit type
    // annotation inside the function will fail because the
    // lifetime of `&_x` is smaller than `y` has. A small lifetime
    // cannot be coerced into a larger one.
    //
    //let y: &'a i32 = &_x;
    // ERROR: `_x` does not live long enough
}
<|endoftext|>


<commit_before>use std::fmt;
use std::ops::Index;

use helper;

// A n-dimensional array
pub struct Array<T> {
    shape: Vec<usize>,
    dim_steps: Vec<usize>, // the ‘volume’ of 1 unit in each dimension.
    buffer: Vec<T>,
}

impl<T> Array<T> {
    pub fn new(shape: Vec<usize>, initial: T) -> Array<T> where T: Clone {
        let buf_size = shape.iter().fold(1, |a, b| a*b);
        let dim_steps = helper::compute_dim_steps(&shape);
        Array {
            shape: shape,
            dim_steps: dim_steps,
            buffer: vec![initial; buf_size],
        }
    }

    pub fn from_vec(shape: Vec<usize>, vec: Vec<T>) -> Array<T> {
        let dim_steps = helper::compute_dim_steps(&shape);
        Array {
            shape: shape,
            dim_steps: dim_steps,
            buffer: vec,
        }
    }

    pub fn get<'a, 'b, I: IntoIterator<Item=&'b usize>>(&'a self, coords: I) -> &'a T {
        let index: usize = coords.into_iter().zip(self.dim_steps.iter())
                                 .map(|(c, s)| (*c)*(*s))
                                 .sum();
        &self.buffer[index]
    }

    pub fn get_mut<'a, 'b, I: IntoIterator<Item=&'b usize>>(&'a mut self, coords: I) -> &'a mut T {
        let index: usize = coords.into_iter().zip(self.dim_steps.iter())
                                 .map(|(c, s)| (*c)*(*s))
                                 .sum();
        &mut self.buffer[index]
    }

    pub fn shape(&self) -> &[usize] {
        &self.shape
    }

    pub fn dim_steps(&self) -> &[usize] {
        &self.shape
    }

    pub fn buffer(&self) -> &[T] {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut [T] {
        &mut self.buffer
    }
}

impl<'a, 'b, T, I: IntoIterator<Item=&'b usize>> Index<I> for Array<T> {
    type Output = T;

    fn index<'r>(&'r self, index: I) -> &'r T {
        self.get(index)
    }
}

impl<T: Clone+fmt::Debug> fmt::Debug for Array<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "[\n"));
        for row in 0..self.shape[0] {
            try!(write!(f, "[{:?}", self.get(&[row, 0])));
            for col in 1..self.shape[1] {
                try!(write!(f, "\t{:?}", self.get(&[row, col])));
            }
            try!(write!(f, "]\n"));
        }
        try!(write!(f, "]\n"));
        Ok(())
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

#[test]
fn test_array_indexing() {
    let a = Array::from_vec(vec![2, 3, 4], vec![1, 2, 3, 4,
                                                5, 6, 7, 8,
                                                9, 10, 11, 12,

                                                13, 14, 15, 16,
                                                17, 18, 19, 20,
                                                21, 22, 23, 24]);
    assert!(a[&[0, 0, 0]] == 1);
    assert!(a[&[0, 0, 1]] == 2);
    assert!(a[&[0, 0, 2]] == 3);
    assert!(a[&[0, 0, 3]] == 4);
    assert!(a[&[0, 1, 0]] == 5);
    assert!(a[&[0, 1, 1]] == 6);
    assert!(a[&[0, 1, 2]] == 7);
    assert!(a[&[0, 1, 3]] == 8);
    assert!(a[&[0, 2, 0]] == 9);
    assert!(a[&[0, 2, 1]] == 10);
    assert!(a[&[0, 2, 2]] == 11);
    assert!(a[&[0, 2, 3]] == 12);
    assert!(a[&[1, 0, 0]] == 13);
    assert!(a[&[1, 0, 1]] == 14);
    assert!(a[&[1, 0, 2]] == 15);
    assert!(a[&[1, 0, 3]] == 16);
    assert!(a[&[1, 1, 0]] == 17);
    assert!(a[&[1, 1, 1]] == 18);
    assert!(a[&[1, 1, 2]] == 19);
    assert!(a[&[1, 1, 3]] == 20);
    assert!(a[&[1, 2, 0]] == 21);
    assert!(a[&[1, 2, 1]] == 22);
    assert!(a[&[1, 2, 2]] == 23);
    assert!(a[&[1, 2, 3]] == 24);
}
<commit_msg>mutable array indexing<commit_after>use std::fmt;
use std::ops::{Index, IndexMut};

use helper;

// A n-dimensional array
pub struct Array<T> {
    shape: Vec<usize>,
    dim_steps: Vec<usize>, // the ‘volume’ of 1 unit in each dimension.
    buffer: Vec<T>,
}

impl<T> Array<T> {
    pub fn new(shape: Vec<usize>, initial: T) -> Array<T> where T: Clone {
        let buf_size = shape.iter().fold(1, |a, b| a*b);
        let dim_steps = helper::compute_dim_steps(&shape);
        Array {
            shape: shape,
            dim_steps: dim_steps,
            buffer: vec![initial; buf_size],
        }
    }

    pub fn from_vec(shape: Vec<usize>, vec: Vec<T>) -> Array<T> {
        let dim_steps = helper::compute_dim_steps(&shape);
        Array {
            shape: shape,
            dim_steps: dim_steps,
            buffer: vec,
        }
    }

    pub fn get<'a, 'b, I: IntoIterator<Item=&'b usize>>(&'a self, coords: I) -> &'a T {
        let index: usize = coords.into_iter().zip(self.dim_steps.iter())
                                 .map(|(c, s)| (*c)*(*s))
                                 .sum();
        &self.buffer[index]
    }

    pub fn get_mut<'a, 'b, I: IntoIterator<Item=&'b usize>>(&'a mut self, coords: I) -> &'a mut T {
        let index: usize = coords.into_iter().zip(self.dim_steps.iter())
                                 .map(|(c, s)| (*c)*(*s))
                                 .sum();
        &mut self.buffer[index]
    }

    pub fn shape(&self) -> &[usize] {
        &self.shape
    }

    pub fn dim_steps(&self) -> &[usize] {
        &self.shape
    }

    pub fn buffer(&self) -> &[T] {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut [T] {
        &mut self.buffer
    }
}

impl<'a, 'b, T, I: IntoIterator<Item=&'b usize>> Index<I> for Array<T> {
    type Output = T;

    fn index<'r>(&'r self, index: I) -> &'r T {
        self.get(index)
    }
}

impl<'a, 'b, T, I: IntoIterator<Item=&'b usize>> IndexMut<I> for Array<T> {
    fn index_mut<'r>(&'r mut self, index: I) -> &'r mut T {
        self.get_mut(index)
    }
}

impl<T: Clone+fmt::Debug> fmt::Debug for Array<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "[\n"));
        for row in 0..self.shape[0] {
            try!(write!(f, "[{:?}", self.get(&[row, 0])));
            for col in 1..self.shape[1] {
                try!(write!(f, "\t{:?}", self.get(&[row, col])));
            }
            try!(write!(f, "]\n"));
        }
        try!(write!(f, "]\n"));
        Ok(())
    }
}

////////////////////////////////////////////////////////////////////////////////////////////////////

#[test]
fn test_array_indexing() {
    let a = Array::from_vec(vec![2, 3, 4], vec![1, 2, 3, 4,
                                                5, 6, 7, 8,
                                                9, 10, 11, 12,

                                                13, 14, 15, 16,
                                                17, 18, 19, 20,
                                                21, 22, 23, 24]);
    assert!(a[&[0, 0, 0]] == 1);
    assert!(a[&[0, 0, 1]] == 2);
    assert!(a[&[0, 0, 2]] == 3);
    assert!(a[&[0, 0, 3]] == 4);
    assert!(a[&[0, 1, 0]] == 5);
    assert!(a[&[0, 1, 1]] == 6);
    assert!(a[&[0, 1, 2]] == 7);
    assert!(a[&[0, 1, 3]] == 8);
    assert!(a[&[0, 2, 0]] == 9);
    assert!(a[&[0, 2, 1]] == 10);
    assert!(a[&[0, 2, 2]] == 11);
    assert!(a[&[0, 2, 3]] == 12);
    assert!(a[&[1, 0, 0]] == 13);
    assert!(a[&[1, 0, 1]] == 14);
    assert!(a[&[1, 0, 2]] == 15);
    assert!(a[&[1, 0, 3]] == 16);
    assert!(a[&[1, 1, 0]] == 17);
    assert!(a[&[1, 1, 1]] == 18);
    assert!(a[&[1, 1, 2]] == 19);
    assert!(a[&[1, 1, 3]] == 20);
    assert!(a[&[1, 2, 0]] == 21);
    assert!(a[&[1, 2, 1]] == 22);
    assert!(a[&[1, 2, 2]] == 23);
    assert!(a[&[1, 2, 3]] == 24);
}

#[test]
fn test_array_indexing_mut() {
    let mut a = Array::from_vec(vec![3], vec![1, 2, 3]);
    a[&[1]] = 42;
    assert!(a[&[1]] == 42);
}
<|endoftext|>


<commit_before>use crate::config::*;
use crate::errors::RunError;
use cargo_metadata::{diagnostic::DiagnosticLevel, CargoOpt, Message, MetadataCommand};
use log::{error, trace};
use std::env;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use walkdir::WalkDir;

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TestBinary {
    path: PathBuf,
    ty: RunType,
    cargo_dir: Option<PathBuf>,
    pkg_name: Option<String>,
    pkg_version: Option<String>,
    pkg_authors: Option<Vec<String>>,
    should_panic: bool,
}

impl TestBinary {
    pub fn new(path: PathBuf, ty: RunType) -> Self {
        Self {
            path,
            ty,
            pkg_name: None,
            pkg_version: None,
            pkg_authors: None,
            cargo_dir: None,
            should_panic: false,
        }
    }

    pub fn path(&self) -> &Path {
        &self.path
    }

    pub fn run_type(&self) -> RunType {
        self.ty
    }

    pub fn manifest_dir(&self) -> &Option<PathBuf> {
        &self.cargo_dir
    }

    pub fn pkg_name(&self) -> &Option<String> {
        &self.pkg_name
    }

    pub fn pkg_version(&self) -> &Option<String> {
        &self.pkg_version
    }

    pub fn pkg_authors(&self) -> &Option<Vec<String>> {
        &self.pkg_authors
    }

    /// Should be `false` for normal tests and for doctests either `true` or
    /// `false` depending on the test attribute
    pub fn should_panic(&self) -> bool {
        self.should_panic
    }
}

pub fn get_tests(config: &Config) -> Result<Vec<TestBinary>, RunError> {
    let mut result = vec![];
    let manifest = match config.manifest.as_path().to_str() {
        Some(s) => s,
        None => "Cargo.toml",
    };
    let metadata = MetadataCommand::new()
        .manifest_path(manifest)
        .features(CargoOpt::AllFeatures)
        .exec()
        .map_err(|e| RunError::Cargo(e.to_string()))?;

    for ty in &config.run_types {
        let mut cmd = create_command(manifest, config, ty);
        cmd.stdout(Stdio::piped());
        if !config.verbose {
            cmd.stderr(Stdio::null());
        }
        trace!("Running command {:?}", cmd);
        let mut child = cmd.spawn().map_err(|e| RunError::Cargo(e.to_string()))?;

        if ty != &RunType::Doctests {
            let mut package_ids = vec![];
            let reader = std::io::BufReader::new(child.stdout.take().unwrap());
            for msg in Message::parse_stream(reader) {
                match msg {
                    Ok(Message::CompilerArtifact(art)) => {
                        if let Some(path) = art.executable {
                            if !art.profile.test && ty == &RunType::Tests {
                                continue;
                            }
                            result.push(TestBinary::new(path, *ty));
                            package_ids.push(art.package_id.clone());
                        }
                    }
                    Ok(Message::CompilerMessage(m)) => match m.message.level {
                        DiagnosticLevel::Error | DiagnosticLevel::Ice => {
                            let _ = child.wait();
                            return Err(RunError::TestCompile(m.message.message));
                        }
                        _ => {}
                    },
                    Err(e) => {
                        error!("Error parsing cargo messages {}", e);
                    }
                    _ => {}
                }
            }
            for (res, package) in result.iter_mut().zip(package_ids.iter()) {
                let package = &metadata[package];
                res.cargo_dir = package.manifest_path.parent().map(|x| x.to_path_buf());
                res.pkg_name = Some(package.name.clone());
                res.pkg_version = Some(package.version.to_string());
                res.pkg_authors = Some(package.authors.clone());
            }
            child.wait().map_err(|e| RunError::Cargo(e.to_string()))?;
        } else {
            // need to wait for compiling to finish before getting doctests
            // also need to wait with output to ensure the stdout buffer doesn't fill up
            let out = child
                .wait_with_output()
                .map_err(|e| RunError::Cargo(e.to_string()))?;
            if !out.status.success() {
                error!("Building doctests failed");
            }
            let walker = WalkDir::new(&config.doctest_dir()).into_iter();
            for dt in walker
                .filter_map(|e| e.ok())
                .filter(|e| match e.metadata() {
                    Ok(ref m) if m.is_file() && m.len() != 0 => true,
                    _ => false,
                })
            {
                trace!("Found doctest binary {}", dt.path().display());
                result.push(TestBinary::new(dt.path().to_path_buf(), *ty));
            }
        }
    }
    Ok(result)
}

fn create_command(manifest_path: &str, config: &Config, ty: &RunType) -> Command {
    let mut test_cmd = Command::new("cargo");
    if *ty == RunType::Doctests {
        if let Some(toolchain) = env::var("RUSTUP_TOOLCHAIN")
            .ok()
            .filter(|t| t.starts_with("nightly"))
        {
            test_cmd.args(&[format!("+{}", toolchain).as_str(), "test"]);
        } else {
            test_cmd.args(&["+nightly", "test"]);
        }
    } else {
        if let Ok(toolchain) = env::var("RUSTUP_TOOLCHAIN") {
            test_cmd.arg(format!("+{}", toolchain));
        }
        test_cmd.args(&["test", "--no-run"]);
    }
    test_cmd.args(&["--message-format", "json", "--manifest-path", manifest_path]);
    match ty {
        RunType::Tests => test_cmd.arg("--tests"),
        RunType::Doctests => test_cmd.arg("--doc"),
        RunType::Benchmarks => test_cmd.arg("--benches"),
        RunType::Examples => test_cmd.arg("--examples"),
    };
    init_args(&mut test_cmd, config);
    setup_environment(&mut test_cmd, config);
    test_cmd
}

fn init_args(test_cmd: &mut Command, config: &Config) {
    if config.debug {
        test_cmd.arg("-vvv");
    }
    if config.locked {
        test_cmd.arg("--locked");
    }
    if config.frozen {
        test_cmd.arg("--frozen");
    }
    if let Some(features) = config.features.as_ref() {
        test_cmd.arg("--features");
        test_cmd.arg(features);
    }
    if config.all_features {
        test_cmd.arg("--all-features");
    }
    if config.no_default_features {
        test_cmd.arg("--no-default-features");
    }
    if config.all {
        test_cmd.arg("--workspace");
    }
    if config.release {
        test_cmd.arg("--release");
    }
    config.packages.iter().for_each(|package| {
        test_cmd.arg("--package");
        test_cmd.arg(package);
    });
    config.exclude.iter().for_each(|package| {
        test_cmd.arg("--exclude");
        test_cmd.arg(package);
    });
    if let Some(target) = config.target.as_ref() {
        test_cmd.args(&["--target", target]);
    }
    let args = vec![
        "--target-dir".to_string(),
        format!("{}", config.target_dir().display()),
    ];
    test_cmd.args(args);
    if config.offline {
        test_cmd.arg("--offline");
    }
    for feat in &config.unstable_features {
        test_cmd.arg(format!("-Z{}", feat));
    }
    if !config.varargs.is_empty() {
        let mut args = vec!["--".to_string()];
        args.extend_from_slice(&config.varargs);
        test_cmd.args(args);
    }
}

fn setup_environment(cmd: &mut Command, config: &Config) {
    cmd.env("TARPAULIN", "1");
    let rustflags = "RUSTFLAGS";
    let common_opts = " -C relocation-model=dynamic-no-pic -C link-dead-code -C debuginfo=2 ";
    let mut value = common_opts.to_string();
    if config.release {
        value = format!("{}-C debug-assertions=off ", value);
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    cmd.env(rustflags, value);
    // doesn't matter if we don't use it
    let rustdoc = "RUSTDOCFLAGS";
    let mut value = format!(
        "{} --persist-doctests {} -Z unstable-options ",
        common_opts,
        config.doctest_dir().display()
    );
    if let Ok(vtemp) = env::var(rustdoc) {
        if !vtemp.contains("--persist-doctests") {
            value.push_str(vtemp.as_ref());
        }
    }
    trace!("Setting RUSTDOCFLAGS='{}'", value);
    cmd.env(rustdoc, value);
}
<commit_msg>pipe doctest command to stdio::null<commit_after>use crate::config::*;
use crate::errors::RunError;
use cargo_metadata::{diagnostic::DiagnosticLevel, CargoOpt, Message, MetadataCommand};
use log::{error, trace};
use std::env;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use walkdir::WalkDir;

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TestBinary {
    path: PathBuf,
    ty: RunType,
    cargo_dir: Option<PathBuf>,
    pkg_name: Option<String>,
    pkg_version: Option<String>,
    pkg_authors: Option<Vec<String>>,
    should_panic: bool,
}

impl TestBinary {
    pub fn new(path: PathBuf, ty: RunType) -> Self {
        Self {
            path,
            ty,
            pkg_name: None,
            pkg_version: None,
            pkg_authors: None,
            cargo_dir: None,
            should_panic: false,
        }
    }

    pub fn path(&self) -> &Path {
        &self.path
    }

    pub fn run_type(&self) -> RunType {
        self.ty
    }

    pub fn manifest_dir(&self) -> &Option<PathBuf> {
        &self.cargo_dir
    }

    pub fn pkg_name(&self) -> &Option<String> {
        &self.pkg_name
    }

    pub fn pkg_version(&self) -> &Option<String> {
        &self.pkg_version
    }

    pub fn pkg_authors(&self) -> &Option<Vec<String>> {
        &self.pkg_authors
    }

    /// Should be `false` for normal tests and for doctests either `true` or
    /// `false` depending on the test attribute
    pub fn should_panic(&self) -> bool {
        self.should_panic
    }
}

pub fn get_tests(config: &Config) -> Result<Vec<TestBinary>, RunError> {
    let mut result = vec![];
    let manifest = match config.manifest.as_path().to_str() {
        Some(s) => s,
        None => "Cargo.toml",
    };
    let metadata = MetadataCommand::new()
        .manifest_path(manifest)
        .features(CargoOpt::AllFeatures)
        .exec()
        .map_err(|e| RunError::Cargo(e.to_string()))?;

    for ty in &config.run_types {
        let mut cmd = create_command(manifest, config, ty);
        if ty != &RunType::Doctests {
            cmd.stdout(Stdio::piped());
        } else {
            cmd.stdout(Stdio::null());
        }
        if !config.verbose {
            cmd.stderr(Stdio::null());
        }
        trace!("Running command {:?}", cmd);
        let mut child = cmd.spawn().map_err(|e| RunError::Cargo(e.to_string()))?;

        if ty != &RunType::Doctests {
            let mut package_ids = vec![];
            let reader = std::io::BufReader::new(child.stdout.take().unwrap());
            for msg in Message::parse_stream(reader) {
                match msg {
                    Ok(Message::CompilerArtifact(art)) => {
                        if let Some(path) = art.executable {
                            if !art.profile.test && ty == &RunType::Tests {
                                continue;
                            }
                            result.push(TestBinary::new(path, *ty));
                            package_ids.push(art.package_id.clone());
                        }
                    }
                    Ok(Message::CompilerMessage(m)) => match m.message.level {
                        DiagnosticLevel::Error | DiagnosticLevel::Ice => {
                            let _ = child.wait();
                            return Err(RunError::TestCompile(m.message.message));
                        }
                        _ => {}
                    },
                    Err(e) => {
                        error!("Error parsing cargo messages {}", e);
                    }
                    _ => {}
                }
            }
            for (res, package) in result.iter_mut().zip(package_ids.iter()) {
                let package = &metadata[package];
                res.cargo_dir = package.manifest_path.parent().map(|x| x.to_path_buf());
                res.pkg_name = Some(package.name.clone());
                res.pkg_version = Some(package.version.to_string());
                res.pkg_authors = Some(package.authors.clone());
            }
            child.wait().map_err(|e| RunError::Cargo(e.to_string()))?;
        } else {
            // need to wait for compiling to finish before getting doctests
            // also need to wait with output to ensure the stdout buffer doesn't fill up
            let out = child
                .wait_with_output()
                .map_err(|e| RunError::Cargo(e.to_string()))?;
            if !out.status.success() {
                error!("Building doctests failed");
            }
            let walker = WalkDir::new(&config.doctest_dir()).into_iter();
            for dt in walker
                .filter_map(|e| e.ok())
                .filter(|e| match e.metadata() {
                    Ok(ref m) if m.is_file() && m.len() != 0 => true,
                    _ => false,
                })
            {
                trace!("Found doctest binary {}", dt.path().display());
                result.push(TestBinary::new(dt.path().to_path_buf(), *ty));
            }
        }
    }
    Ok(result)
}

fn create_command(manifest_path: &str, config: &Config, ty: &RunType) -> Command {
    let mut test_cmd = Command::new("cargo");
    if *ty == RunType::Doctests {
        if let Some(toolchain) = env::var("RUSTUP_TOOLCHAIN")
            .ok()
            .filter(|t| t.starts_with("nightly"))
        {
            test_cmd.args(&[format!("+{}", toolchain).as_str(), "test"]);
        } else {
            test_cmd.args(&["+nightly", "test"]);
        }
    } else {
        if let Ok(toolchain) = env::var("RUSTUP_TOOLCHAIN") {
            test_cmd.arg(format!("+{}", toolchain));
        }
        test_cmd.args(&["test", "--no-run"]);
    }
    test_cmd.args(&["--message-format", "json", "--manifest-path", manifest_path]);
    match ty {
        RunType::Tests => test_cmd.arg("--tests"),
        RunType::Doctests => test_cmd.arg("--doc"),
        RunType::Benchmarks => test_cmd.arg("--benches"),
        RunType::Examples => test_cmd.arg("--examples"),
    };
    init_args(&mut test_cmd, config);
    setup_environment(&mut test_cmd, config);
    test_cmd
}

fn init_args(test_cmd: &mut Command, config: &Config) {
    if config.debug {
        test_cmd.arg("-vvv");
    }
    if config.locked {
        test_cmd.arg("--locked");
    }
    if config.frozen {
        test_cmd.arg("--frozen");
    }
    if let Some(features) = config.features.as_ref() {
        test_cmd.arg("--features");
        test_cmd.arg(features);
    }
    if config.all_features {
        test_cmd.arg("--all-features");
    }
    if config.no_default_features {
        test_cmd.arg("--no-default-features");
    }
    if config.all {
        test_cmd.arg("--workspace");
    }
    if config.release {
        test_cmd.arg("--release");
    }
    config.packages.iter().for_each(|package| {
        test_cmd.arg("--package");
        test_cmd.arg(package);
    });
    config.exclude.iter().for_each(|package| {
        test_cmd.arg("--exclude");
        test_cmd.arg(package);
    });
    if let Some(target) = config.target.as_ref() {
        test_cmd.args(&["--target", target]);
    }
    let args = vec![
        "--target-dir".to_string(),
        format!("{}", config.target_dir().display()),
    ];
    test_cmd.args(args);
    if config.offline {
        test_cmd.arg("--offline");
    }
    for feat in &config.unstable_features {
        test_cmd.arg(format!("-Z{}", feat));
    }
    if !config.varargs.is_empty() {
        let mut args = vec!["--".to_string()];
        args.extend_from_slice(&config.varargs);
        test_cmd.args(args);
    }
}

fn setup_environment(cmd: &mut Command, config: &Config) {
    cmd.env("TARPAULIN", "1");
    let rustflags = "RUSTFLAGS";
    let common_opts = " -C relocation-model=dynamic-no-pic -C link-dead-code -C debuginfo=2 ";
    let mut value = common_opts.to_string();
    if config.release {
        value = format!("{}-C debug-assertions=off ", value);
    }
    if let Ok(vtemp) = env::var(rustflags) {
        value.push_str(vtemp.as_ref());
    }
    cmd.env(rustflags, value);
    // doesn't matter if we don't use it
    let rustdoc = "RUSTDOCFLAGS";
    let mut value = format!(
        "{} --persist-doctests {} -Z unstable-options ",
        common_opts,
        config.doctest_dir().display()
    );
    if let Ok(vtemp) = env::var(rustdoc) {
        if !vtemp.contains("--persist-doctests") {
            value.push_str(vtemp.as_ref());
        }
    }
    trace!("Setting RUSTDOCFLAGS='{}'", value);
    cmd.env(rustdoc, value);
}
<|endoftext|>


<commit_before>use keys::*;
use byteorder::{BigEndian, WriteBytesExt};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Color {
    pub red: u8,
    pub green: u8,
    pub blue: u8,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KeyColor {
    pub key: Key,
    pub color: Color,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ColorPacket {
    key_type: Option<KeyType>,
    colors: Vec<KeyColor>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FlushPacket {
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum KeyColorError {
    PacketFull,
    InvalidKeyType,
}

impl Color {
    pub fn new(red: u8, green: u8, blue: u8) -> Color {
        Color {
            red: red,
            green: green,
            blue: blue,
        }
    }
}

impl KeyColor {
    pub fn new<T: Into<Key>>(key: T, color: Color) -> KeyColor {
        KeyColor {
            key: key.into(),
            color: color,
        }
    }
}

impl ColorPacket {
    pub fn new() -> ColorPacket {
        ColorPacket {
            key_type: None,
            colors: Vec::new(),
        }
    }

    /// Adds a color to this packet
    ///
    /// If this packet is alredy full, Err will be returned.
    pub fn add_key_color(&mut self, key_color: KeyColor) -> Result<(), KeyColorError> {
        match self.key_type {
            None => self.key_type = Some((&key_color.key).into()),
            Some(key_code) if key_code != (&key_color.key).into() =>
                return Err(KeyColorError::InvalidKeyType),
            _ => {}
        }

        if self.colors.len() >= 14 {
            Err(KeyColorError::PacketFull)
        } else {
            self.colors.push(key_color);
            Ok(())
        }
    }

    /// Returns the number of Colors in this packet
    pub fn len(&self) -> usize {
        self.colors.len()
    }

    /// Wrapper for ColorPacket::into::<[u8; 64]>()
    pub fn to_arr(self) -> [u8; 64] {
        self.into()
    }
}

impl From<ColorPacket> for [u8; 64] {
    fn from(color_packet: ColorPacket) -> [u8; 64] {
        let mut arr = [0u8; 64];
        // head
        (&mut arr[0..4]).write_u32::<BigEndian>(0x12ff0f3b).unwrap();
        // key type
        // if none is specified, no data exists and no key will be set
        // as From can not return a Result, just use any key type
        (&mut arr[4..6]).write_u16::<BigEndian>(color_packet.key_type.unwrap_or(KeyType::Standard) as u16).unwrap();
        // reserved
        arr[6] = 0x00;
        // number of key colors
        arr[7] = color_packet.colors.len() as u8;
        // key colors
        for (key_col, buf) in color_packet.colors.iter().zip((&mut arr[8..64]).chunks_mut(4)) {
            buf[0] = key_col.key.clone().into();
            buf[1] = key_col.color.red;
            buf[2] = key_col.color.green;
            buf[3] = key_col.color.blue;
        }
        arr
    }
}

impl FlushPacket {
    pub fn new() -> FlushPacket {
        FlushPacket {  }
    }

    pub fn to_arr(self) -> [u8; 20] {
        self.into()
    }
}

impl From<FlushPacket> for [u8; 20] {
    #[allow(unused_variables)]
    fn from(p: FlushPacket) -> [u8; 20] {
        let mut arr = [0u8; 20];
        // head
        (&mut arr[0..4]).write_u32::<BigEndian>(0x11ff0f5b).unwrap();
        // body is 0
        arr
    }
}

<commit_msg>fix(color): Return `KeyColor` from `ColorPacket::add_key_color` if the packet is full<commit_after>use keys::*;
use byteorder::{BigEndian, WriteBytesExt};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Color {
    pub red: u8,
    pub green: u8,
    pub blue: u8,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct KeyColor {
    pub key: Key,
    pub color: Color,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ColorPacket {
    key_type: Option<KeyType>,
    colors: Vec<KeyColor>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FlushPacket {
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum KeyColorError {
    PacketFull(KeyColor),
    InvalidKeyType,
}

impl Color {
    pub fn new(red: u8, green: u8, blue: u8) -> Color {
        Color {
            red: red,
            green: green,
            blue: blue,
        }
    }
}

impl KeyColor {
    pub fn new<T: Into<Key>>(key: T, color: Color) -> KeyColor {
        KeyColor {
            key: key.into(),
            color: color,
        }
    }
}

impl ColorPacket {
    pub fn new() -> ColorPacket {
        ColorPacket {
            key_type: None,
            colors: Vec::new(),
        }
    }

    /// Adds a color to this packet
    ///
    /// If this packet is alredy full, Err will be returned.
    pub fn add_key_color(&mut self, key_color: KeyColor) -> Result<(), KeyColorError> {
        match self.key_type {
            None => self.key_type = Some((&key_color.key).into()),
            Some(key_code) if key_code != (&key_color.key).into() =>
                return Err(KeyColorError::InvalidKeyType),
            _ => {}
        }

        if self.colors.len() >= 14 {
            Err(KeyColorError::PacketFull(key_color))
        } else {
            self.colors.push(key_color);
            Ok(())
        }
    }

    /// Returns the number of Colors in this packet
    pub fn len(&self) -> usize {
        self.colors.len()
    }

    /// Wrapper for ColorPacket::into::<[u8; 64]>()
    pub fn to_arr(self) -> [u8; 64] {
        self.into()
    }
}

impl From<ColorPacket> for [u8; 64] {
    fn from(color_packet: ColorPacket) -> [u8; 64] {
        let mut arr = [0u8; 64];
        // head
        (&mut arr[0..4]).write_u32::<BigEndian>(0x12ff0f3b).unwrap();
        // key type
        // if none is specified, no data exists and no key will be set
        // as From can not return a Result, just use any key type
        (&mut arr[4..6]).write_u16::<BigEndian>(color_packet.key_type.unwrap_or(KeyType::Standard) as u16).unwrap();
        // reserved
        arr[6] = 0x00;
        // number of key colors
        arr[7] = color_packet.colors.len() as u8;
        // key colors
        for (key_col, buf) in color_packet.colors.iter().zip((&mut arr[8..64]).chunks_mut(4)) {
            buf[0] = key_col.key.clone().into();
            buf[1] = key_col.color.red;
            buf[2] = key_col.color.green;
            buf[3] = key_col.color.blue;
        }
        arr
    }
}

impl FlushPacket {
    pub fn new() -> FlushPacket {
        FlushPacket {  }
    }

    pub fn to_arr(self) -> [u8; 20] {
        self.into()
    }
}

impl From<FlushPacket> for [u8; 20] {
    #[allow(unused_variables)]
    fn from(p: FlushPacket) -> [u8; 20] {
        let mut arr = [0u8; 20];
        // head
        (&mut arr[0..4]).write_u32::<BigEndian>(0x11ff0f5b).unwrap();
        // body is 0
        arr
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 ZFilexfer Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use czmq;
use rustc_serialize::json;
use std::{convert, error, fmt, io, result, str};
use zdaemon;

pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    ChunkFail,
    ChunkIndex,
    Czmq(czmq::Error),
    FileFail,
    InvalidFileOpts,
    InvalidFilePath,
    InvalidReply,
    InvalidRequest,
    Io(io::Error),
    JsonEncoder(json::EncoderError),
    JsonDecoder(json::DecoderError),
    ModeRecv,
    ModeSend,
    UploadError(String),
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::ChunkFail => write!(f, "Failed to save chunk to file"),
            Error::ChunkIndex => write!(f, "Chunk index not in file"),
            Error::Czmq(ref e) => write!(f, "CZMQ error: {}", e),
            Error::FileFail => write!(f, "Failed to upload file"),
            Error::InvalidFileOpts => write!(f, "Invalid file options"),
            Error::InvalidFilePath => write!(f, "Path does not exist or is not a file"),
            Error::InvalidReply => write!(f, "Invalid reply"),
            Error::InvalidRequest => write!(f, "Invalid request"),
            Error::Io(ref e) => write!(f, "IO error: {}", e),
            Error::JsonEncoder(ref e) => write!(f, "JSON encoder error: {}", e),
            Error::JsonDecoder(ref e) => write!(f, "JSON decoder error: {}", e),
            Error::ModeRecv => write!(f, "Struct is in wrong mode for receiving"),
            Error::ModeSend => write!(f, "Struct is in wrong mode for sending"),
            Error::UploadError(ref e) => write!(f, "Could not upload file: {}", e),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ChunkFail => "Failed to save chunk to file",
            Error::ChunkIndex => "Chunk index not in file",
            Error::Czmq(ref e) => e.description(),
            Error::FileFail => "Failed to upload file",
            Error::InvalidFileOpts => "Invalid file options",
            Error::InvalidFilePath => "Path does not exist or is not a file",
            Error::InvalidReply => "Invalid reply",
            Error::InvalidRequest => "Invalid request",
            Error::Io(ref e) => e.description(),
            Error::JsonEncoder(ref e) => e.description(),
            Error::JsonDecoder(ref e) => e.description(),
            Error::ModeRecv => "Struct is in wrong mode for receiving",
            Error::ModeSend => "Struct is in wrong mode for sending",
            Error::UploadError(ref e) => e,
        }
    }
}

impl convert::From<czmq::Error> for Error {
    fn from(err: czmq::Error) -> Error {
        Error::Czmq(err)
    }
}

impl convert::From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl convert::From<json::EncoderError> for Error {
    fn from(err: json::EncoderError) -> Error {
        Error::JsonEncoder(err)
    }
}

impl convert::From<json::DecoderError> for Error {
    fn from(err: json::DecoderError) -> Error {
        Error::JsonDecoder(err)
    }
}

impl convert::Into<zdaemon::Error> for Error {
    fn into(self) -> zdaemon::Error {
        zdaemon::Error::Generic(Box::new(self))
    }
}
<commit_msg>Error tests for code coverage<commit_after>// Copyright 2016 ZFilexfer Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use czmq;
use rustc_serialize::json;
use std::{convert, error, fmt, io, result, str};
use zdaemon;

pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum Error {
    ChunkFail,
    ChunkIndex,
    Czmq(czmq::Error),
    FileFail,
    InvalidFileOpts,
    InvalidFilePath,
    InvalidReply,
    InvalidRequest,
    Io(io::Error),
    JsonEncoder(json::EncoderError),
    JsonDecoder(json::DecoderError),
    ModeRecv,
    ModeSend,
    UploadError(String),
}

unsafe impl Send for Error {}
unsafe impl Sync for Error {}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::ChunkFail => write!(f, "Failed to save chunk to file"),
            Error::ChunkIndex => write!(f, "Chunk index not in file"),
            Error::Czmq(ref e) => write!(f, "CZMQ error: {}", e),
            Error::FileFail => write!(f, "Failed to upload file"),
            Error::InvalidFileOpts => write!(f, "Invalid file options"),
            Error::InvalidFilePath => write!(f, "Path does not exist or is not a file"),
            Error::InvalidReply => write!(f, "Invalid reply"),
            Error::InvalidRequest => write!(f, "Invalid request"),
            Error::Io(ref e) => write!(f, "IO error: {}", e),
            Error::JsonEncoder(ref e) => write!(f, "JSON encoder error: {}", e),
            Error::JsonDecoder(ref e) => write!(f, "JSON decoder error: {}", e),
            Error::ModeRecv => write!(f, "Struct is in wrong mode for receiving"),
            Error::ModeSend => write!(f, "Struct is in wrong mode for sending"),
            Error::UploadError(ref e) => write!(f, "Could not upload file: {}", e),
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::ChunkFail => "Failed to save chunk to file",
            Error::ChunkIndex => "Chunk index not in file",
            Error::Czmq(ref e) => e.description(),
            Error::FileFail => "Failed to upload file",
            Error::InvalidFileOpts => "Invalid file options",
            Error::InvalidFilePath => "Path does not exist or is not a file",
            Error::InvalidReply => "Invalid reply",
            Error::InvalidRequest => "Invalid request",
            Error::Io(ref e) => e.description(),
            Error::JsonEncoder(ref e) => e.description(),
            Error::JsonDecoder(ref e) => e.description(),
            Error::ModeRecv => "Struct is in wrong mode for receiving",
            Error::ModeSend => "Struct is in wrong mode for sending",
            Error::UploadError(ref e) => e,
        }
    }
}

impl convert::From<czmq::Error> for Error {
    fn from(err: czmq::Error) -> Error {
        Error::Czmq(err)
    }
}

impl convert::From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

impl convert::From<json::EncoderError> for Error {
    fn from(err: json::EncoderError) -> Error {
        Error::JsonEncoder(err)
    }
}

impl convert::From<json::DecoderError> for Error {
    fn from(err: json::DecoderError) -> Error {
        Error::JsonDecoder(err)
    }
}

impl convert::Into<zdaemon::Error> for Error {
    fn into(self) -> zdaemon::Error {
        zdaemon::Error::Generic(Box::new(self))
    }
}

#[cfg(test)]
mod tests {
    use czmq::{ZSock, ZSockType, ZSys};
    use rustc_serialize::json::{DecoderError, EncoderError};
    use std::fs::metadata;
    use super::*;
    use zdaemon;

    #[test]
    fn test_convert_czmq() {
        ZSys::init();

        let sock = ZSock::new(ZSockType::REQ);
        let e = sock.recv_str().unwrap_err();
        Error::from(e);
    }

    #[test]
    fn test_convert_io() {
        if let Err(e) = metadata("/fake/path") {
            Error::from(e);
        } else {
            unreachable!();
        }
    }

    #[test]
    fn test_convert_json_encode() {
        let e = EncoderError::BadHashmapKey;
        Error::from(e);
    }

    #[test]
    fn test_convert_json_decode() {
        let e = DecoderError::EOF;
        Error::from(e);
    }

    #[test]
    fn test_convert_zdaemon() {
        let e = Error::ChunkFail;
        let _: zdaemon::Error = e.into();
    }
}
<|endoftext|>


<commit_before>use curl::Error as CurlError;

#[derive(Debug)]
pub enum TealdeerError {
    CacheError(String),
    ConfigError(String),
    UpdateError(String),
}

impl From<CurlError> for TealdeerError {
    fn from(err: CurlError) -> TealdeerError {
        TealdeerError::UpdateError(format!("Curl error: {}", err.to_string()))
    }
}
<commit_msg>Impl Display for TealdeerError<commit_after>use std::fmt;
use curl::Error as CurlError;

#[derive(Debug)]
pub enum TealdeerError {
    CacheError(String),
    ConfigError(String),
    UpdateError(String),
}

impl From<CurlError> for TealdeerError {
    fn from(err: CurlError) -> TealdeerError {
        TealdeerError::UpdateError(format!("Curl error: {}", err.to_string()))
    }
}

impl fmt::Display for TealdeerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            TealdeerError::CacheError(e) => write!(f, "CacheError: {}", e),
            TealdeerError::ConfigError(e) => write!(f, "ConfigError: {}", e),
            TealdeerError::UpdateError(e) => write!(f, "UpdateError: {}", e),
        }
    }
}
<|endoftext|>


<commit_before>//! Error types.

use std::error;
use std::fmt;

use cssparser::{BasicParseError, BasicParseErrorKind, ParseErrorKind, ToCss};
use markup5ever::QualName;

use crate::node::Node;
use crate::url_resolver::Fragment;

/// A short-lived error.
///
/// The lifetime of the error is the same as the `cssparser::ParserInput` that
/// was used to create a `cssparser::Parser`.  That is, it is the lifetime of
/// the string data that is being parsed.
///
/// The code flow will sometimes require preserving this error as a long-lived struct;
/// see the `impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>>` for that
/// purpose.
pub type ParseError<'i> = cssparser::ParseError<'i, ValueErrorKind>;

/// A simple error which refers to an attribute's value
#[derive(Debug, Clone, PartialEq)]
pub enum ValueErrorKind {
    /// A property with the specified name was not found
    UnknownProperty,

    /// The value could not be parsed
    Parse(String),

    // The value could be parsed, but is invalid
    Value(String),
}

impl ValueErrorKind {
    pub fn parse_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Parse(s.to_string())
    }

    pub fn value_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Value(s.to_string())
    }
}

impl fmt::Display for ValueErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ValueErrorKind::UnknownProperty => write!(f, "unknown property name"),

            ValueErrorKind::Parse(ref s) => write!(f, "parse error: {}", s),

            ValueErrorKind::Value(ref s) => write!(f, "invalid value: {}", s),
        }
    }
}

impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
    fn from(e: BasicParseError<'_>) -> ValueErrorKind {
        let BasicParseError { kind, .. } = e;

        let msg = match kind {
            BasicParseErrorKind::UnexpectedToken(_) => "unexpected token",
            BasicParseErrorKind::EndOfInput => "unexpected end of input",
            BasicParseErrorKind::AtRuleInvalid(_) => "invalid @-rule",
            BasicParseErrorKind::AtRuleBodyInvalid => "invalid @-rule body",
            BasicParseErrorKind::QualifiedRuleInvalid => "invalid qualified rule",
        };

        ValueErrorKind::parse_error(msg)
    }
}

/// A complete error for an attribute and its erroneous value
#[derive(Debug, Clone, PartialEq)]
pub struct ElementError {
    pub attr: QualName,
    pub err: ValueErrorKind,
}

impl error::Error for ElementError {
    fn description(&self) -> &str {
        match self.err {
            ValueErrorKind::UnknownProperty => "unknown property",
            ValueErrorKind::Parse(_) => "parse error",
            ValueErrorKind::Value(_) => "invalid attribute value",
        }
    }
}

impl fmt::Display for ElementError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}: {}", self.attr.expanded(), self.err)
    }
}

/// Errors returned when looking up a resource by URL reference.
#[derive(Debug, Clone, PartialEq)]
pub enum DefsLookupErrorKind {
    /// Error when parsing an [`Href`].
    ///
    /// [`Href`]: allowed_url/enum.Href.html
    HrefError(HrefError),

    /// Used when the public API tries to look up an external URL, which is not allowed.
    ///
    /// This catches the case where a public API wants to be misused to access an external
    /// resource.  For example, `SvgHandle.has_sub("https://evil.com/phone_home#element_id") will
    /// fail with this error.
    CannotLookupExternalReferences,

    /// For internal use only.
    ///
    // FIXME: this is returned internally from Handle.lookup_node(), and gets translated
    // to Ok(false).  Don't expose this internal code in the public API.
    NotFound,
}

/// Errors that can happen while rendering or measuring an SVG document.
#[derive(Debug, Clone, PartialEq)]
pub enum RenderingError {
    /// A Cairo error happened during rendering.
    Cairo(cairo::Status),

    /// A particular implementation-defined limit was exceeded.
    LimitExceeded(String),

    /// Tried to reference an SVG element from a fragment identifier that is incorrect.
    InvalidId(DefsLookupErrorKind),

    /// Not enough memory was available for rendering.
    // FIXME: right now this is only returned from pixbuf_utils.rs
    OutOfMemory,

    /// Cannot occur from librsvg_crate; this is just for the C API.
    HandleIsNotLoaded,
}

impl error::Error for RenderingError {}

impl fmt::Display for RenderingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            RenderingError::LimitExceeded(ref s) => write!(f, "limit exceeded: {}", s),
            RenderingError::OutOfMemory => write!(f, "out of memory"),
            RenderingError::HandleIsNotLoaded => write!(f, "SVG data is not loaded into handle"),
            RenderingError::Cairo(ref status) => write!(f, "cairo error: {:?}", status),
            RenderingError::InvalidId(ref id) => write!(f, "invalid id: {:?}", id),
        }
    }
}

impl From<cairo::Status> for RenderingError {
    fn from(e: cairo::Status) -> RenderingError {
        assert!(e != cairo::Status::Success);

        RenderingError::Cairo(e)
    }
}

pub enum AcquireError {
    LinkNotFound(Fragment),
    InvalidLinkType(Fragment),
    CircularReference(Node),
    MaxReferencesExceeded,
}

impl fmt::Display for AcquireError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            AcquireError::LinkNotFound(ref frag) => write!(f, "link not found: {}", frag),

            AcquireError::InvalidLinkType(ref frag) => {
                write!(f, "link {} is to object of invalid type", frag)
            }

            AcquireError::CircularReference(ref node) => {
                write!(f, "circular reference in node {}", node)
            }

            AcquireError::MaxReferencesExceeded => {
                write!(f, "maximum number of references exceeded")
            }
        }
    }
}

/// Helper for converting `Result<O, E>` into `Result<O, ElementError>`
///
/// A `ElementError` requires a `QualName` that corresponds to the attribute to which the
/// error refers, plus the actual `ValueErrorKind` that describes the error.  However,
/// parsing functions for attribute value types will want to return their own kind of
/// error, instead of `ValueErrorKind`.  If that particular error type has an `impl
/// From<FooError> for ValueErrorKind`, then this trait helps assign attribute values in
/// `set_atts()` methods as follows:
///
/// ```
/// # use librsvg::doctest_only::AttributeResultExt;
/// # use librsvg::doctest_only::ValueErrorKind;
/// # use librsvg::doctest_only::ElementError;
/// # use markup5ever::{QualName, Prefix, Namespace, LocalName};
/// # type FooError = ValueErrorKind;
/// fn parse_foo(value: &str) -> Result<(), FooError>
/// # { Err(ValueErrorKind::value_error("test")) }
///
/// // It is assumed that there is an impl From<FooError> for ValueErrorKind
/// # let attr = QualName::new(
/// #     Some(Prefix::from("")),
/// #     Namespace::from(""),
/// #     LocalName::from(""),
/// # );
/// let result = parse_foo("value").attribute(attr);
/// assert!(result.is_err());
/// # Ok::<(), ElementError>(())
/// ```
///
/// The call to `.attribute(attr)` converts the `Result` from `parse_foo()` into a full
/// `ElementError` with the provided `attr`.
pub trait AttributeResultExt<O> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError>;
}

impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O> for Result<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| e.into())
            .map_err(|err| ElementError { attr, err })
    }
}

/// Turns a short-lived `ParseError` into a long-lived `ElementError`
impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| {
            // FIXME: eventually, here we'll want to preserve the location information

            let ParseError {
                kind,
                location: _location,
            } = e;

            match kind {
                ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(tok)) => {
                    let mut s = String::from("unexpected token '");
                    tok.to_css(&mut s).unwrap(); // FIXME: what do we do with a fmt::Error?
                    s.push_str("'");

                    ElementError {
                        attr,
                        err: ValueErrorKind::Parse(s),
                    }
                }

                ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => ElementError {
                    attr,
                    err: ValueErrorKind::parse_error("unexpected end of input"),
                },

                ParseErrorKind::Basic(_) => {
                    unreachable!("attribute parsers should not return errors for CSS rules")
                }

                ParseErrorKind::Custom(err) => ElementError { attr, err },
            }
        })
    }
}

/// Errors returned when creating an `Href` out of a string
#[derive(Debug, Clone, PartialEq)]
pub enum HrefError {
    /// The href is an invalid URI or has empty components.
    ParseError,

    /// A fragment identifier ("`#foo`") is not allowed here
    ///
    /// For example, the SVG `<image>` element only allows referencing
    /// resources without fragment identifiers like
    /// `xlink:href="foo.png"`.
    FragmentForbidden,

    /// A fragment identifier ("`#foo`") was required but not found.  For example,
    /// the SVG `<use>` element requires one, as in `<use xlink:href="foo.svg#bar">`.
    FragmentRequired,
}

impl From<HrefError> for ValueErrorKind {
    fn from(e: HrefError) -> ValueErrorKind {
        match e {
            HrefError::ParseError => ValueErrorKind::parse_error("url parse error"),
            HrefError::FragmentForbidden => {
                ValueErrorKind::value_error("fragment identifier not allowed")
            }
            HrefError::FragmentRequired => {
                ValueErrorKind::value_error("fragment identifier required")
            }
        }
    }
}

/// Errors that can happen while loading an SVG document.
///
/// All of these codes are for unrecoverable errors that keep an SVG document from being
/// fully loaded and parsed.  Note that SVG is very lenient with respect to document
/// structure and the syntax of CSS property values; most errors there will not lead to a
/// `LoadingError`.  To see those errors, you may want to set the `RSVG_LOG=1` environment
/// variable.
///
/// I/O errors get reported in the `Glib` variant, since librsvg uses GIO internally for
/// all input/output.
#[derive(Debug, Clone)]
pub enum LoadingError {
    /// XML syntax error.
    XmlParseError(String),

    /// Not enough memory to load the document.
    OutOfMemory(String),

    /// A malformed or disallowed URL was used.
    BadUrl,

    /// A `data:` URL could not be decoded.
    BadDataUrl,

    // FIXME: used only if XML processing instruction cannot find the stylesheet.
    BadStylesheet,

    /// An invalid stylesheet was used.
    BadCss,

    // FIXME: only used in load_image()
    EmptyData,

    /// There is no `<svg>` root element in the XML.
    NoSvgRoot,

    /// Generally an I/O error, or another error from GIO.
    Glib(glib::Error),

    /// A particular implementation-defined limit was exceeded.
    LimitExceeded(String),

    /// Catch-all for loading errors.
    Other(String),
}

impl error::Error for LoadingError {}

impl fmt::Display for LoadingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            LoadingError::XmlParseError(ref s) => write!(f, "XML parse error: {}", s),
            LoadingError::OutOfMemory(ref s) => write!(f, "out of memory: {}", s),
            LoadingError::BadUrl => write!(f, "invalid URL"),
            LoadingError::BadDataUrl => write!(f, "invalid data: URL"),
            LoadingError::BadStylesheet => write!(f, "invalid stylesheet"),
            LoadingError::BadCss => write!(f, "invalid CSS"),
            LoadingError::EmptyData => write!(f, "empty data"),
            LoadingError::NoSvgRoot => write!(f, "XML does not have <svg> root"),
            LoadingError::Glib(ref e) => e.fmt(f),
            LoadingError::LimitExceeded(ref s) => write!(f, "limit exceeded: {}", s),
            LoadingError::Other(ref s) => write!(f, "{}", s),
        }
    }
}

impl From<glib::Error> for LoadingError {
    fn from(e: glib::Error) -> LoadingError {
        LoadingError::Glib(e)
    }
}
<commit_msg>Make LoadingError and RenderingError non_exhaustive<commit_after>//! Error types.

use std::error;
use std::fmt;

use cssparser::{BasicParseError, BasicParseErrorKind, ParseErrorKind, ToCss};
use markup5ever::QualName;

use crate::node::Node;
use crate::url_resolver::Fragment;

/// A short-lived error.
///
/// The lifetime of the error is the same as the `cssparser::ParserInput` that
/// was used to create a `cssparser::Parser`.  That is, it is the lifetime of
/// the string data that is being parsed.
///
/// The code flow will sometimes require preserving this error as a long-lived struct;
/// see the `impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>>` for that
/// purpose.
pub type ParseError<'i> = cssparser::ParseError<'i, ValueErrorKind>;

/// A simple error which refers to an attribute's value
#[derive(Debug, Clone, PartialEq)]
pub enum ValueErrorKind {
    /// A property with the specified name was not found
    UnknownProperty,

    /// The value could not be parsed
    Parse(String),

    // The value could be parsed, but is invalid
    Value(String),
}

impl ValueErrorKind {
    pub fn parse_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Parse(s.to_string())
    }

    pub fn value_error(s: &str) -> ValueErrorKind {
        ValueErrorKind::Value(s.to_string())
    }
}

impl fmt::Display for ValueErrorKind {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ValueErrorKind::UnknownProperty => write!(f, "unknown property name"),

            ValueErrorKind::Parse(ref s) => write!(f, "parse error: {}", s),

            ValueErrorKind::Value(ref s) => write!(f, "invalid value: {}", s),
        }
    }
}

impl<'a> From<BasicParseError<'a>> for ValueErrorKind {
    fn from(e: BasicParseError<'_>) -> ValueErrorKind {
        let BasicParseError { kind, .. } = e;

        let msg = match kind {
            BasicParseErrorKind::UnexpectedToken(_) => "unexpected token",
            BasicParseErrorKind::EndOfInput => "unexpected end of input",
            BasicParseErrorKind::AtRuleInvalid(_) => "invalid @-rule",
            BasicParseErrorKind::AtRuleBodyInvalid => "invalid @-rule body",
            BasicParseErrorKind::QualifiedRuleInvalid => "invalid qualified rule",
        };

        ValueErrorKind::parse_error(msg)
    }
}

/// A complete error for an attribute and its erroneous value
#[derive(Debug, Clone, PartialEq)]
pub struct ElementError {
    pub attr: QualName,
    pub err: ValueErrorKind,
}

impl error::Error for ElementError {
    fn description(&self) -> &str {
        match self.err {
            ValueErrorKind::UnknownProperty => "unknown property",
            ValueErrorKind::Parse(_) => "parse error",
            ValueErrorKind::Value(_) => "invalid attribute value",
        }
    }
}

impl fmt::Display for ElementError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:?}: {}", self.attr.expanded(), self.err)
    }
}

/// Errors returned when looking up a resource by URL reference.
#[derive(Debug, Clone, PartialEq)]
pub enum DefsLookupErrorKind {
    /// Error when parsing an [`Href`].
    ///
    /// [`Href`]: allowed_url/enum.Href.html
    HrefError(HrefError),

    /// Used when the public API tries to look up an external URL, which is not allowed.
    ///
    /// This catches the case where a public API wants to be misused to access an external
    /// resource.  For example, `SvgHandle.has_sub("https://evil.com/phone_home#element_id") will
    /// fail with this error.
    CannotLookupExternalReferences,

    /// For internal use only.
    ///
    // FIXME: this is returned internally from Handle.lookup_node(), and gets translated
    // to Ok(false).  Don't expose this internal code in the public API.
    NotFound,
}

/// Errors that can happen while rendering or measuring an SVG document.
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum RenderingError {
    /// A Cairo error happened during rendering.
    Cairo(cairo::Status),

    /// A particular implementation-defined limit was exceeded.
    LimitExceeded(String),

    /// Tried to reference an SVG element from a fragment identifier that is incorrect.
    InvalidId(DefsLookupErrorKind),

    /// Not enough memory was available for rendering.
    // FIXME: right now this is only returned from pixbuf_utils.rs
    OutOfMemory,

    /// Cannot occur from librsvg_crate; this is just for the C API.
    HandleIsNotLoaded,
}

impl error::Error for RenderingError {}

impl fmt::Display for RenderingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            RenderingError::LimitExceeded(ref s) => write!(f, "limit exceeded: {}", s),
            RenderingError::OutOfMemory => write!(f, "out of memory"),
            RenderingError::HandleIsNotLoaded => write!(f, "SVG data is not loaded into handle"),
            RenderingError::Cairo(ref status) => write!(f, "cairo error: {:?}", status),
            RenderingError::InvalidId(ref id) => write!(f, "invalid id: {:?}", id),
        }
    }
}

impl From<cairo::Status> for RenderingError {
    fn from(e: cairo::Status) -> RenderingError {
        assert!(e != cairo::Status::Success);

        RenderingError::Cairo(e)
    }
}

pub enum AcquireError {
    LinkNotFound(Fragment),
    InvalidLinkType(Fragment),
    CircularReference(Node),
    MaxReferencesExceeded,
}

impl fmt::Display for AcquireError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            AcquireError::LinkNotFound(ref frag) => write!(f, "link not found: {}", frag),

            AcquireError::InvalidLinkType(ref frag) => {
                write!(f, "link {} is to object of invalid type", frag)
            }

            AcquireError::CircularReference(ref node) => {
                write!(f, "circular reference in node {}", node)
            }

            AcquireError::MaxReferencesExceeded => {
                write!(f, "maximum number of references exceeded")
            }
        }
    }
}

/// Helper for converting `Result<O, E>` into `Result<O, ElementError>`
///
/// A `ElementError` requires a `QualName` that corresponds to the attribute to which the
/// error refers, plus the actual `ValueErrorKind` that describes the error.  However,
/// parsing functions for attribute value types will want to return their own kind of
/// error, instead of `ValueErrorKind`.  If that particular error type has an `impl
/// From<FooError> for ValueErrorKind`, then this trait helps assign attribute values in
/// `set_atts()` methods as follows:
///
/// ```
/// # use librsvg::doctest_only::AttributeResultExt;
/// # use librsvg::doctest_only::ValueErrorKind;
/// # use librsvg::doctest_only::ElementError;
/// # use markup5ever::{QualName, Prefix, Namespace, LocalName};
/// # type FooError = ValueErrorKind;
/// fn parse_foo(value: &str) -> Result<(), FooError>
/// # { Err(ValueErrorKind::value_error("test")) }
///
/// // It is assumed that there is an impl From<FooError> for ValueErrorKind
/// # let attr = QualName::new(
/// #     Some(Prefix::from("")),
/// #     Namespace::from(""),
/// #     LocalName::from(""),
/// # );
/// let result = parse_foo("value").attribute(attr);
/// assert!(result.is_err());
/// # Ok::<(), ElementError>(())
/// ```
///
/// The call to `.attribute(attr)` converts the `Result` from `parse_foo()` into a full
/// `ElementError` with the provided `attr`.
pub trait AttributeResultExt<O> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError>;
}

impl<O, E: Into<ValueErrorKind>> AttributeResultExt<O> for Result<O, E> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| e.into())
            .map_err(|err| ElementError { attr, err })
    }
}

/// Turns a short-lived `ParseError` into a long-lived `ElementError`
impl<'i, O> AttributeResultExt<O> for Result<O, ParseError<'i>> {
    fn attribute(self, attr: QualName) -> Result<O, ElementError> {
        self.map_err(|e| {
            // FIXME: eventually, here we'll want to preserve the location information

            let ParseError {
                kind,
                location: _location,
            } = e;

            match kind {
                ParseErrorKind::Basic(BasicParseErrorKind::UnexpectedToken(tok)) => {
                    let mut s = String::from("unexpected token '");
                    tok.to_css(&mut s).unwrap(); // FIXME: what do we do with a fmt::Error?
                    s.push_str("'");

                    ElementError {
                        attr,
                        err: ValueErrorKind::Parse(s),
                    }
                }

                ParseErrorKind::Basic(BasicParseErrorKind::EndOfInput) => ElementError {
                    attr,
                    err: ValueErrorKind::parse_error("unexpected end of input"),
                },

                ParseErrorKind::Basic(_) => {
                    unreachable!("attribute parsers should not return errors for CSS rules")
                }

                ParseErrorKind::Custom(err) => ElementError { attr, err },
            }
        })
    }
}

/// Errors returned when creating an `Href` out of a string
#[derive(Debug, Clone, PartialEq)]
pub enum HrefError {
    /// The href is an invalid URI or has empty components.
    ParseError,

    /// A fragment identifier ("`#foo`") is not allowed here
    ///
    /// For example, the SVG `<image>` element only allows referencing
    /// resources without fragment identifiers like
    /// `xlink:href="foo.png"`.
    FragmentForbidden,

    /// A fragment identifier ("`#foo`") was required but not found.  For example,
    /// the SVG `<use>` element requires one, as in `<use xlink:href="foo.svg#bar">`.
    FragmentRequired,
}

impl From<HrefError> for ValueErrorKind {
    fn from(e: HrefError) -> ValueErrorKind {
        match e {
            HrefError::ParseError => ValueErrorKind::parse_error("url parse error"),
            HrefError::FragmentForbidden => {
                ValueErrorKind::value_error("fragment identifier not allowed")
            }
            HrefError::FragmentRequired => {
                ValueErrorKind::value_error("fragment identifier required")
            }
        }
    }
}

/// Errors that can happen while loading an SVG document.
///
/// All of these codes are for unrecoverable errors that keep an SVG document from being
/// fully loaded and parsed.  Note that SVG is very lenient with respect to document
/// structure and the syntax of CSS property values; most errors there will not lead to a
/// `LoadingError`.  To see those errors, you may want to set the `RSVG_LOG=1` environment
/// variable.
///
/// I/O errors get reported in the `Glib` variant, since librsvg uses GIO internally for
/// all input/output.
#[non_exhaustive]
#[derive(Debug, Clone)]
pub enum LoadingError {
    /// XML syntax error.
    XmlParseError(String),

    /// Not enough memory to load the document.
    OutOfMemory(String),

    /// A malformed or disallowed URL was used.
    BadUrl,

    /// A `data:` URL could not be decoded.
    BadDataUrl,

    // FIXME: used only if XML processing instruction cannot find the stylesheet.
    BadStylesheet,

    /// An invalid stylesheet was used.
    BadCss,

    // FIXME: only used in load_image()
    EmptyData,

    /// There is no `<svg>` root element in the XML.
    NoSvgRoot,

    /// Generally an I/O error, or another error from GIO.
    Glib(glib::Error),

    /// A particular implementation-defined limit was exceeded.
    LimitExceeded(String),

    /// Catch-all for loading errors.
    Other(String),
}

impl error::Error for LoadingError {}

impl fmt::Display for LoadingError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            LoadingError::XmlParseError(ref s) => write!(f, "XML parse error: {}", s),
            LoadingError::OutOfMemory(ref s) => write!(f, "out of memory: {}", s),
            LoadingError::BadUrl => write!(f, "invalid URL"),
            LoadingError::BadDataUrl => write!(f, "invalid data: URL"),
            LoadingError::BadStylesheet => write!(f, "invalid stylesheet"),
            LoadingError::BadCss => write!(f, "invalid CSS"),
            LoadingError::EmptyData => write!(f, "empty data"),
            LoadingError::NoSvgRoot => write!(f, "XML does not have <svg> root"),
            LoadingError::Glib(ref e) => e.fmt(f),
            LoadingError::LimitExceeded(ref s) => write!(f, "limit exceeded: {}", s),
            LoadingError::Other(ref s) => write!(f, "{}", s),
        }
    }
}

impl From<glib::Error> for LoadingError {
    fn from(e: glib::Error) -> LoadingError {
        LoadingError::Glib(e)
    }
}
<|endoftext|>


<commit_before>use std::{fmt, io, result, string};
use tera;
use toml;

#[derive(Debug)]
pub struct Error {
    msg: String
}

pub type Result<T> = result::Result<T, Error>;

impl Error {
    pub fn new(msg: String) -> Self {
        Error { msg }
    }
}

// XXX macro is your friend
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.msg)
    }
}

impl From<string::String> for Error {
    fn from(msg: string::String) -> Self {
        Error { msg }
    }
}

impl From<io::Error> for Error {
    fn from(e: io::Error) -> Self {
        Error { msg: e.to_string() }
    }
}

impl From<toml::de::Error> for Error {
    fn from(e: toml::de::Error) -> Self {
        Error { msg: e.to_string() }
    }
}

impl From<toml::ser::Error> for Error {
    fn from(e: toml::ser::Error) -> Self {
        Error { msg: e.to_string() }
    }
}

impl From<tera::Error> for Error {
    fn from(e: tera::Error) -> Self {
        Error { msg: e.to_string() }
    }
}

impl From<string::FromUtf8Error> for Error {
    fn from(e: string::FromUtf8Error) -> Self {
        Error { msg: e.to_string() }
    }
}

impl From<::std::str::Utf8Error> for Error {
    fn from(e: ::std::str::Utf8Error) -> Self {
        Error { msg: e.to_string() }
    }
}

impl From<Box<::std::error::Error + Send + Sync + 'static>> for Error {
    fn from(e: Box<::std::error::Error + Send + Sync + 'static>) -> Self {
        Error { msg: e.to_string() }
    }
}

impl From<()> for Error {
    fn from(_: ()) -> Self {
        Error { msg: "error from tiny_http header parsing".to_string() }
    }
}
<commit_msg>Add ResultContext trait<commit_after>use std::{error, fmt, io, result, string};
use tera;
use toml;

#[derive(Debug)]
pub struct Error {
    msg: String
}

impl Error {
    pub fn new(msg: String) -> Self {
        Error { msg }
    }
}

pub type Result<T> = result::Result<T, Error>;

trait ResultContext<T, E> {
    fn context(self, s: String) -> Result<T>;
}

impl<T, E> ResultContext<T, E> for result::Result<T, E>
        where E: error::Error
{
    fn context(self, s: String) -> Result<T> {
        self.map_err(|e| Error::new(format!("{}: {}", s, e.description())))
    }
}

impl<E: error::Error> From<E> for Error {
    fn from(e: E) -> Self {
        Error::new(e.description().to_string())
    }
}
<|endoftext|>