<commit_before>use learning::toolkit::kernel::{Kernel, SquaredExp};
use learning::SupModel;
use linalg::matrix::Matrix;

pub trait MeanFunc {
    fn func(&self, x: Matrix<f64>) -> Matrix<f64>;
}

/// Constant mean function
pub struct ConstMean {
    a: f64,
}

impl Default for ConstMean {
    fn default() -> ConstMean {
        ConstMean { a: 0f64 }
    }
}

impl MeanFunc for ConstMean {
    fn func(&self, x: Matrix<f64>) -> Matrix<f64> {
        Matrix::ones(x.rows(), x.cols()) * self.a
    }
}

/// Gaussian Process struct
///
/// Gaussian process with generic kernel and deterministic mean function.
/// Can be used for gaussian process regression with noise.
/// Currently does not support classification.
///
/// # Note
///
/// The
pub struct GaussianProcess<T: Kernel, U: MeanFunc> {
    ker: T,
    mean: U,
    noise: f64,
    train_data: Option<Matrix<f64>>,
    train_output: Option<Matrix<f64>>,
    train_mat: Option<Matrix<f64>>,
}

impl Default for GaussianProcess<SquaredExp, ConstMean> {
    /// Construct a default Gaussian Process
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::gp;
    ///
    /// let gp = gp::GaussianProcess::default();
    /// ```
    fn default() -> GaussianProcess<SquaredExp, ConstMean> {
        GaussianProcess {
            ker: SquaredExp::default(),
            mean: ConstMean::default(),
            noise: 1f64,
            train_data: None,
            train_output: None,
            train_mat: None,
        }
    }
}

impl<T: Kernel, U: MeanFunc> GaussianProcess<T, U> {
    /// Construct a new Gaussian Process.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::gp;
    /// use rusty_machine::learning::toolkit::kernel;
    ///
    /// let ker = kernel::SquaredExp::default();
    /// let mean = gp::ConstMean::default();
    /// let gaussp = gp::GaussianProcess::new(ker, mean, 1e-3f64);
    /// ```
    pub fn new(ker: T, mean: U, noise: f64) -> GaussianProcess<T, U> {
        GaussianProcess {
            ker: ker,
            mean: mean,
            noise: noise,
            train_data: None,
            train_output: None,
            train_mat: None,
        }
    }

    /// Construct a kernel matrix
    fn ker_mat(&self, m1: &Matrix<f64>, m2: &Matrix<f64>) -> Matrix<f64> {
        assert_eq!(m1.cols(), m2.cols());
        let dim1 = m1.rows();
        let dim2 = m2.rows();

        let mut ker_data = Vec::with_capacity(dim1 * dim2);

        for i in 0..dim1 {
            for j in 0..dim2 {
                ker_data.push(self.ker.kernel(&m1.data[i * m1.cols()..(i + 1) * m1.cols()],
                                              &m2.data[j * m2.cols()..(j + 1) * m2.cols()]));
            }
        }

        Matrix::new(dim1, dim2, ker_data)
    }
}

impl<T: Kernel, U: MeanFunc> SupModel<Matrix<f64>, Matrix<f64>> for GaussianProcess<T, U> {
    /// Predict output from data.
    fn predict(&self, data: &Matrix<f64>) -> Matrix<f64> {
        let mean = self.mean.func(data.clone());

        // Messy referencing for succint syntax
        if let (&Some(ref t_data), &Some(ref t_mat), &Some(ref t_out)) = (&self.train_data,
                                                                          &self.train_mat,
                                                                          &self.train_output) {
            let test_mat = self.ker_mat(data, t_data) * t_mat *
                           (t_out - self.mean.func(t_data.clone()));
            return mean + test_mat;
        }

        panic!("The model has not been trained.");

    }

    /// Train the model using data and outputs.
    fn train(&mut self, data: &Matrix<f64>, value: &Matrix<f64>) {
        let noise_mat = Matrix::identity(data.rows()) * self.noise;

        let ker_mat = self.ker_mat(data, data);

        let train_mat = (ker_mat + noise_mat).inverse();

        self.train_mat = Some(train_mat);
        self.train_data = Some(data.clone());
        self.train_output = Some(value.clone());
    }
}
<commit_msg>Implementing posterior calculation for GP<commit_after>use learning::toolkit::kernel::{Kernel, SquaredExp};
use learning::SupModel;
use linalg::matrix::Matrix;

pub trait MeanFunc {
    fn func(&self, x: Matrix<f64>) -> Matrix<f64>;
}

/// Constant mean function
pub struct ConstMean {
    a: f64,
}

impl Default for ConstMean {
    fn default() -> ConstMean {
        ConstMean { a: 0f64 }
    }
}

impl MeanFunc for ConstMean {
    fn func(&self, x: Matrix<f64>) -> Matrix<f64> {
        Matrix::ones(x.rows(), x.cols()) * self.a
    }
}

/// Gaussian Process struct
///
/// Gaussian process with generic kernel and deterministic mean function.
/// Can be used for gaussian process regression with noise.
/// Currently does not support classification.
///
/// # Note
///
/// The
pub struct GaussianProcess<T: Kernel, U: MeanFunc> {
    ker: T,
    mean: U,
    noise: f64,
    train_data: Option<Matrix<f64>>,
    train_output: Option<Matrix<f64>>,
    train_mat: Option<Matrix<f64>>,
}

impl Default for GaussianProcess<SquaredExp, ConstMean> {
    /// Construct a default Gaussian Process
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::gp;
    ///
    /// let gp = gp::GaussianProcess::default();
    /// ```
    fn default() -> GaussianProcess<SquaredExp, ConstMean> {
        GaussianProcess {
            ker: SquaredExp::default(),
            mean: ConstMean::default(),
            noise: 1f64,
            train_data: None,
            train_output: None,
            train_mat: None,
        }
    }
}

impl<T: Kernel, U: MeanFunc> GaussianProcess<T, U> {
    /// Construct a new Gaussian Process.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::learning::gp;
    /// use rusty_machine::learning::toolkit::kernel;
    ///
    /// let ker = kernel::SquaredExp::default();
    /// let mean = gp::ConstMean::default();
    /// let gaussp = gp::GaussianProcess::new(ker, mean, 1e-3f64);
    /// ```
    pub fn new(ker: T, mean: U, noise: f64) -> GaussianProcess<T, U> {
        GaussianProcess {
            ker: ker,
            mean: mean,
            noise: noise,
            train_data: None,
            train_output: None,
            train_mat: None,
        }
    }

    /// Construct a kernel matrix
    fn ker_mat(&self, m1: &Matrix<f64>, m2: &Matrix<f64>) -> Matrix<f64> {
        assert_eq!(m1.cols(), m2.cols());
        let dim1 = m1.rows();
        let dim2 = m2.rows();

        let mut ker_data = Vec::with_capacity(dim1 * dim2);

        for i in 0..dim1 {
            for j in 0..dim2 {
                ker_data.push(self.ker.kernel(&m1.data[i * m1.cols()..(i + 1) * m1.cols()],
                                              &m2.data[j * m2.cols()..(j + 1) * m2.cols()]));
            }
        }

        Matrix::new(dim1, dim2, ker_data)
    }
}

impl<T: Kernel, U: MeanFunc> SupModel<Matrix<f64>, Matrix<f64>> for GaussianProcess<T, U> {
    /// Predict output from data.
    fn predict(&self, data: &Matrix<f64>) -> Matrix<f64> {
        let mean = self.mean.func(data.clone());

        // Messy referencing for succint syntax
        if let (&Some(ref t_data), &Some(ref t_mat), &Some(ref t_out)) = (&self.train_data,
                                                                          &self.train_mat,
                                                                          &self.train_output) {
            let test_mat = self.ker_mat(data, t_data) * t_mat *
                           (t_out - self.mean.func(t_data.clone()));
            return mean + test_mat;
        }

        panic!("The model has not been trained.");
    }

    /// Train the model using data and outputs.
    fn train(&mut self, data: &Matrix<f64>, value: &Matrix<f64>) {
        let noise_mat = Matrix::identity(data.rows()) * self.noise;

        let ker_mat = self.ker_mat(data, data);

        let train_mat = (ker_mat + noise_mat).inverse();

        self.train_mat = Some(train_mat);
        self.train_data = Some(data.clone());
        self.train_output = Some(value.clone());
    }
}

impl<T: Kernel, U: MeanFunc> GaussianProcess<T,U> {

	/// Compute the posterior distribution
	///
	/// Requires the model to be trained first.
	/// _Note that this is a messy compromise as GPs do not
	/// fit the SupModel trait as is currently implemented._
	pub fn get_posterior(&self, data: &Matrix<f64>) -> (Matrix<f64>, Matrix<f64>) {
		let mean = self.mean.func(data.clone());

        // Messy referencing for succint syntax
        if let (&Some(ref t_data), &Some(ref t_mat), &Some(ref t_out)) = (&self.train_data,
                                                                          &self.train_mat,
                                                                          &self.train_output) {
            let test_mat = self.ker_mat(data, t_data) * t_mat;
            let post_mean = mean + &test_mat * (t_out - self.mean.func(t_data.clone()));

            let post_cov = self.ker_mat(data, data) - test_mat * self.ker_mat(t_data, data);

            return (post_mean, post_cov);
        }

        panic!("The model has not been trained.");
	}
}<|endoftext|>


<commit_before>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::{ Annotated
                                 , UnscopedState
                                 };
use core::semantic::ast::*;
use core::position::*;

type ParseFn<'a, I, T> = fn (&MnEnv<'a, I>, State<I>) -> ParseResult<T, I>;

type U = UnscopedState;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b MnEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

        /// Wrap a function into a MnParser with this environment
        fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                    -> MnParser<'a, 'b, I, T> {
            MnParser { env: self, parser: parser }
        }

        fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            unimplemented!()
        }

        fn parse_if(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            unimplemented!()
        }

        fn parse_lambda(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            unimplemented!()
        }

        fn parse_let(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            unimplemented!()
        }

        fn parse_call(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            let pos = Position::from(input.position.clone());
            self.env
                .identifier::<'b>()
                .and(many(self.parser(MnEnv::parse_expr)))
                .map(|(name, args)| Form::Call {
                        fun: Positional { pos: pos, value: name }
                      , body: args
                })
                .parse_state(input)
        }

        fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
            let pos = Position::from(input.position.clone());
            self.env
                .parens(choice([ self.parser(MnEnv::parse_def)
                               , self.parser(MnEnv::parse_if)
                               , self.parser(MnEnv::parse_lambda)
                               , self.parser(MnEnv::parse_let)
                               , self.parser(MnEnv::parse_call)
                               ]))
                .map(|f| Annotated::new(f, pos) )
                .parse_state(input)
        }

        fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
            self.parser(MnEnv::parse_expr)
        }

        fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }

        fn if_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }

        fn let_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }

        fn lambda(&'b self)-> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }
}
pub fn parse_module<N: ?Sized>(code: &str) -> Result<Vec<N>, ParseError<&str>>
where N: ASTNode + Sized {
    let alpha_ext = "+-*/<=>!?:$%_~^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(|c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(|c| alpha_ext.contains(c)))
          , reserved: [ "and"               , "begin"
                      , "case"              , "cond"
                      , "data"              , "define"
                      , "defn"              , "delay"
                      , "do"                , "else"
                      , "if"                , "lambda"
                      , "let"               , "let*"
                      , "letrec"            , "or"
                      , "quasiquote"        , "quote"
                      , "set!"              , "unquote"
                      , "unquote-splicing"
                      ].iter().map(|x| (*x).into()).collect()
        }
      , op: Identifier {
            start: satisfy(|c| ops.contains(c))
          , rest:  satisfy(|c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|"].iter().map(|x| (*x).into())
                                                     .collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });
    let env = MnEnv { env: env };

    env.white_space()
       .parse(code);

    unimplemented!()
}
<commit_msg>Start on parser for let expressions<commit_after>extern crate combine;
extern crate combine_language;
extern crate mnemosyne as core;

use combine::*;
use combine_language::{ LanguageEnv
                      , LanguageDef
                      , Identifier
                      };
use combine::primitives::{ Stream
                         , Positioner
                         , SourcePosition
                         };

use core::semantic::*;
use core::semantic::annotations::{ Annotated
                                 , UnscopedState
                                 };
use core::semantic::ast::*;
use core::position::*;

use std::rc::Rc;

type ParseFn<'a, I, T> = fn (&MnEnv<'a, I>, State<I>) -> ParseResult<T, I>;

type U = UnscopedState;

/// Wraps a parsing function with a language definition environment.
///
/// TODO: this could probably push identifiers to the symbol table here?
#[derive(Copy)]
struct MnParser<'a: 'b, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b {
        env: &'b MnEnv<'a, I>
      , parser: ParseFn<'a, I, T>
}

impl<'a, 'b, I, T> Clone for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    fn clone(&self) -> Self {
        MnParser { env: self.env , parser: self.parser }
    }
}

impl<'a, 'b, I, T> Parser for MnParser<'a, 'b, I, T>
where I: Stream<Item=char>
    , I::Range: 'b
    , I: 'b
    , 'a: 'b {

    type Input = I;
    type Output = T;

    fn parse_state(&mut self, input: State<I>) -> ParseResult<T, I> {
        (self.parser)(self.env, input)
    }

}

struct MnEnv<'a, I>
where I: Stream<Item = char>
    , I::Item: Positioner<Position = SourcePosition> {
    env: LanguageEnv<'a, I>
}

impl <'a, I> std::ops::Deref for MnEnv<'a, I>
where I: Stream<Item=char> {
    type Target = LanguageEnv<'a, I>;
    fn deref(&self) -> &LanguageEnv<'a, I> { &self.env }
}

impl<'a, 'b, I> MnEnv<'a, I>
where I: Stream<Item=char>
    , I::Item: Positioner<Position = SourcePosition>
    , I::Range: 'b {

        /// Wrap a function into a MnParser with this environment
        fn parser<T>(&'b self, parser: ParseFn<'a, I, T>)
                    -> MnParser<'a, 'b, I, T> {
            MnParser { env: self, parser: parser }
        }

        fn parse_def(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            unimplemented!()
        }

        fn parse_if(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            unimplemented!()
        }

        fn parse_lambda(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            unimplemented!()
        }

        fn parse_type(&self, input: State<I>) -> ParseResult<types::Type, I> {
            unimplemented!()
        }

        fn parse_binding(&self, input: State<I>)
                        -> ParseResult<Annotated<'a
                                                , Binding<'a, UnscopedState>
                                                , UnscopedState>
                                                , I>
        {
            let pos = input.position.clone();
            self.parser(MnEnv::parse_name)
                .and(self.parser(MnEnv::parse_type))
                .and(self.parser(MnEnv::parse_expr))
                .map(|((name, typ), value)|
                    Annotated::new( Binding { name: name
                                            , typ: typ
                                            , value: Rc::new(value)
                                            }
                                   , Position::from(pos)
                               ))
                .parse_state(input)
        }

        fn parse_let(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {

            let binding_form =
                self.reserved("let")
                    .with(many(self.parens(self.parser(MnEnv::parse_binding))))
                    .and(many(self.parser(MnEnv::parse_expr)))
                    .map(|(bindings, body)| LetForm::Let { bindings: bindings
                                                         , body: body });

            choice([ binding_form ])
                .map(Form::Let)
                .parse_state(input)
        }

        fn parse_name (&self, input: State<I>) -> ParseResult<Ident, I> {
            let position = input.position.clone();
            self.env.identifier::<'b>()
                .map(|name| Positional { pos: Position::from(position)
                                       , value: name })
                .parse_state(input)
        }

        fn parse_call(&self, input: State<I>) -> ParseResult<Form<'a, U>, I> {
            let pos = Position::from(input.position.clone());
            self.parser(MnEnv::parse_name)
                .and(many(self.parser(MnEnv::parse_expr)))
                .map(|(name, args)| Form::Call { fun: name, body: args })
                .parse_state(input)
        }

        fn parse_expr(&self, input: State<I>) -> ParseResult<Expr<'a, U>, I> {
            let pos = Position::from(input.position.clone());
            self.env
                .parens(choice([ self.parser(MnEnv::parse_def)
                               , self.parser(MnEnv::parse_if)
                               , self.parser(MnEnv::parse_lambda)
                               , self.parser(MnEnv::parse_let)
                               , self.parser(MnEnv::parse_call)
                               ]))
                .map(|f| Annotated::new(f, pos) )
                .parse_state(input)
        }

        fn expr(&'b self) -> MnParser<'a, 'b, I, Expr<'a, U>> {
            self.parser(MnEnv::parse_expr)
        }

        fn def(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }

        fn if_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }

        fn let_form(&'b self) -> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }

        fn lambda(&'b self)-> MnParser<'a, 'b, I, Form<'a, U>> {
            unimplemented!()
        }
}
pub fn parse_module<N: ?Sized>(code: &str) -> Result<Vec<N>, ParseError<&str>>
where N: ASTNode + Sized {
    let alpha_ext = "+-*/<=>!?:$%_~^";
    let ops = "+-*/|=<>";
    let env = LanguageEnv::new(LanguageDef {
        ident: Identifier {
            start: letter().or(satisfy(|c| alpha_ext.contains(c)))
          , rest: alpha_num().or(satisfy(|c| alpha_ext.contains(c)))
          , reserved: [ "and"               , "begin"
                      , "case"              , "cond"
                      , "data"              , "define"
                      , "defn"              , "delay"
                      , "do"                , "else"
                      , "if"                , "lambda"
                      , "let"               , "let*"
                      , "letrec"            , "or"
                      , "quasiquote"        , "quote"
                      , "set!"              , "unquote"
                      , "unquote-splicing"
                      ].iter().map(|x| (*x).into()).collect()
        }
      , op: Identifier {
            start: satisfy(|c| ops.contains(c))
          , rest:  satisfy(|c| ops.contains(c))
          , reserved: [ "=>", "->", "\\", "|"].iter().map(|x| (*x).into())
                                                     .collect()
        }
      , comment_line: string(";").map(|_| ())
      , comment_start: string("#|").map(|_| ())
      , comment_end: string("|#").map(|_| ())
    });
    let env = MnEnv { env: env };

    env.white_space()
       .parse(code);

    unimplemented!()
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use std::ops::{Range, Index};

/// Implementation of a `Stack` which maintains an log of `StackOp`s in order to rewind the stack
/// to a previous state.
#[derive(Debug)]
pub struct Stack<T: Clone> {
    ops: Vec<StackOp<T>>,
    cache: Vec<T>,
    snapshots: Vec<usize>
}

impl<T: Clone> Stack<T> {
    /// Creates a new `Stack`.
    pub fn new() -> Self {
        Stack {
            ops: vec![],
            cache: vec![],
            snapshots: vec![]
        }
    }

    /// Returns `true` if the stack is currently empty.
    #[allow(dead_code)]
    pub fn is_empty(&self) -> bool {
        self.cache.is_empty()
    }

    /// Returns the top-most `&T` in the `Stack`.
    pub fn peek(&self) -> Option<&T> {
        self.cache.last()
    }

    /// Pushes a `T` onto the `Stack`.
    pub fn push(&mut self, elem: T) {
        self.ops.push(StackOp::Push(elem.clone()));
        self.cache.push(elem);
    }

    /// Pops the top-most `T` from the `Stack`.
    pub fn pop(&mut self) -> Option<T> {
        let popped = self.cache.pop();
        if let Some(ref val) = popped {
            self.ops.push(StackOp::Pop(val.clone()));
        }
        popped
    }

    /// Returns the size of the stack
    pub fn len(&self) -> usize {
        self.cache.len()
    }

    /// Takes a snapshot of the current `Stack`.
    pub fn snapshot(&mut self) {
        self.snapshots.push(self.ops.len());
    }

    /// Rewinds the `Stack` to the most recent `snapshot()`. If no `snapshot()` has been taken, this
    /// function return the stack to its initial state.
    pub fn restore(&mut self) {
        match self.snapshots.pop() {
            Some(ops_index) => {
                self.rewind_to(ops_index);
                self.ops.truncate(ops_index);
            },
            None => {
                self.cache.clear();
                self.ops.clear();
            }
        }
    }

    // Rewind the stack to a particular index
    fn rewind_to(&mut self, index: usize) {
        let ops_to_rewind = &self.ops[index..];
        for op in ops_to_rewind.iter().rev() {
            match *op {
                StackOp::Push(_) => {
                    self.cache.pop();
                }
                StackOp::Pop(ref elem) => {
                    self.cache.push(elem.clone());
                }
            }
        }
    }
}

impl<T: Clone> Index<Range<usize>> for Stack<T> {
    type Output = [T];

    fn index(&self, range: Range<usize>) -> &[T] {
        self.cache.index(range)
    }
}

#[derive(Debug)]
enum StackOp<T> {
    Push(T),
    Pop(T)
}

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

    #[test]
    fn snapshot_with_empty() {
        let mut stack = Stack::new();

        stack.snapshot();
        // []
        assert!(stack.is_empty());
        // [0]
        stack.push(0);
        stack.restore();
        assert!(stack.is_empty());
    }

    #[test]
    fn snapshot_twice() {
        let mut stack = Stack::new();

        stack.push(0);

        stack.snapshot();
        stack.snapshot();
        stack.restore();
        stack.restore();

        assert_eq!(stack.iter().collect::<Vec<&i32>>(), vec![&0]);
    }

    #[test]
    fn stack_ops() {
        let mut stack = Stack::new();

        // []
        assert!(stack.is_empty());
        assert_eq!(stack.peek(), None);
        assert_eq!(stack.pop(), None);

        // [0]
        stack.push(0);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // [0, 1]
        stack.push(1);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&1));

        // [0]
        assert_eq!(stack.pop(), Some(1));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // [0, 2]
        stack.push(2);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&2));

        // [0, 2, 3]
        stack.push(3);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&3));

        // Take a snapshot of the current stack
        // [0, 2, 3]
        stack.snapshot();

        // [0, 2]
        assert_eq!(stack.pop(), Some(3));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&2));

        // Take a snapshot of the current stack
        // [0, 2]
        stack.snapshot();

        // [0]
        assert_eq!(stack.pop(), Some(2));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // []
        assert_eq!(stack.pop(), Some(0));
        assert!(stack.is_empty());

        // Test backtracking
        // [0, 2]
        stack.restore();
        assert_eq!(stack.pop(), Some(2));
        assert_eq!(stack.pop(), Some(0));
        assert_eq!(stack.pop(), None);

        // Test backtracking
        // [0, 2, 3]
        stack.restore();
        assert_eq!(stack.pop(), Some(3));
        assert_eq!(stack.pop(), Some(2));
        assert_eq!(stack.pop(), Some(0));
        assert_eq!(stack.pop(), None);
    }
}
<commit_msg>fixed snapshot test<commit_after>// pest. The Elegant Parser
// Copyright (c) 2018 Dragoș Tiselice
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use std::ops::{Range, Index};

/// Implementation of a `Stack` which maintains an log of `StackOp`s in order to rewind the stack
/// to a previous state.
#[derive(Debug)]
pub struct Stack<T: Clone> {
    ops: Vec<StackOp<T>>,
    cache: Vec<T>,
    snapshots: Vec<usize>
}

impl<T: Clone> Stack<T> {
    /// Creates a new `Stack`.
    pub fn new() -> Self {
        Stack {
            ops: vec![],
            cache: vec![],
            snapshots: vec![]
        }
    }

    /// Returns `true` if the stack is currently empty.
    #[allow(dead_code)]
    pub fn is_empty(&self) -> bool {
        self.cache.is_empty()
    }

    /// Returns the top-most `&T` in the `Stack`.
    pub fn peek(&self) -> Option<&T> {
        self.cache.last()
    }

    /// Pushes a `T` onto the `Stack`.
    pub fn push(&mut self, elem: T) {
        self.ops.push(StackOp::Push(elem.clone()));
        self.cache.push(elem);
    }

    /// Pops the top-most `T` from the `Stack`.
    pub fn pop(&mut self) -> Option<T> {
        let popped = self.cache.pop();
        if let Some(ref val) = popped {
            self.ops.push(StackOp::Pop(val.clone()));
        }
        popped
    }

    /// Returns the size of the stack
    pub fn len(&self) -> usize {
        self.cache.len()
    }

    /// Takes a snapshot of the current `Stack`.
    pub fn snapshot(&mut self) {
        self.snapshots.push(self.ops.len());
    }

    /// Rewinds the `Stack` to the most recent `snapshot()`. If no `snapshot()` has been taken, this
    /// function return the stack to its initial state.
    pub fn restore(&mut self) {
        match self.snapshots.pop() {
            Some(ops_index) => {
                self.rewind_to(ops_index);
                self.ops.truncate(ops_index);
            },
            None => {
                self.cache.clear();
                self.ops.clear();
            }
        }
    }

    // Rewind the stack to a particular index
    fn rewind_to(&mut self, index: usize) {
        let ops_to_rewind = &self.ops[index..];
        for op in ops_to_rewind.iter().rev() {
            match *op {
                StackOp::Push(_) => {
                    self.cache.pop();
                }
                StackOp::Pop(ref elem) => {
                    self.cache.push(elem.clone());
                }
            }
        }
    }
}

impl<T: Clone> Index<Range<usize>> for Stack<T> {
    type Output = [T];

    fn index(&self, range: Range<usize>) -> &[T] {
        self.cache.index(range)
    }
}

#[derive(Debug)]
enum StackOp<T> {
    Push(T),
    Pop(T)
}

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

    #[test]
    fn snapshot_with_empty() {
        let mut stack = Stack::new();

        stack.snapshot();
        // []
        assert!(stack.is_empty());
        // [0]
        stack.push(0);
        stack.restore();
        assert!(stack.is_empty());
    }

    #[test]
    fn snapshot_twice() {
        let mut stack = Stack::new();

        stack.push(0);

        stack.snapshot();
        stack.snapshot();
        stack.restore();
        stack.restore();

        assert_eq!(stack[0..stack.len()], [0]);
    }

    #[test]
    fn stack_ops() {
        let mut stack = Stack::new();

        // []
        assert!(stack.is_empty());
        assert_eq!(stack.peek(), None);
        assert_eq!(stack.pop(), None);

        // [0]
        stack.push(0);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // [0, 1]
        stack.push(1);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&1));

        // [0]
        assert_eq!(stack.pop(), Some(1));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // [0, 2]
        stack.push(2);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&2));

        // [0, 2, 3]
        stack.push(3);
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&3));

        // Take a snapshot of the current stack
        // [0, 2, 3]
        stack.snapshot();

        // [0, 2]
        assert_eq!(stack.pop(), Some(3));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&2));

        // Take a snapshot of the current stack
        // [0, 2]
        stack.snapshot();

        // [0]
        assert_eq!(stack.pop(), Some(2));
        assert!(!stack.is_empty());
        assert_eq!(stack.peek(), Some(&0));

        // []
        assert_eq!(stack.pop(), Some(0));
        assert!(stack.is_empty());

        // Test backtracking
        // [0, 2]
        stack.restore();
        assert_eq!(stack.pop(), Some(2));
        assert_eq!(stack.pop(), Some(0));
        assert_eq!(stack.pop(), None);

        // Test backtracking
        // [0, 2, 3]
        stack.restore();
        assert_eq!(stack.pop(), Some(3));
        assert_eq!(stack.pop(), Some(2));
        assert_eq!(stack.pop(), Some(0));
        assert_eq!(stack.pop(), None);
    }
}
<|endoftext|>


<commit_before>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the Matrix protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//! Depending on which parts of Matrix are relevant to you, activate the
//! following features:
//!
//! * `client-api` for the client-server API
//! * `federation-api` for the server-server (federation) API
//! * `appservice-api` for the application service API
//!
//! There's also the features `api`, `events` and `signatures` for the
//! submodules of the same names. Usually they are activated by one of the
//! other features when needed. If you are viewing this on `docs.rs`, you can
//! have a look at the feature dependencies by clicking 'Feature flags' in the
//! toolbar at the top.

#![deny(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};

pub use ruma_common::*;
#[doc(inline)]
pub use ruma_identifiers as identifiers;
#[doc(inline)]
pub use ruma_serde as serde;

pub use ruma_serde::Outgoing;

#[allow(deprecated)] // Allow re-export of deprecated items
pub use ruma_identifiers::{
    device_id, device_key_id, event_id, room_alias_id, room_id, room_version_id, server_key_id,
    server_name, server_signing_key_id, user_id, DeviceId, DeviceKeyAlgorithm, DeviceKeyId,
    EventId, RoomAliasId, RoomId, RoomIdOrAliasId, RoomVersionId, ServerName, ServerSigningKeyId,
    SigningKeyAlgorithm, UserId,
};

#[cfg(feature = "events")]
#[cfg_attr(docsrs, doc(cfg(feature = "events")))]
#[doc(inline)]
pub use ruma_events as events;
#[cfg(feature = "signatures")]
#[cfg_attr(docsrs, doc(cfg(feature = "signatures")))]
#[doc(inline)]
pub use ruma_signatures as signatures;

/// Rust types for various Matrix APIs requests and responses and abstractions for them.
#[cfg(feature = "api")]
#[cfg_attr(docsrs, doc(cfg(feature = "api")))]
pub mod api {
    pub use ruma_api::*;

    #[cfg(feature = "appservice-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "appservice-api")))]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "client-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "client-api")))]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "federation-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "federation-api")))]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "identity-service-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "identity-service-api")))]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "push-gateway-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "push-gateway-api")))]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}
<commit_msg>ruma: Re-export MxcUri, mxc_uri! from ruma-identifiers<commit_after>#![doc(html_favicon_url = "https://www.ruma.io/favicon.ico")]
#![doc(html_logo_url = "https://www.ruma.io/images/logo.png")]
//! Types and traits for working with the Matrix protocol.
//!
//! This crate re-exports things from all of the other ruma crates so you don't
//! have to manually keep all the versions in sync.
//!
//! Which crates are re-exported can be configured through cargo features.
//! Depending on which parts of Matrix are relevant to you, activate the
//! following features:
//!
//! * `client-api` for the client-server API
//! * `federation-api` for the server-server (federation) API
//! * `appservice-api` for the application service API
//!
//! There's also the features `api`, `events` and `signatures` for the
//! submodules of the same names. Usually they are activated by one of the
//! other features when needed. If you are viewing this on `docs.rs`, you can
//! have a look at the feature dependencies by clicking 'Feature flags' in the
//! toolbar at the top.

#![deny(missing_docs)]
#![cfg_attr(docsrs, feature(doc_cfg))]

#[doc(no_inline)]
pub use assign::assign;
#[doc(no_inline)]
pub use js_int::{int, uint, Int, UInt};

pub use ruma_common::*;
#[doc(inline)]
pub use ruma_identifiers as identifiers;
#[doc(inline)]
pub use ruma_serde as serde;

pub use ruma_serde::Outgoing;

#[allow(deprecated)] // Allow re-export of deprecated items
pub use ruma_identifiers::{
    device_id, device_key_id, event_id, mxc_uri, room_alias_id, room_id, room_version_id,
    server_key_id, server_name, server_signing_key_id, user_id, DeviceId, DeviceKeyAlgorithm,
    DeviceKeyId, EventId, MxcUri, RoomAliasId, RoomId, RoomIdOrAliasId, RoomVersionId, ServerName,
    ServerSigningKeyId, SigningKeyAlgorithm, UserId,
};

#[cfg(feature = "events")]
#[cfg_attr(docsrs, doc(cfg(feature = "events")))]
#[doc(inline)]
pub use ruma_events as events;
#[cfg(feature = "signatures")]
#[cfg_attr(docsrs, doc(cfg(feature = "signatures")))]
#[doc(inline)]
pub use ruma_signatures as signatures;

/// Rust types for various Matrix APIs requests and responses and abstractions for them.
#[cfg(feature = "api")]
#[cfg_attr(docsrs, doc(cfg(feature = "api")))]
pub mod api {
    pub use ruma_api::*;

    #[cfg(feature = "appservice-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "appservice-api")))]
    #[doc(inline)]
    pub use ruma_appservice_api as appservice;
    #[cfg(feature = "client-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "client-api")))]
    #[doc(inline)]
    pub use ruma_client_api as client;
    #[cfg(feature = "federation-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "federation-api")))]
    #[doc(inline)]
    pub use ruma_federation_api as federation;
    #[cfg(feature = "identity-service-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "identity-service-api")))]
    #[doc(inline)]
    pub use ruma_identity_service_api as identity_service;
    #[cfg(feature = "push-gateway-api")]
    #[cfg_attr(docsrs, doc(cfg(feature = "push-gateway-api")))]
    #[doc(inline)]
    pub use ruma_push_gateway_api as push_gateway;
}
<|endoftext|>


<commit_before>pub use self::material_font_icons::*;

pub mod material_font_icons;
<commit_msg>vector_graphics: update code to incorporate new material_icons_fonts<commit_after>pub use self::{
    material_icons_font_ttf::*,
    material_icons_font::*,
    material_icons_round_font::*,
    material_icons_sharp_font::*,
    material_icons_twotone_font::*,
};

// ttf mappings
pub mod material_icons_font_ttf;

// woff2 mappings
pub mod material_icons_font;
pub mod material_icons_round_font;
pub mod material_icons_sharp_font;
pub mod material_icons_twotone_font;
<|endoftext|>


<commit_before>use crate::io::util::{BufReader, BufWriter};
use crate::io::{AsyncBufRead, AsyncRead, AsyncWrite};

use pin_project_lite::pin_project;
use std::io;
use std::mem::MaybeUninit;
use std::pin::Pin;
use std::task::{Context, Poll};

pin_project! {
    /// Wraps a type that is [`AsyncWrite`] and [`AsyncRead`], and buffers its input and output.
    ///
    /// It can be excessively inefficient to work directly with something that implements [`AsyncWrite`]
    /// and [`AsyncRead`]. For example, every `write`, however small, has to traverse the syscall
    /// interface, and similarly, every read has to do the same. The [`BufWriter`] and [`BufReader`]
    /// types aid with these problems respectively, but do so in only one direction. `BufStream` wraps
    /// one in the other so that both directions are buffered. See their documentation for details.
    #[derive(Debug)]
    #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
    pub struct BufStream<RW> {
        #[pin]
        inner: BufReader<BufWriter<RW>>,
    }
}

impl<RW: AsyncRead + AsyncWrite> BufStream<RW> {
    /// Wrap a type in both [`BufWriter`] and [`BufReader`].
    ///
    /// See the documentation for those types and [`BufStream`] for details.
    pub fn new(stream: RW) -> BufStream<RW> {
        BufStream {
            inner: BufReader::new(BufWriter::new(stream)),
        }
    }

    /// Gets a reference to the underlying I/O object.
    ///
    /// It is inadvisable to directly read from the underlying I/O object.
    pub fn get_ref(&self) -> &RW {
        self.inner.get_ref().get_ref()
    }

    /// Gets a mutable reference to the underlying I/O object.
    ///
    /// It is inadvisable to directly read from the underlying I/O object.
    pub fn get_mut(&mut self) -> &mut RW {
        self.inner.get_mut().get_mut()
    }

    /// Gets a pinned mutable reference to the underlying I/O object.
    ///
    /// It is inadvisable to directly read from the underlying I/O object.
    pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut RW> {
        self.project().inner.get_pin_mut().get_pin_mut()
    }

    /// Consumes this `BufStream`, returning the underlying I/O object.
    ///
    /// Note that any leftover data in the internal buffer is lost.
    pub fn into_inner(self) -> RW {
        self.inner.into_inner().into_inner()
    }
}

impl<RW> From<BufReader<BufWriter<RW>>> for BufStream<RW> {
    fn from(b: BufReader<BufWriter<RW>>) -> Self {
        BufStream { inner: b }
    }
}

impl<RW> From<BufWriter<BufReader<RW>>> for BufStream<RW> {
    fn from(b: BufWriter<BufReader<RW>>) -> Self {
        // we need to "invert" the reader and writer
        let BufWriter {
            inner:
                BufReader {
                    inner,
                    buf: rbuf,
                    pos,
                    cap,
                },
            buf: wbuf,
            written,
        } = b;

        BufStream {
            inner: BufReader {
                inner: BufWriter {
                    inner,
                    buf: wbuf,
                    written,
                },
                buf: rbuf,
                pos,
                cap,
            },
        }
    }
}

impl<RW: AsyncRead + AsyncWrite> AsyncWrite for BufStream<RW> {
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<io::Result<usize>> {
        self.project().inner.poll_write(cx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        self.project().inner.poll_flush(cx)
    }

    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        self.project().inner.poll_shutdown(cx)
    }
}

impl<RW: AsyncRead + AsyncWrite> AsyncRead for BufStream<RW> {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        self.project().inner.poll_read(cx, buf)
    }

    // we can't skip unconditionally because of the large buffer case in read.
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [MaybeUninit<u8>]) -> bool {
        self.inner.prepare_uninitialized_buffer(buf)
    }
}

impl<RW: AsyncBufRead + AsyncRead + AsyncWrite> AsyncBufRead for BufStream<RW> {
    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
        self.project().inner.poll_fill_buf(cx)
    }

    fn consume(self: Pin<&mut Self>, amt: usize) {
        self.project().inner.consume(amt)
    }
}

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

    #[test]
    fn assert_unpin() {
        crate::is_unpin::<BufStream<()>>();
    }
}
<commit_msg>io: Drop AsyncBufRead bound on BufStream impl (#2108)<commit_after>use crate::io::util::{BufReader, BufWriter};
use crate::io::{AsyncBufRead, AsyncRead, AsyncWrite};

use pin_project_lite::pin_project;
use std::io;
use std::mem::MaybeUninit;
use std::pin::Pin;
use std::task::{Context, Poll};

pin_project! {
    /// Wraps a type that is [`AsyncWrite`] and [`AsyncRead`], and buffers its input and output.
    ///
    /// It can be excessively inefficient to work directly with something that implements [`AsyncWrite`]
    /// and [`AsyncRead`]. For example, every `write`, however small, has to traverse the syscall
    /// interface, and similarly, every read has to do the same. The [`BufWriter`] and [`BufReader`]
    /// types aid with these problems respectively, but do so in only one direction. `BufStream` wraps
    /// one in the other so that both directions are buffered. See their documentation for details.
    #[derive(Debug)]
    #[cfg_attr(docsrs, doc(cfg(feature = "io-util")))]
    pub struct BufStream<RW> {
        #[pin]
        inner: BufReader<BufWriter<RW>>,
    }
}

impl<RW: AsyncRead + AsyncWrite> BufStream<RW> {
    /// Wrap a type in both [`BufWriter`] and [`BufReader`].
    ///
    /// See the documentation for those types and [`BufStream`] for details.
    pub fn new(stream: RW) -> BufStream<RW> {
        BufStream {
            inner: BufReader::new(BufWriter::new(stream)),
        }
    }

    /// Gets a reference to the underlying I/O object.
    ///
    /// It is inadvisable to directly read from the underlying I/O object.
    pub fn get_ref(&self) -> &RW {
        self.inner.get_ref().get_ref()
    }

    /// Gets a mutable reference to the underlying I/O object.
    ///
    /// It is inadvisable to directly read from the underlying I/O object.
    pub fn get_mut(&mut self) -> &mut RW {
        self.inner.get_mut().get_mut()
    }

    /// Gets a pinned mutable reference to the underlying I/O object.
    ///
    /// It is inadvisable to directly read from the underlying I/O object.
    pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut RW> {
        self.project().inner.get_pin_mut().get_pin_mut()
    }

    /// Consumes this `BufStream`, returning the underlying I/O object.
    ///
    /// Note that any leftover data in the internal buffer is lost.
    pub fn into_inner(self) -> RW {
        self.inner.into_inner().into_inner()
    }
}

impl<RW> From<BufReader<BufWriter<RW>>> for BufStream<RW> {
    fn from(b: BufReader<BufWriter<RW>>) -> Self {
        BufStream { inner: b }
    }
}

impl<RW> From<BufWriter<BufReader<RW>>> for BufStream<RW> {
    fn from(b: BufWriter<BufReader<RW>>) -> Self {
        // we need to "invert" the reader and writer
        let BufWriter {
            inner:
                BufReader {
                    inner,
                    buf: rbuf,
                    pos,
                    cap,
                },
            buf: wbuf,
            written,
        } = b;

        BufStream {
            inner: BufReader {
                inner: BufWriter {
                    inner,
                    buf: wbuf,
                    written,
                },
                buf: rbuf,
                pos,
                cap,
            },
        }
    }
}

impl<RW: AsyncRead + AsyncWrite> AsyncWrite for BufStream<RW> {
    fn poll_write(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &[u8],
    ) -> Poll<io::Result<usize>> {
        self.project().inner.poll_write(cx, buf)
    }

    fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        self.project().inner.poll_flush(cx)
    }

    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
        self.project().inner.poll_shutdown(cx)
    }
}

impl<RW: AsyncRead + AsyncWrite> AsyncRead for BufStream<RW> {
    fn poll_read(
        self: Pin<&mut Self>,
        cx: &mut Context<'_>,
        buf: &mut [u8],
    ) -> Poll<io::Result<usize>> {
        self.project().inner.poll_read(cx, buf)
    }

    // we can't skip unconditionally because of the large buffer case in read.
    unsafe fn prepare_uninitialized_buffer(&self, buf: &mut [MaybeUninit<u8>]) -> bool {
        self.inner.prepare_uninitialized_buffer(buf)
    }
}

impl<RW: AsyncRead + AsyncWrite> AsyncBufRead for BufStream<RW> {
    fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
        self.project().inner.poll_fill_buf(cx)
    }

    fn consume(self: Pin<&mut Self>, amt: usize) {
        self.project().inner.consume(amt)
    }
}

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

    #[test]
    fn assert_unpin() {
        crate::is_unpin::<BufStream<()>>();
    }
}
<|endoftext|>


<commit_before>pub fn main() {
    let mut count = 0u32;

    println!("Let's count until infinity!");

    // Infinite loop
    loop {
        count += 1;

        if count == 3 {
            println!("three");

            // Skip the rest of this iteration
            continue;
        }

        println!("{}", count);

        if count == 5 {
            println!("OK, that's enough");

            // Exit this loop
            break;
        }
    }
}<commit_msg>Rust By Examples [RBE] - loop - 7.2.1 Nesting and labels<commit_after>#![allow(unreachable_code)]

pub fn main() {
    let mut count = 0u32;

    println!("Let's count until infinity!");

    // Infinite loop
    loop {
        count += 1;

        if count == 3 {
            println!("three");

            // Skip the rest of this iteration
            continue;
        }

        println!("{}", count);

        if count == 5 {
            println!("OK, that's enough");

            // Exit this loop
            break;
        }
    }
    loop_nested_labeles();
}

fn loop_nested_labeles() {
    let mut i = 0;
    'outer: loop {
        i += 1;
        println!("Entered the outer loop [{}]", i);

        'inner: loop {
            println!("Entered the inner loop [{}]", i);
            if i <= 2 {
                continue 'outer;
            }
            // This would break only the inner loop
            //break;

            // This breaks the outer loop
            break 'outer;
        }
        println!("This point will never be reached");
    }

    println!("Exited the outer loop");
}<|endoftext|>


<commit_before>// TODO: everything
<commit_msg>Completed BST implementation<commit_after>// TODO: everything

#[derive(Debug)]
pub struct Tree {
    root: Link,
}

#[derive(Debug)]
pub struct Node {
    elem: i32,
    left: Link,
    right: Link,
}

#[derive(Debug)]
pub enum Link {
    Empty,
    More(Box<Node>),
}

impl Tree {
    pub fn new() -> Self {
        Tree { root: Link::Empty }
    }

    pub fn insert(&mut self, elem: i32) -> bool {
        return self.root.insert(elem);
    }

    pub fn search(&self, elem: i32) -> bool {
        return self.root.search(elem);
    }
}

impl Link {
    pub fn insert(&mut self, elem: i32) -> bool {
        let target_node = self;
         let new_node = Node {
            elem: elem,
            left: Link::Empty,
            right: Link::Empty,
        };
        let boxed_link = Link::More(Box::new(new_node));
        match target_node {
            &mut Link::More(ref mut node) => {
                if node.elem == elem {
                    return false;
                } else if node.elem < elem {
                    node.left.insert(elem)
                } else {
                    node.right.insert(elem)
                }
            },
            _ => {
                *target_node = boxed_link;
                return true;
            }
        }
    }

    pub fn search(&self, elem: i32) -> bool {
        let root = self;
        match root {
            &Link::More(ref node) => {
                if node.elem == elem {
                    return true;
                }else if node.elem < elem {
                    node.left.search(elem)
                }else {
                    node.right.search(elem)
                }
            }
            &Link::Empty => {
                return false;
            }
        }
    }
}

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

    #[test]
    fn test_insert() {
        let mut bst = Tree::new();

        for i in 0 .. 1000 {
            assert!(bst.insert(i));
        }

        for i in 0 .. 1000 {
            assert!(bst.search(i));
        }
    }

    #[test]
    fn test_search() {
        let mut bst = Tree::new();
        assert!(bst.insert(1));
        assert!(bst.insert(10));
        assert!(bst.insert(4));
        assert!(bst.insert(7));
        assert!(bst.insert(2));

        assert!(bst.search(1));
        assert!(!bst.search(11));
        assert!(bst.search(7));
        assert!(bst.search(10));
        assert!(!bst.search(13));
        assert!(bst.search(4));
        assert!(bst.search(2));
        assert!(bst.search(10));
    }
}

<|endoftext|>


<commit_before>// This file provides functions to create a libxml2 xmlParserCtxtPtr, configured
// to read from a gio::InputStream, and to maintain its loading data in an XmlState.

use gio;
use gio::prelude::*;
use gio_sys;
use glib_sys;
use std::mem;
use std::ptr;
use std::slice;
use std::str;

use glib::translate::*;

use error::{set_gerror, RsvgError};
use property_bag::PropertyBag;
use util::utf8_cstr;
use xml::XmlState;
use xml2::*;

extern "C" {
    fn rsvg_sax_error_cb(data: *mut libc::c_void);
}

fn get_xml2_sax_handler() -> xmlSAXHandler {
    let mut h: xmlSAXHandler = unsafe { mem::zeroed() };

    h.getEntity = Some(sax_get_entity_cb);
    h.entityDecl = Some(sax_entity_decl_cb);
    h.unparsedEntityDecl = Some(sax_unparsed_entity_decl_cb);
    h.getParameterEntity = Some(sax_get_parameter_entity_cb);
    h.characters = Some(sax_characters_cb);
    h.cdataBlock = Some(sax_characters_cb);
    h.startElement = Some(sax_start_element_cb);
    h.endElement = Some(sax_end_element_cb);
    h.processingInstruction = Some(sax_processing_instruction_cb);

    // This one is defined in the C code, because the prototype has varargs
    // and we can't handle those from Rust :(
    h.error = rsvg_sax_error_cb as *mut _;

    h
}

fn free_xml_parser_and_doc(parser: xmlParserCtxtPtr) {
    unsafe {
        if !parser.is_null() {
            let rparser = &mut *parser;

            if !rparser.myDoc.is_null() {
                xmlFreeDoc(rparser.myDoc);
                rparser.myDoc = ptr::null_mut();
            }

            xmlFreeParserCtxt(parser);
        }
    }
}

unsafe extern "C" fn sax_get_entity_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
) -> xmlEntityPtr {
    let xml = &*(ctx as *mut XmlState);

    assert!(!name.is_null());
    let name = utf8_cstr(name);

    xml.entity_lookup(name).unwrap_or(ptr::null_mut())
}

unsafe extern "C" fn sax_entity_decl_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
    type_: libc::c_int,
    _public_id: *const libc::c_char,
    _system_id: *const libc::c_char,
    content: *const libc::c_char,
) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!name.is_null());

    if type_ != XML_INTERNAL_GENERAL_ENTITY {
        // We don't allow loading external entities; we don't support
        // defining parameter entities in the DTD, and libxml2 should
        // handle internal predefined entities by itself (e.g. "&").
        return;
    }

    let entity = xmlNewEntity(
        ptr::null_mut(),
        name,
        type_,
        ptr::null(),
        ptr::null(),
        content,
    );
    assert!(!entity.is_null());

    let name = utf8_cstr(name);
    xml.entity_insert(name, entity);
}

unsafe extern "C" fn sax_unparsed_entity_decl_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
    public_id: *const libc::c_char,
    system_id: *const libc::c_char,
    _notation_name: *const libc::c_char,
) {
    sax_entity_decl_cb(
        ctx,
        name,
        XML_INTERNAL_GENERAL_ENTITY,
        public_id,
        system_id,
        ptr::null(),
    );
}

unsafe extern "C" fn sax_start_element_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
    atts: *const *const libc::c_char,
) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!name.is_null());
    let name = utf8_cstr(name);

    let pbag = PropertyBag::new_from_key_value_pairs(atts);

    xml.start_element(name, &pbag);
}

unsafe extern "C" fn sax_end_element_cb(ctx: *mut libc::c_void, name: *const libc::c_char) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!name.is_null());
    let name = utf8_cstr(name);

    xml.end_element(name);
}

unsafe extern "C" fn sax_characters_cb(
    ctx: *mut libc::c_void,
    unterminated_text: *const libc::c_char,
    len: libc::c_int,
) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!unterminated_text.is_null());
    assert!(len >= 0);

    // libxml2 already validated the incoming string as UTF-8.  Note that
    // it is *not* nul-terminated; this is why we create a byte slice first.
    let bytes = std::slice::from_raw_parts(unterminated_text as *const u8, len as usize);
    let utf8 = str::from_utf8_unchecked(bytes);

    xml.characters(utf8);
}

unsafe extern "C" fn sax_processing_instruction_cb(
    ctx: *mut libc::c_void,
    target: *const libc::c_char,
    data: *const libc::c_char,
) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!target.is_null());
    let target = utf8_cstr(target);

    assert!(!data.is_null());
    let data = utf8_cstr(data);

    xml.processing_instruction(target, data);
}

unsafe extern "C" fn sax_get_parameter_entity_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
) -> xmlEntityPtr {
    sax_get_entity_cb(ctx, name)
}

fn set_xml_parse_options(parser: xmlParserCtxtPtr, unlimited_size: bool) {
    let mut options: libc::c_int = XML_PARSE_NONET | XML_PARSE_BIG_LINES;

    if unlimited_size {
        options |= XML_PARSE_HUGE;
    }

    unsafe {
        xmlCtxtUseOptions(parser, options);

        // If false, external entities work, but internal ones don't. if
        // true, internal entities work, but external ones don't. favor
        // internal entities, in order to not cause a regression
        (*parser).replaceEntities = 1;
    }
}

// Struct used as closure data for xmlCreateIOParserCtxt().  In conjunction
// with stream_ctx_read() and stream_ctx_close(), this struct provides the
// I/O callbacks and their context for libxml2.
//
// We call I/O methods on the stream, and as soon as we get an error
// we store it in the gio_error field.  Libxml2 just allows us to
// return -1 from the I/O callbacks in that case; it doesn't actually
// see the error code.
//
// The gio_error field comes from the place that constructs the
// StreamCtx.  That place is later responsible for seeing if the error
// is set; if it is, it means that there was an I/O error.  Otherwise,
// there were no I/O errors but the caller must then ask libxml2 for
// XML parsing errors.
struct StreamCtx {
    stream: gio::InputStream,
    cancellable: Option<gio::Cancellable>,
    gio_error: *mut *mut glib_sys::GError,
}

// read() callback from xmlCreateIOParserCtxt()
unsafe extern "C" fn stream_ctx_read(
    context: *mut libc::c_void,
    buffer: *mut libc::c_char,
    len: libc::c_int,
) -> libc::c_int {
    let ctx = &mut *(context as *mut StreamCtx);

    // has the error been set already?
    if !(*ctx.gio_error).is_null() {
        return -1;
    }

    let buf: &mut [u8] = slice::from_raw_parts_mut(buffer as *mut u8, len as usize);

    match ctx.stream.read(buf, ctx.cancellable.as_ref()) {
        Ok(size) => size as libc::c_int,

        Err(e) => {
            let e: *const glib_sys::GError = e.to_glib_full();
            *ctx.gio_error = e as *mut _;
            -1
        }
    }
}

// close() callback from xmlCreateIOParserCtxt()
unsafe extern "C" fn stream_ctx_close(context: *mut libc::c_void) -> libc::c_int {
    let ctx = &mut *(context as *mut StreamCtx);

    let ret = match ctx.stream.close(ctx.cancellable.as_ref()) {
        Ok(()) => 0,

        Err(e) => {
            // don't overwrite a previous error
            if (*ctx.gio_error).is_null() {
                let e: *const glib_sys::GError = e.to_glib_full();
                *ctx.gio_error = e as *mut _;
            }

            -1
        }
    };

    Box::from_raw(ctx);

    ret
}

fn create_xml_stream_parser(
    xml: &mut XmlState,
    unlimited_size: bool,
    stream: gio::InputStream,
    cancellable: Option<gio::Cancellable>,
    gio_error: *mut *mut glib_sys::GError,
) -> Result<xmlParserCtxtPtr, glib::Error> {
    let ctx = Box::new(StreamCtx {
        stream,
        cancellable,
        gio_error,
    });

    let mut sax_handler = get_xml2_sax_handler();

    unsafe {
        let parser = xmlCreateIOParserCtxt(
            &mut sax_handler,
            xml as *mut _ as *mut _,
            Some(stream_ctx_read),
            Some(stream_ctx_close),
            Box::into_raw(ctx) as *mut _,
            XML_CHAR_ENCODING_NONE,
        );

        if parser.is_null() {
            // on error, xmlCreateIOParserCtxt() frees our context via the
            // stream_ctx_close function
            Err(glib::Error::new(RsvgError, "Error creating XML parser"))
        } else {
            set_xml_parse_options(parser, unlimited_size);
            Ok(parser)
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_create_xml_push_parser(
    xml: *mut XmlState,
    unlimited_size: glib_sys::gboolean,
    base_uri: *const libc::c_char,
    error: *mut *mut glib_sys::GError,
) -> xmlParserCtxtPtr {
    let mut sax_handler = get_xml2_sax_handler();

    let parser = xmlCreatePushParserCtxt(&mut sax_handler, xml as *mut _, ptr::null(), 0, base_uri);

    if parser.is_null() {
        set_gerror(error, 0, "Error creating XML parser");
    } else {
        set_xml_parse_options(parser, from_glib(unlimited_size));
    }

    parser
}

fn xml2_error_to_string(xerr: xmlErrorPtr) -> String {
    unsafe {
        if !xerr.is_null() {
            let xerr = &*xerr;

            let file = if xerr.file.is_null() {
                "data".to_string()
            } else {
                from_glib_none(xerr.file)
            };

            let message = if xerr.message.is_null() {
                "-".to_string()
            } else {
                from_glib_none(xerr.message)
            };

            format!(
                "Error domain {} code {} on line {} column {} of {}: {}",
                xerr.domain, xerr.code, xerr.line, xerr.int2, file, message
            )
        } else {
            // The error is not set?  Return a generic message :(
            "Error parsing XML data".to_string()
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_set_error_from_xml(
    error: *mut *mut glib_sys::GError,
    ctxt: xmlParserCtxtPtr,
) {
    let xerr = xmlCtxtGetLastError(ctxt as *mut _);

    set_gerror(error, 0, &xml2_error_to_string(xerr));
}

// Error returned when parsing an XML stream
pub enum ParseFromStreamError {
    // GIO error from the I/O callbacks
    IoError(glib::Error),

    // XML parsing error from libxml2
    XmlParseError(String),
}

// Parses XML from a stream into an XmlState.
//
// This can be called "in the middle" of an XmlState's processing status,
// for example, when including another XML file via xi:include.
pub fn xml_state_parse_from_stream(
    xml: &mut XmlState,
    unlimited_size: bool,
    stream: gio::InputStream,
    cancellable: Option<gio::Cancellable>,
) -> Result<(), ParseFromStreamError> {
    let mut gio_err: *mut glib_sys::GError = ptr::null_mut();

    match create_xml_stream_parser(xml, unlimited_size, stream, cancellable, &mut gio_err) {
        Ok(parser) => unsafe {
            let xml_parse_success = xmlParseDocument(parser) == 0;

            let io_success = gio_err.is_null();

            let res;

            if !io_success {
                res = Err(ParseFromStreamError::IoError(from_glib_full(gio_err)));
            } else if !xml_parse_success {
                let xerr = xmlCtxtGetLastError(parser as *mut _);
                res = Err(ParseFromStreamError::XmlParseError(xml2_error_to_string(
                    xerr,
                )));
            } else {
                res = Ok(());
            }

            free_xml_parser_and_doc(parser);

            res
        },

        Err(e) => Err(ParseFromStreamError::IoError(e)),
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_xml_state_parse_from_stream(
    xml: *mut XmlState,
    unlimited_size: glib_sys::gboolean,
    stream: *mut gio_sys::GInputStream,
    cancellable: *mut gio_sys::GCancellable,
    error: *mut *mut glib_sys::GError,
) -> glib_sys::gboolean {
    assert!(!xml.is_null());
    let xml = &mut *xml;

    let unlimited_size = from_glib(unlimited_size);

    let stream = from_glib_none(stream);
    let cancellable = from_glib_none(cancellable);

    match xml_state_parse_from_stream(xml, unlimited_size, stream, cancellable) {
        Ok(()) => true.to_glib(),

        Err(e) => {
            match e {
                ParseFromStreamError::IoError(e) => {
                    if !error.is_null() {
                        *error = e.to_glib_full() as *mut _;
                    }
                }

                ParseFromStreamError::XmlParseError(s) => {
                    set_gerror(error, 0, &s);
                }
            }

            false.to_glib()
        }
    }
}
<commit_msg>create_xml_stream_parser(): Don't return a glib::Error; use a custom error code<commit_after>// This file provides functions to create a libxml2 xmlParserCtxtPtr, configured
// to read from a gio::InputStream, and to maintain its loading data in an XmlState.

use gio;
use gio::prelude::*;
use gio_sys;
use glib_sys;
use std::mem;
use std::ptr;
use std::slice;
use std::str;

use glib::translate::*;

use error::set_gerror;
use property_bag::PropertyBag;
use util::utf8_cstr;
use xml::XmlState;
use xml2::*;

extern "C" {
    fn rsvg_sax_error_cb(data: *mut libc::c_void);
}

fn get_xml2_sax_handler() -> xmlSAXHandler {
    let mut h: xmlSAXHandler = unsafe { mem::zeroed() };

    h.getEntity = Some(sax_get_entity_cb);
    h.entityDecl = Some(sax_entity_decl_cb);
    h.unparsedEntityDecl = Some(sax_unparsed_entity_decl_cb);
    h.getParameterEntity = Some(sax_get_parameter_entity_cb);
    h.characters = Some(sax_characters_cb);
    h.cdataBlock = Some(sax_characters_cb);
    h.startElement = Some(sax_start_element_cb);
    h.endElement = Some(sax_end_element_cb);
    h.processingInstruction = Some(sax_processing_instruction_cb);

    // This one is defined in the C code, because the prototype has varargs
    // and we can't handle those from Rust :(
    h.error = rsvg_sax_error_cb as *mut _;

    h
}

fn free_xml_parser_and_doc(parser: xmlParserCtxtPtr) {
    unsafe {
        if !parser.is_null() {
            let rparser = &mut *parser;

            if !rparser.myDoc.is_null() {
                xmlFreeDoc(rparser.myDoc);
                rparser.myDoc = ptr::null_mut();
            }

            xmlFreeParserCtxt(parser);
        }
    }
}

unsafe extern "C" fn sax_get_entity_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
) -> xmlEntityPtr {
    let xml = &*(ctx as *mut XmlState);

    assert!(!name.is_null());
    let name = utf8_cstr(name);

    xml.entity_lookup(name).unwrap_or(ptr::null_mut())
}

unsafe extern "C" fn sax_entity_decl_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
    type_: libc::c_int,
    _public_id: *const libc::c_char,
    _system_id: *const libc::c_char,
    content: *const libc::c_char,
) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!name.is_null());

    if type_ != XML_INTERNAL_GENERAL_ENTITY {
        // We don't allow loading external entities; we don't support
        // defining parameter entities in the DTD, and libxml2 should
        // handle internal predefined entities by itself (e.g. "&").
        return;
    }

    let entity = xmlNewEntity(
        ptr::null_mut(),
        name,
        type_,
        ptr::null(),
        ptr::null(),
        content,
    );
    assert!(!entity.is_null());

    let name = utf8_cstr(name);
    xml.entity_insert(name, entity);
}

unsafe extern "C" fn sax_unparsed_entity_decl_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
    public_id: *const libc::c_char,
    system_id: *const libc::c_char,
    _notation_name: *const libc::c_char,
) {
    sax_entity_decl_cb(
        ctx,
        name,
        XML_INTERNAL_GENERAL_ENTITY,
        public_id,
        system_id,
        ptr::null(),
    );
}

unsafe extern "C" fn sax_start_element_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
    atts: *const *const libc::c_char,
) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!name.is_null());
    let name = utf8_cstr(name);

    let pbag = PropertyBag::new_from_key_value_pairs(atts);

    xml.start_element(name, &pbag);
}

unsafe extern "C" fn sax_end_element_cb(ctx: *mut libc::c_void, name: *const libc::c_char) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!name.is_null());
    let name = utf8_cstr(name);

    xml.end_element(name);
}

unsafe extern "C" fn sax_characters_cb(
    ctx: *mut libc::c_void,
    unterminated_text: *const libc::c_char,
    len: libc::c_int,
) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!unterminated_text.is_null());
    assert!(len >= 0);

    // libxml2 already validated the incoming string as UTF-8.  Note that
    // it is *not* nul-terminated; this is why we create a byte slice first.
    let bytes = std::slice::from_raw_parts(unterminated_text as *const u8, len as usize);
    let utf8 = str::from_utf8_unchecked(bytes);

    xml.characters(utf8);
}

unsafe extern "C" fn sax_processing_instruction_cb(
    ctx: *mut libc::c_void,
    target: *const libc::c_char,
    data: *const libc::c_char,
) {
    let xml = &mut *(ctx as *mut XmlState);

    assert!(!target.is_null());
    let target = utf8_cstr(target);

    assert!(!data.is_null());
    let data = utf8_cstr(data);

    xml.processing_instruction(target, data);
}

unsafe extern "C" fn sax_get_parameter_entity_cb(
    ctx: *mut libc::c_void,
    name: *const libc::c_char,
) -> xmlEntityPtr {
    sax_get_entity_cb(ctx, name)
}

fn set_xml_parse_options(parser: xmlParserCtxtPtr, unlimited_size: bool) {
    let mut options: libc::c_int = XML_PARSE_NONET | XML_PARSE_BIG_LINES;

    if unlimited_size {
        options |= XML_PARSE_HUGE;
    }

    unsafe {
        xmlCtxtUseOptions(parser, options);

        // If false, external entities work, but internal ones don't. if
        // true, internal entities work, but external ones don't. favor
        // internal entities, in order to not cause a regression
        (*parser).replaceEntities = 1;
    }
}

// Struct used as closure data for xmlCreateIOParserCtxt().  In conjunction
// with stream_ctx_read() and stream_ctx_close(), this struct provides the
// I/O callbacks and their context for libxml2.
//
// We call I/O methods on the stream, and as soon as we get an error
// we store it in the gio_error field.  Libxml2 just allows us to
// return -1 from the I/O callbacks in that case; it doesn't actually
// see the error code.
//
// The gio_error field comes from the place that constructs the
// StreamCtx.  That place is later responsible for seeing if the error
// is set; if it is, it means that there was an I/O error.  Otherwise,
// there were no I/O errors but the caller must then ask libxml2 for
// XML parsing errors.
struct StreamCtx {
    stream: gio::InputStream,
    cancellable: Option<gio::Cancellable>,
    gio_error: *mut *mut glib_sys::GError,
}

// read() callback from xmlCreateIOParserCtxt()
unsafe extern "C" fn stream_ctx_read(
    context: *mut libc::c_void,
    buffer: *mut libc::c_char,
    len: libc::c_int,
) -> libc::c_int {
    let ctx = &mut *(context as *mut StreamCtx);

    // has the error been set already?
    if !(*ctx.gio_error).is_null() {
        return -1;
    }

    let buf: &mut [u8] = slice::from_raw_parts_mut(buffer as *mut u8, len as usize);

    match ctx.stream.read(buf, ctx.cancellable.as_ref()) {
        Ok(size) => size as libc::c_int,

        Err(e) => {
            let e: *const glib_sys::GError = e.to_glib_full();
            *ctx.gio_error = e as *mut _;
            -1
        }
    }
}

// close() callback from xmlCreateIOParserCtxt()
unsafe extern "C" fn stream_ctx_close(context: *mut libc::c_void) -> libc::c_int {
    let ctx = &mut *(context as *mut StreamCtx);

    let ret = match ctx.stream.close(ctx.cancellable.as_ref()) {
        Ok(()) => 0,

        Err(e) => {
            // don't overwrite a previous error
            if (*ctx.gio_error).is_null() {
                let e: *const glib_sys::GError = e.to_glib_full();
                *ctx.gio_error = e as *mut _;
            }

            -1
        }
    };

    Box::from_raw(ctx);

    ret
}

fn create_xml_stream_parser(
    xml: &mut XmlState,
    unlimited_size: bool,
    stream: gio::InputStream,
    cancellable: Option<gio::Cancellable>,
    gio_error: *mut *mut glib_sys::GError,
) -> Result<xmlParserCtxtPtr, ParseFromStreamError> {
    let ctx = Box::new(StreamCtx {
        stream,
        cancellable,
        gio_error,
    });

    let mut sax_handler = get_xml2_sax_handler();

    unsafe {
        let parser = xmlCreateIOParserCtxt(
            &mut sax_handler,
            xml as *mut _ as *mut _,
            Some(stream_ctx_read),
            Some(stream_ctx_close),
            Box::into_raw(ctx) as *mut _,
            XML_CHAR_ENCODING_NONE,
        );

        if parser.is_null() {
            // on error, xmlCreateIOParserCtxt() frees our ctx via the
            // stream_ctx_close function
            Err(ParseFromStreamError::CouldNotCreateParser)
        } else {
            set_xml_parse_options(parser, unlimited_size);
            Ok(parser)
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_create_xml_push_parser(
    xml: *mut XmlState,
    unlimited_size: glib_sys::gboolean,
    base_uri: *const libc::c_char,
    error: *mut *mut glib_sys::GError,
) -> xmlParserCtxtPtr {
    let mut sax_handler = get_xml2_sax_handler();

    let parser = xmlCreatePushParserCtxt(&mut sax_handler, xml as *mut _, ptr::null(), 0, base_uri);

    if parser.is_null() {
        set_gerror(error, 0, "Error creating XML parser");
    } else {
        set_xml_parse_options(parser, from_glib(unlimited_size));
    }

    parser
}

fn xml2_error_to_string(xerr: xmlErrorPtr) -> String {
    unsafe {
        if !xerr.is_null() {
            let xerr = &*xerr;

            let file = if xerr.file.is_null() {
                "data".to_string()
            } else {
                from_glib_none(xerr.file)
            };

            let message = if xerr.message.is_null() {
                "-".to_string()
            } else {
                from_glib_none(xerr.message)
            };

            format!(
                "Error domain {} code {} on line {} column {} of {}: {}",
                xerr.domain, xerr.code, xerr.line, xerr.int2, file, message
            )
        } else {
            // The error is not set?  Return a generic message :(
            "Error parsing XML data".to_string()
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_set_error_from_xml(
    error: *mut *mut glib_sys::GError,
    ctxt: xmlParserCtxtPtr,
) {
    let xerr = xmlCtxtGetLastError(ctxt as *mut _);

    set_gerror(error, 0, &xml2_error_to_string(xerr));
}

// Error returned when parsing an XML stream
pub enum ParseFromStreamError {
    // We couldn't even create the libxml2 parser
    CouldNotCreateParser,

    // GIO error from the I/O callbacks
    IoError(glib::Error),

    // XML parsing error from libxml2
    XmlParseError(String),
}

// Parses XML from a stream into an XmlState.
//
// This can be called "in the middle" of an XmlState's processing status,
// for example, when including another XML file via xi:include.
pub fn xml_state_parse_from_stream(
    xml: &mut XmlState,
    unlimited_size: bool,
    stream: gio::InputStream,
    cancellable: Option<gio::Cancellable>,
) -> Result<(), ParseFromStreamError> {
    let mut gio_err: *mut glib_sys::GError = ptr::null_mut();

    match create_xml_stream_parser(xml, unlimited_size, stream, cancellable, &mut gio_err) {
        Ok(parser) => unsafe {
            let xml_parse_success = xmlParseDocument(parser) == 0;

            let io_success = gio_err.is_null();

            let res;

            if !io_success {
                res = Err(ParseFromStreamError::IoError(from_glib_full(gio_err)));
            } else if !xml_parse_success {
                let xerr = xmlCtxtGetLastError(parser as *mut _);
                res = Err(ParseFromStreamError::XmlParseError(xml2_error_to_string(
                    xerr,
                )));
            } else {
                res = Ok(());
            }

            free_xml_parser_and_doc(parser);

            res
        },

        Err(e) => Err(e),
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_xml_state_parse_from_stream(
    xml: *mut XmlState,
    unlimited_size: glib_sys::gboolean,
    stream: *mut gio_sys::GInputStream,
    cancellable: *mut gio_sys::GCancellable,
    error: *mut *mut glib_sys::GError,
) -> glib_sys::gboolean {
    assert!(!xml.is_null());
    let xml = &mut *xml;

    let unlimited_size = from_glib(unlimited_size);

    let stream = from_glib_none(stream);
    let cancellable = from_glib_none(cancellable);

    match xml_state_parse_from_stream(xml, unlimited_size, stream, cancellable) {
        Ok(()) => true.to_glib(),

        Err(e) => {
            match e {
                ParseFromStreamError::CouldNotCreateParser => {
                    set_gerror(error, 0, "Error creating XML parser");
                }

                ParseFromStreamError::IoError(e) => {
                    if !error.is_null() {
                        *error = e.to_glib_full() as *mut _;
                    }
                }

                ParseFromStreamError::XmlParseError(s) => {
                    set_gerror(error, 0, &s);
                }
            }

            false.to_glib()
        }
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use std::fs::File;
use std::io::{self, BufRead};
use std::str::FromStr;

#[macro_use]
extern crate lazy_static;
extern crate if_chain;

struct State<'a, T>(Box<dyn 'a + Iterator<Item = T>>, Option<T>);

pub struct Merge<'a, T> {
    count: usize,
    states: Vec<State<'a, T>>,
}

impl<'a, T: 'a + FromStr> Merge<'a, T> {
    pub fn new(filename: &str) -> Self {
        let count = get_number(filename).unwrap();
        let states = (0..count)
            .map(|i| {
                let collection = Box::new(get_collection(filename, i).unwrap());
                State(collection, None)
            })
            .collect();
        Merge {
            count: count,
            states: states,
        }
    }
}

impl<'a, T: PartialOrd> Iterator for Merge<'a, T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        for i in 0..count {
            let state = &mut states[i];
            if state.1.is_none() {
                state.1 = state.0.next();
            }
        }
        let mut min_index: Option<usize> = None;
        for i in 0..count {
            if_chain::if_chain! {
                if let Some(_) = states[i].1.as_ref();
                if min_index.is_none();
                then {
                    min_index.replace(i);
                }
            }
            if_chain::if_chain! {
                if let Some(val) = states[i].1.as_ref();
                if let Some(m) = min_index;
                if let Some(min) = states[m].1.as_ref();
                if val < min;
                then {
                    min_index.replace(i);
                }
            }
        }
        if let Some(m) = min_index {
            return states[m].1.take();
        }
        return None;
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    return Ok(matches.next().unwrap().parse().unwrap());
}

pub fn get_output<T: FromStr>(filename: &str) -> io::Result<impl Iterator<Item = T>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection<T: FromStr>(
    filename: &str,
    idx: usize,
) -> io::Result<impl Iterator<Item = T>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers<T: FromStr>(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = T>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<T> {
        if let Ok(i) = v.parse::<T>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches
        .map(move |s| {
            let numbers = s.split(',').filter_map(|v| to_int(&v));
            numbers.collect::<Vec<_>>()
        })
        .flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line| line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches =
        lines.filter_map(move |line| r.captures(&line).map(|captures| captures[1].to_string()));
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap(), 3);
    }

    #[test]
    fn test_output() {
        let output = [1, 1, 2, 2, 3, 4, 4, 6, 7, 9, 9, 20, 21];
        assert_eq!(
            get_output("../data/test.txt")
                .unwrap()
                .collect::<Vec<u32>>(),
            output
        );
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(
            get_collection("../data/test.txt", 1)
                .unwrap()
                .collect::<Vec<u32>>(),
            output
        );
    }

    fn merge<'a, T: 'a + FromStr + PartialOrd>(
        filename: &str,
    ) -> (impl 'a + Iterator<Item = T>, impl Iterator<Item = T>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator<T: PartialEq>(
        iter1: &mut impl Iterator<Item = T>,
        iter2: &mut impl Iterator<Item = T>,
    ) -> bool {
        loop {
            match (iter1.next(), iter2.next()) {
                (None, None) => return true,
                (Some(v1), Some(v2)) if v1 == v2 => continue,
                _ => return false,
            }
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge::<u32>(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge::<u32>(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge::<u32>(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge::<u32>(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<commit_msg>do no use unwrap<commit_after>use regex::Regex;
use std::fs::File;
use std::io::{self, BufRead};
use std::str::FromStr;

#[macro_use]
extern crate lazy_static;
extern crate if_chain;

struct State<'a, T>(Box<dyn 'a + Iterator<Item = T>>, Option<T>);

pub struct Merge<'a, T> {
    count: usize,
    states: Vec<State<'a, T>>,
}

impl<'a, T: 'a + FromStr> Merge<'a, T> {
    pub fn new(filename: &str) -> Self {
        let count = get_number(filename).unwrap();
        let states = (0..count)
            .map(|i| {
                let collection = Box::new(get_collection(filename, i).unwrap());
                State(collection, None)
            })
            .collect();
        Merge {
            count: count,
            states: states,
        }
    }
}

impl<'a, T: PartialOrd> Iterator for Merge<'a, T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let count = self.count;
        let states = &mut self.states;
        for i in 0..count {
            let state = &mut states[i];
            if state.1.is_none() {
                state.1 = state.0.next();
            }
        }
        let mut min_index: Option<usize> = None;
        for i in 0..count {
            if_chain::if_chain! {
                if let Some(_) = states[i].1.as_ref();
                if min_index.is_none();
                then {
                    min_index.replace(i);
                }
            }
            if_chain::if_chain! {
                if let Some(val) = states[i].1.as_ref();
                if let Some(m) = min_index;
                if let Some(min) = states[m].1.as_ref();
                if val < min;
                then {
                    min_index.replace(i);
                }
            }
        }
        if let Some(m) = min_index {
            return states[m].1.take();
        }
        return None;
    }
}

pub fn get_number(filename: &str) -> io::Result<usize> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"NUMBER=(\d+)").unwrap();
    }
    let mut matches = match_lines(filename, &*RE)?;
    if_chain::if_chain! {
        if let Some(m) = matches.next();
        if let Ok(number) = m.parse();
        then {
            Ok(number)
        }
        else {
            Err(io::Error::new(io::ErrorKind::Other, "oh no!"))
        }
    }
}

pub fn get_output<T: FromStr>(filename: &str) -> io::Result<impl Iterator<Item = T>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"OUTPUT:(.*)").unwrap();
    }
    get_numbers(filename, &*RE)
}

pub fn get_collection<T: FromStr>(
    filename: &str,
    idx: usize,
) -> io::Result<impl Iterator<Item = T>> {
    let regex: Regex = {
        let r = format!("COLLECTION{}:(.*)", idx);
        Regex::new(&r).unwrap()
    };
    get_numbers(filename, &regex)
}

fn get_numbers<T: FromStr>(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = T>> {
    let matches = match_lines(filename, regex)?;
    let to_int = |v: &str| -> Option<T> {
        if let Ok(i) = v.parse::<T>() {
            Some(i)
        } else {
            None
        }
    };
    let values = matches
        .map(move |s| {
            let numbers = s.split(',').filter_map(|v| to_int(&v));
            numbers.collect::<Vec<_>>()
        })
        .flatten();
    Ok(values)
}

fn match_lines(filename: &str, regex: &Regex) -> io::Result<impl Iterator<Item = String>> {
    let read_lines = move || -> io::Result<_> {
        let file = File::open(filename)?;
        Ok(io::BufReader::new(file).lines().map(|line| line.unwrap()))
    };
    let lines = read_lines()?;
    let r = regex.clone(); // TODO
    let matches =
        lines.filter_map(move |line| r.captures(&line).map(|captures| captures[1].to_string()));
    Ok(matches)
}

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

    #[test]
    fn test_number() {
        assert_eq!(get_number("../data/test.txt").unwrap(), 3);
    }

    #[test]
    fn test_output() {
        let output = [1, 1, 2, 2, 3, 4, 4, 6, 7, 9, 9, 20, 21];
        assert_eq!(
            get_output("../data/test.txt")
                .unwrap()
                .collect::<Vec<u32>>(),
            output
        );
    }

    #[test]
    fn test_collection() {
        let output = [2, 4, 6, 9, 20];
        assert_eq!(
            get_collection("../data/test.txt", 1)
                .unwrap()
                .collect::<Vec<u32>>(),
            output
        );
    }

    fn merge<'a, T: 'a + FromStr + PartialOrd>(
        filename: &str,
    ) -> (impl 'a + Iterator<Item = T>, impl Iterator<Item = T>) {
        let result = Merge::new(filename);
        let output = get_output(filename).unwrap();
        (result, output)
    }

    fn assert_iterator<T: PartialEq>(
        iter1: &mut impl Iterator<Item = T>,
        iter2: &mut impl Iterator<Item = T>,
    ) -> bool {
        loop {
            match (iter1.next(), iter2.next()) {
                (None, None) => return true,
                (Some(v1), Some(v2)) if v1 == v2 => continue,
                _ => return false,
            }
        }
    }

    #[test]
    fn test_merge() {
        let filename = "../data/test.txt";
        let (mut result, mut output) = merge::<u32>(filename);
        assert!(assert_iterator(&mut result, &mut output));
    }

    #[test]
    #[should_panic]
    fn test_bad_merge() {
        let filename = "../data/bad.txt";
        let (_result, _output) = merge::<u32>(filename);
    }

    #[test]
    fn test_zero_merge() {
        let filename = "../data/zero.txt";
        let (mut result, mut output) = merge::<u32>(filename);
        assert!(result.next().is_none());
        assert!(output.next().is_none());
    }

    #[test]
    fn test_err() {
        let filename = "../data/err.txt";
        let (mut result, mut output) = merge::<u32>(filename);
        assert!(!assert_iterator(&mut result, &mut output));
    }
}
<|endoftext|>