<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 an iterator to the current state of the cache in lifo order (top to bottom).
    #[allow(dead_code)]
    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.cache.iter().rev()
    }

    /// 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 iter() {
        let mut stack = Stack::new();

        stack.push(0);
        stack.push(1);
        stack.push(2);

        assert_eq!(stack.iter().collect::<Vec<&i32>>(), vec![&2, &1, &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>Style<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 an iterator to the current state of the cache in lifo order (top to bottom).
    #[allow(dead_code)]
    pub fn iter(&self) -> impl Iterator<Item = &T> {
        self.cache.iter().rev()
    }

    /// 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 iter() {
        let mut stack = Stack::new();

        stack.push(0);
        stack.push(1);
        stack.push(2);

        assert_eq!(stack.iter().collect::<Vec<&i32>>(), vec![&2, &1, &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>use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::Path;
use log;
use serde_json;
use directives;
use highlighter::{self, SyntaxHighlighter};
use markdown;
use parse::{Parser, Node, NodeValue};

pub struct Evaluator {
    directives: HashMap<String, Box<directives::DirectiveHandler>>,
    pub parser: RefCell<Parser>,
    pub markdown: markdown::MarkdownRenderer,
    pub highlighter: SyntaxHighlighter,

    pub variable_stack: RefCell<Vec<(String, String)>>,
    pub ctx: RefCell<HashMap<String, NodeValue>>,
    pub theme_config: RefCell<serde_json::map::Map<String, serde_json::Value>>,
}

impl Evaluator {
    #[allow(dead_code)]
    pub fn new() -> Self {
        Self::new_with_options(highlighter::DEFAULT_SYNTAX_THEME)
    }

    pub fn new_with_options(syntax_theme: &str) -> Self {
        Evaluator {
            directives: HashMap::new(),
            parser: RefCell::new(Parser::new()),
            markdown: markdown::MarkdownRenderer::new(),
            highlighter: SyntaxHighlighter::new(syntax_theme),
            variable_stack: RefCell::new(vec![]),
            ctx: RefCell::new(HashMap::new()),
            theme_config: RefCell::new(serde_json::map::Map::new()),
        }
    }

    pub fn register<S: Into<String>>(&mut self,
                                     name: S,
                                     handler: Box<directives::DirectiveHandler>) {
        self.directives.insert(name.into(), handler);
    }

    pub fn evaluate(&self, node: &Node) -> String {
        match node.value {
            NodeValue::Owned(ref s) => s.to_owned(),
            NodeValue::Children(ref children) => {
                if let Some(first_element) = children.get(0) {
                    let directive_name = match first_element.value {
                        NodeValue::Owned(ref dname) => Cow::Borrowed(dname),
                        NodeValue::Children(_) => Cow::Owned(self.evaluate(first_element)),
                    };

                    self.lookup(node, directive_name.as_ref(), &children[1..])
                        .unwrap_or_else(|_| "".to_owned())
                } else {
                    println!("Empty node");
                    "".to_owned()
                }
            }
        }
    }

    pub fn log(&self, node: &Node, message: &str, level: log::LogLevel) {
        let parser = self.parser.borrow();
        let file_path = parser.get_node_source_path(node);
        log!(level,
             "{}\n  --> {}:?:?",
             message,
             file_path.unwrap_or_else(|| Path::new("")).to_string_lossy());
    }

    #[allow(dead_code)]
    pub fn warn(&self, node: &Node, message: &str) {
        self.log(node, message, log::LogLevel::Warn);
    }

    pub fn error(&self, node: &Node, message: &str) {
        self.log(node, message, log::LogLevel::Error);
    }

    pub fn reset(&self) {
        self.ctx.borrow_mut().clear();
        self.theme_config.borrow_mut().clear();
    }

    fn lookup(&self, node: &Node, key: &str, args: &[Node]) -> Result<String, ()> {
        let var = self.variable_stack
            .borrow()
            .iter()
            .rev()
            .find(|&&(ref k, _)| k == key)
            .map(|&(_, ref v)| v.to_owned());

        if let Some(value) = var {
            if !args.is_empty() {
                return Err(());
            }

            return Ok(value.to_owned());
        }

        if let Some(handler) = self.directives.get(key) {
            return match handler.handle(self, args) {
                       Ok(result) => Ok(result),
                       Err(_) => {
                           self.error(node, &format!("Error in directive {}", key));
                           Err(())
                       }
                   };
        }

        self.error(node, &format!("Unknown directive {}", key));
        Err(())
    }
}
<commit_msg>Reset variable stack at the end of evaluation<commit_after>use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::Path;
use log;
use serde_json;
use directives;
use highlighter::{self, SyntaxHighlighter};
use markdown;
use parse::{Parser, Node, NodeValue};

pub struct Evaluator {
    directives: HashMap<String, Box<directives::DirectiveHandler>>,
    pub parser: RefCell<Parser>,
    pub markdown: markdown::MarkdownRenderer,
    pub highlighter: SyntaxHighlighter,

    pub variable_stack: RefCell<Vec<(String, String)>>,
    pub ctx: RefCell<HashMap<String, NodeValue>>,
    pub theme_config: RefCell<serde_json::map::Map<String, serde_json::Value>>,
}

impl Evaluator {
    #[allow(dead_code)]
    pub fn new() -> Self {
        Self::new_with_options(highlighter::DEFAULT_SYNTAX_THEME)
    }

    pub fn new_with_options(syntax_theme: &str) -> Self {
        Evaluator {
            directives: HashMap::new(),
            parser: RefCell::new(Parser::new()),
            markdown: markdown::MarkdownRenderer::new(),
            highlighter: SyntaxHighlighter::new(syntax_theme),
            variable_stack: RefCell::new(vec![]),
            ctx: RefCell::new(HashMap::new()),
            theme_config: RefCell::new(serde_json::map::Map::new()),
        }
    }

    pub fn register<S: Into<String>>(&mut self,
                                     name: S,
                                     handler: Box<directives::DirectiveHandler>) {
        self.directives.insert(name.into(), handler);
    }

    pub fn evaluate(&self, node: &Node) -> String {
        match node.value {
            NodeValue::Owned(ref s) => s.to_owned(),
            NodeValue::Children(ref children) => {
                if let Some(first_element) = children.get(0) {
                    let directive_name = match first_element.value {
                        NodeValue::Owned(ref dname) => Cow::Borrowed(dname),
                        NodeValue::Children(_) => Cow::Owned(self.evaluate(first_element)),
                    };

                    self.lookup(node, directive_name.as_ref(), &children[1..])
                        .unwrap_or_else(|_| "".to_owned())
                } else {
                    println!("Empty node");
                    "".to_owned()
                }
            }
        }
    }

    pub fn log(&self, node: &Node, message: &str, level: log::LogLevel) {
        let parser = self.parser.borrow();
        let file_path = parser.get_node_source_path(node);
        log!(level,
             "{}\n  --> {}:?:?",
             message,
             file_path.unwrap_or_else(|| Path::new("")).to_string_lossy());
    }

    #[allow(dead_code)]
    pub fn warn(&self, node: &Node, message: &str) {
        self.log(node, message, log::LogLevel::Warn);
    }

    pub fn error(&self, node: &Node, message: &str) {
        self.log(node, message, log::LogLevel::Error);
    }

    pub fn reset(&self) {
        self.ctx.borrow_mut().clear();
        self.theme_config.borrow_mut().clear();
        self.variable_stack.borrow_mut().clear();
    }

    fn lookup(&self, node: &Node, key: &str, args: &[Node]) -> Result<String, ()> {
        let var = self.variable_stack
            .borrow()
            .iter()
            .rev()
            .find(|&&(ref k, _)| k == key)
            .map(|&(_, ref v)| v.to_owned());

        if let Some(value) = var {
            if !args.is_empty() {
                return Err(());
            }

            return Ok(value.to_owned());
        }

        if let Some(handler) = self.directives.get(key) {
            return match handler.handle(self, args) {
                       Ok(result) => Ok(result),
                       Err(_) => {
                           self.error(node, &format!("Error in directive {}", key));
                           Err(())
                       }
                   };
        }

        self.error(node, &format!("Unknown directive {}", key));
        Err(())
    }
}
<|endoftext|>


<commit_before>use syntax::ast;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;

use block::{Block, Describe, It, Bench};

pub trait Generate {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item>;
}

impl Generate for Block {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        match self {
            Block::Describe(describe) => describe.generate(cx, up),
            Block::It(it) => it.generate(cx, up),
            Block::Bench(bench) => bench.generate(cx, up)
        }
    }
}

impl Generate for Describe {
    fn generate(mut self,
                cx: &mut ExtCtxt,
                up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        if let Some(ref up) = up {
            self.before = up.before.iter()
                .chain(self.before.iter())
                .cloned()
                .collect();
            self.after = self.after.iter()
                .chain(up.after.iter())
                .cloned()
                .collect();
        }

        let mut items = self.blocks.iter().map(|block| {
            block.clone().generate(cx, Some(&self))
        }).collect::<Vec<_>>();

        items.push(quote_item!(cx, pub use super::*;).unwrap());

        quote_item!(cx, mod $name { $items }).unwrap()
    }
}

impl Generate for It {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        let block = if let Some(ref up) = up {
            up.before.iter()
                .chain(Some(self.block).iter())
                .chain(up.after.iter())
                .cloned().collect()
        } else {
            vec![self.block]
        };

        let mut block = block.into_iter();
        let head = block.next().unwrap();
        let block = block.fold(head, merge_blocks);

        quote_item!(cx, #[test] fn $name() { $block }).unwrap()
    }
}

impl Generate for Bench {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        let block = if let Some(ref up) = up {
            up.before.iter()
                .chain(Some(self.block).iter())
                .chain(up.after.iter())
                .cloned().collect()
        } else {
            vec![self.block]
        };

        let mut block = block.into_iter();
        let head = block.next().unwrap();
        let block = block.fold(head, merge_blocks);

        let ident = self.ident;
        quote_item!(cx, #[bench] fn $name($ident: &mut ::test::Bencher) {
            $block
        }).unwrap()
    }
}

fn merge_blocks(left: P<ast::Block>, right: P<ast::Block>) -> P<ast::Block> {
    let mut stmts = left.stmts.clone();
    stmts.extend(right.stmts.clone());

    P(ast::Block {
        stmts: stmts,
        ..(*left).clone()
    })
}
<commit_msg>Refactor a `merge_blocks` using iterators.<commit_after>use syntax::ast;
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;

use block::{Block, Describe, It, Bench};

pub trait Generate {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item>;
}

impl Generate for Block {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        match self {
            Block::Describe(describe) => describe.generate(cx, up),
            Block::It(it) => it.generate(cx, up),
            Block::Bench(bench) => bench.generate(cx, up)
        }
    }
}

impl Generate for Describe {
    fn generate(mut self,
                cx: &mut ExtCtxt,
                up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        if let Some(ref up) = up {
            self.before = up.before.iter()
                .chain(self.before.iter())
                .cloned()
                .collect();
            self.after = self.after.iter()
                .chain(up.after.iter())
                .cloned()
                .collect();
        }

        let mut items = self.blocks.iter().map(|block| {
            block.clone().generate(cx, Some(&self))
        }).collect::<Vec<_>>();

        items.push(quote_item!(cx, pub use super::*;).unwrap());

        quote_item!(cx, mod $name { $items }).unwrap()
    }
}

impl Generate for It {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        let block = if let Some(ref up) = up {
            up.before.iter()
                .chain(Some(self.block).iter())
                .chain(up.after.iter())
                .cloned().collect()
        } else {
            vec![self.block]
        };

        let mut block = block.into_iter();
        let head = block.next().unwrap();
        let block = block.fold(head, merge_blocks);

        quote_item!(cx, #[test] fn $name() { $block }).unwrap()
    }
}

impl Generate for Bench {
    fn generate(self, cx: &mut ExtCtxt, up: Option<&Describe>) -> P<ast::Item> {
        let name = cx.ident_of(&self.name);

        let block = if let Some(ref up) = up {
            up.before.iter()
                .chain(Some(self.block).iter())
                .chain(up.after.iter())
                .cloned().collect()
        } else {
            vec![self.block]
        };

        let mut block = block.into_iter();
        let head = block.next().unwrap();
        let block = block.fold(head, merge_blocks);

        let ident = self.ident;
        quote_item!(cx, #[bench] fn $name($ident: &mut ::test::Bencher) {
            $block
        }).unwrap()
    }
}

fn merge_blocks(left: P<ast::Block>, right: P<ast::Block>) -> P<ast::Block> {
    P(ast::Block {
        stmts: left.stmts.iter().chain(right.stmts.iter()).cloned().collect(),
        ..(*left).clone()
    })
}
<|endoftext|>


<commit_before>use std::iter::repeat;
use std::ops::{Index, RangeFull};
use std::fmt::Debug;

use super::point::Point;
use super::number::NumberOps;

#[derive(Debug)]
pub struct Ring<T> {
   v: Vec<T>,
   start: usize,
   end: usize,
}

impl<T> Ring<T> where T: Default + Clone + Debug {
   #[inline]
   pub fn new(capacity: usize) -> Self {
      let v = repeat(T::default()).take(capacity).collect();

      Ring { v: v, start: 0, end: 0 }
   }

   #[inline]
   pub fn len(&self) -> usize {
      self.end - self.start
   }

   #[inline]
   pub fn last(&self) -> Option<&T> {
      self.v.last()
   }

   #[inline]
   pub fn start(&self) -> usize {
      self.start
   }

   #[inline]
   pub fn end(&self) -> usize {
      self.end
   }

   #[inline]
   pub fn consume(&mut self, marker: usize) {
      self.start = marker;
   }

   #[inline]
   pub fn reserve(&mut self, additional: usize) {
      self.v.reserve(additional);
   }

   #[inline]
   pub fn check_rewind(&mut self, extra: usize) {
      if extra > (self.v.len() - self.end) {
         if self.start != self.end {
            for i in 0..(self.end - self.start) {
               self.v[i] = self.v[self.start + i].clone();
            }
         }

         self.end -= self.start;
         self.start = 0;
      }
   }

   #[inline]
   pub fn push(&mut self, value: T) {
      self.v[self.end] = value;
      self.end += 1;
   }
}

impl<T> Index<usize> for Ring<T> {
   type Output = T;

   #[inline]
   fn index(&self, index: usize) -> &T {
      &self.v[index]
   }
}

impl<T> Index<RangeFull> for Ring<T> {
   type Output = [T];

   #[inline]
   fn index(&self, _index: RangeFull) -> &[T] {
      &self.v[self.start..self.end]
   }
}

#[inline]
pub fn h_down_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y > y {
      if p1.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y > y && p2.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_up_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y < y {
      if p1.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y < y && p2.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_left_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x > x {
      if p1.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x > x && p2.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_right_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x < x {
      if p1.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x < x && p2.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_intersect(y: i64, p1: Point, p2: Point) -> i64 {
   p1.x + ((p2.x - p1.x) * (y - p1.y)).rounding_div(p2.y - p1.y)
}

#[inline]
pub fn v_intersect(x: i64, p1: Point, p2: Point) -> i64 {
   p1.y + ((p2.y - p1.y) * (x - p1.x)).rounding_div(p2.x - p1.x)
}

pub fn hv_clip<F>(intersect: F, y: i64, points: &mut Ring<Point>) where
   F: Fn(i64, Point, Point, &mut Ring<Point>),
{
   let start = points.start();
   let end = points.end();

   points.check_rewind(2 * (end - start));

   let rewinded_end = points.end();

   let mut p1 = points[end-1];

   for i in start..end {
      let p2 = points[i];

      intersect(y, p1, p2, points);

      p1 = p2;
   }

   points.consume(rewinded_end);
}

pub fn h_split(y: i64, start: usize, down: &mut Vec<Point>, up: &mut Vec<Point>) {
   let end = up.len();

   assert!(end - start > 2);

   let mut p1 = up[end-1];

   for i in start..end {
      let p2 = up[i];

      h_split_edge(y, p1, p2, down, up);

      p1 = p2;
   }
}

pub fn v_split(x: i64, start: usize, left: &mut Vec<Point>, right: &mut Vec<Point>) {
   let end = right.len();

   assert!(end - start > 2);

   let mut p1 = right[end-1];

   for i in start..end {
      let p2 = right[i];

      v_split_edge(x, p1, p2, left, right);

      p1 = p2;
   }
}

#[inline]
pub fn h_split_edge(y: i64, p1: Point, p2: Point, down: &mut Vec<Point>, up: &mut Vec<Point>) {
   if p2.y > y {
      if p1.y < y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      up.push(p2);
   } else if p2.y < y {
      if p1.y > y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      down.push(p2);
   } else {
      down.push(p2);
      up.push(p2);
   }
}

#[inline]
pub fn v_split_edge(x: i64, p1: Point, p2: Point, left: &mut Vec<Point>, right: &mut Vec<Point>) {
   if p2.x > x {
      if p1.x < x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      right.push(p2);
   } else if p2.x < x {
      if p1.x > x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      left.push(p2);
   } else {
      left.push(p2);
      right.push(p2);
   }
}

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

   use super::super::point::Point;

   use super::*;

   #[bench]
   fn bench_clip(b: &mut Bencher) {
      b.iter(|| {
         for _ in 0..1000 {
            let mut points = Ring::new(30);

            points.push(Point::new(50, 50));
            points.push(Point::new(100, 200));
            points.push(Point::new(150, 100));

            hv_clip(h_down_intersect, 150, &mut points);

            hv_clip(h_up_intersect, 80, &mut points);

            hv_clip(v_right_intersect, 70, &mut points);

            hv_clip(v_left_intersect, 140, &mut points);
         }
      });
   }
/*
   #[test]
   fn test_clip() {
      let mut points = Ring::new(30);

      points.push(Point::new(50, 50));
      points.push(Point::new(100, 200));
      points.push(Point::new(150, 100));

      hv_clip(h_down_intersect, 150, &mut points);

      hv_clip(h_up_intersect, 80, &mut points);

      hv_clip(v_right_intersect, 70, &mut points);

      hv_clip(v_left_intersect, 140, &mut points);

      assert_eq!(points[..].len(), 7);

      assert_eq!(&points[..], [
         Point::new(140, 95),
         Point::new(110, 80),
         Point::new(70, 80),
         Point::new(70, 110),
         Point::new(83, 150),
         Point::new(125, 150),
         Point::new(140, 120),
      ]);
   }
*/
}
<commit_msg>Ring vec improvements and fixes, splitting using Ring instead of Vec<commit_after>use std::iter::repeat;
use std::ops::{Index, RangeFull};
use std::fmt::Debug;

use super::point::Point;
use super::number::NumberOps;

#[derive(Debug)]
pub struct Ring<T> {
   v: Vec<T>,
   start: usize,
   end: usize,
}

impl<T> Ring<T> where T: Default + Clone + Debug {
   #[inline]
   pub fn new(capacity: usize) -> Self {
      let v = repeat(T::default()).take(capacity).collect();

      Ring { v: v, start: 0, end: 0 }
   }

   #[inline]
   pub fn len(&self) -> usize {
      self.end - self.start
   }

   #[inline]
   pub fn last(&self) -> Option<&T> {
      if self.start == self.end {
         None
      } else {
         Some(unsafe {
            self.v.get_unchecked(self.end - 1)
         })
      }
   }

   #[inline]
   pub fn start(&self) -> usize {
      self.start
   }

   #[inline]
   pub fn end(&self) -> usize {
      self.end
   }

   #[inline]
   pub fn consume_at(&mut self, marker: usize) {
      self.start = marker;
   }

   #[inline]
   pub fn consume(&mut self) {
      self.start = self.end;
   }

   #[inline]
   pub fn reserve(&mut self, additional: usize) {
      self.v.reserve(additional);
   }

   #[inline]
   pub fn rewind(&mut self, extra: usize) {
      if extra > (self.v.len() - self.end) {
         if self.start != self.end {
            for i in 0..(self.end - self.start) {
               self.v[i] = self.v[self.start + i].clone();
            }
         }

         self.end -= self.start;
         self.start = 0;
      }
   }

   #[inline]
   pub fn push(&mut self, value: T) {
      self.v[self.end] = value;
      self.end += 1;
   }
}

impl<T> Index<usize> for Ring<T> {
   type Output = T;

   #[inline]
   fn index(&self, index: usize) -> &T {
      &self.v[index]
   }
}

impl<T> Index<RangeFull> for Ring<T> {
   type Output = [T];

   #[inline]
   fn index(&self, _index: RangeFull) -> &[T] {
      &self.v[self.start..self.end]
   }
}

#[inline]
pub fn h_down_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y > y {
      if p1.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y > y && p2.y < y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_up_intersect(y: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.y < y {
      if p1.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
   } else {
      if p1.y < y && p2.y > y {
         points.push(Point::new(h_intersect(y, p1, p2), y));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_left_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x > x {
      if p1.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x > x && p2.x < x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn v_right_intersect(x: i64, p1: Point, p2: Point, points: &mut Ring<Point>) {
   if p2.x < x {
      if p1.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
   } else {
      if p1.x < x && p2.x > x {
         points.push(Point::new(x, v_intersect(x, p1, p2)));
      }
      points.push(p2);
   }
}

#[inline]
pub fn h_intersect(y: i64, p1: Point, p2: Point) -> i64 {
   p1.x + ((p2.x - p1.x) * (y - p1.y)).rounding_div(p2.y - p1.y)
}

#[inline]
pub fn v_intersect(x: i64, p1: Point, p2: Point) -> i64 {
   p1.y + ((p2.y - p1.y) * (x - p1.x)).rounding_div(p2.x - p1.x)
}

pub fn hv_clip<F>(intersect: F, at: i64, points: &mut Ring<Point>) where
   F: Fn(i64, Point, Point, &mut Ring<Point>),
{
   let start = points.start();
   let end = points.end();

   points.rewind(2 * (end - start));

   let rewinded_end = points.end();

   let mut p1 = points[end-1];

   for i in start..end {
      let p2 = points[i];

      intersect(at, p1, p2, points);

      p1 = p2;
   }

   points.consume_at(rewinded_end);
}

pub fn hv_split<F>(split: F, at: i64, write: &mut Ring<Point>, read_write: &mut Ring<Point>) where
   F: Fn(i64, Point, Point, &mut Ring<Point>, &mut Ring<Point>),
{
   let start = read_write.start();
   let end = read_write.end();

   let double = 2 * (end - start);
   read_write.rewind(double);
   write.rewind(double);

   let rewinded_end = read_write.end();

   assert!(end - start > 2);

   let mut p1 = read_write[end-1];

   for i in start..end {
      let p2 = read_write[i];

      split(at, p1, p2, write, read_write);

      p1 = p2;
   }

   read_write.consume_at(rewinded_end);
}

#[inline]
pub fn h_split_edge(y: i64, p1: Point, p2: Point, down: &mut Ring<Point>, up: &mut Ring<Point>) {
   if p2.y > y {
      if p1.y < y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      up.push(p2);
   } else if p2.y < y {
      if p1.y > y {
         let intersection = Point::new(h_intersect(y, p1, p2), y);
         down.push(intersection);
         up.push(intersection);
      }
      down.push(p2);
   } else {
      down.push(p2);
      up.push(p2);
   }
}

#[inline]
pub fn v_split_edge(x: i64, p1: Point, p2: Point, left: &mut Ring<Point>, right: &mut Ring<Point>) {
   if p2.x > x {
      if p1.x < x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      right.push(p2);
   } else if p2.x < x {
      if p1.x > x {
         let intersection = Point::new(x, v_intersect(x, p1, p2));
         left.push(intersection);
         right.push(intersection);
      }
      left.push(p2);
   } else {
      left.push(p2);
      right.push(p2);
   }
}

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

   use super::super::point::Point;

   use super::*;

   #[bench]
   fn bench_clip(b: &mut Bencher) {
      let mut points = Ring::new(1024 * 256);

      b.iter(|| {
         for _ in 0..1000 {
            points.consume();

            points.push(Point::new(50, 50));
            points.push(Point::new(100, 200));
            points.push(Point::new(150, 100));

            hv_clip(h_down_intersect, 150, &mut points);

            hv_clip(h_up_intersect, 80, &mut points);

            hv_clip(v_right_intersect, 70, &mut points);

            hv_clip(v_left_intersect, 140, &mut points);
         }
      });
   }

   #[test]
   fn test_clip() {
      let mut points = Ring::new(30);

      points.push(Point::new(50, 50));
      points.push(Point::new(100, 200));
      points.push(Point::new(150, 100));

      hv_clip(h_down_intersect, 150, &mut points);

      hv_clip(h_up_intersect, 80, &mut points);

      hv_clip(v_right_intersect, 70, &mut points);

      hv_clip(v_left_intersect, 140, &mut points);

      assert_eq!(points[..].len(), 7);

      assert_eq!(&points[..], [
         Point::new(140, 95),
         Point::new(110, 80),
         Point::new(70, 80),
         Point::new(70, 110),
         Point::new(83, 150),
         Point::new(125, 150),
         Point::new(140, 120),
      ]);
   }
}
<|endoftext|>


<commit_before>fn sort(word: &String) -> String {
    let mut sorted: Vec<char> = word.chars().collect();
    sorted.sort();
    let mut output = String::with_capacity(sorted.len());
    for c in sorted.iter() {
        output.push(*c);
    }
    output
}

pub fn anagrams_for<'a>(word: &str, inputs: &[&'a str]) -> Vec<&'a str> {
    let lower = word.to_lowercase();
    let sorted = sort(&lower);
    inputs.iter().filter(|input| {
        let input_lower = input.to_lowercase();
        lower != input_lower && sorted == sort(&input_lower)
    }).cloned().collect()
}
<commit_msg>anagram: Use collect<commit_after>fn sort(word: &String) -> String {
    let mut sorted: Vec<char> = word.chars().collect();
    sorted.sort();
    sorted.into_iter().collect()
}

pub fn anagrams_for<'a>(word: &str, inputs: &[&'a str]) -> Vec<&'a str> {
    let lower = word.to_lowercase();
    let sorted = sort(&lower);
    inputs.iter().filter(|input| {
        let input_lower = input.to_lowercase();
        lower != input_lower && sorted == sort(&input_lower)
    }).cloned().collect()
}
<|endoftext|>


<commit_before>extern crate serde_json;

use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

#[derive(Serialize, Deserialize, Debug)]
pub struct GistFile {
    #[serde(skip_serializing, default = "GistFile::default_name")] pub name: String,

    #[serde(rename(serialize = "content"))] pub content: String,
}

impl GistFile {
    pub fn new(name: String) -> GistFile {
        GistFile {
            name: name,
            content: String::new(),
        }
    }

    pub fn default_name() -> String {
        "content".to_string()
    }

    // Read standard input to content buffer.
    pub fn read_stdin(&mut self) -> io::Result<()> {
        try!(io::stdin().read_to_string(&mut self.content));
        Ok(())
    }

    // Read file to content buffer.
    pub fn read_file(&mut self) -> io::Result<()> {
        let path = Path::new(&self.name);
        let mut fh = try!(File::open(&path));

        try!(fh.read_to_string(&mut self.content));
        Ok(())
    }
}

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

    #[test]
    fn read_invalid_file() {
        let mut f = GistFile::new("/not/found.txt".to_string());
        assert!(f.read_file().is_err());
    }

    #[test]
    fn read_valid_file() {
        let mut f = GistFile::new("Cargo.toml".to_string());
        assert!(f.read_file().is_ok());
    }
}
<commit_msg>There is no try! cleanup :)<commit_after>extern crate serde_json;

use std::fs::File;
use std::io::{self, Read};
use std::path::Path;

#[derive(Serialize, Deserialize, Debug)]
pub struct GistFile {
    #[serde(skip_serializing, default = "GistFile::default_name")] pub name: String,
    #[serde(rename(serialize = "content"))] pub content: String,
}

impl GistFile {
    pub fn new(name: String) -> GistFile {
        GistFile {
            name: name,
            content: String::new(),
        }
    }

    pub fn default_name() -> String {
        String::from("content")
    }

    // Read standard input to content buffer.
    pub fn read_stdin(&mut self) -> io::Result<usize> {
        io::stdin().read_to_string(&mut self.content)
    }

    // Read file to content buffer.
    pub fn read_file(&mut self) -> io::Result<usize> {
        let path = Path::new(&self.name);
        let mut fh = File::open(&path)?;
        fh.read_to_string(&mut self.content)
    }
}

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

    #[test]
    fn read_invalid_file() {
        let mut f = GistFile::new(String::from("/not/found.txt"));
        assert!(f.read_file().is_err());
    }

    #[test]
    fn read_valid_file() {
        let mut f = GistFile::new(String::from("Cargo.toml"));
        assert!(f.read_file().is_ok());
    }
}
<|endoftext|>


<commit_before>use diesel::prelude::*;
use diesel::sql_query;

cfg_if! {
    if #[cfg(feature = "sqlite")] {
        pub type TestConnection = SqliteConnection;

        pub fn connection() -> TestConnection {
            let mut conn = SqliteConnection::establish(":memory:").unwrap();
            sql_query("CREATE TABLE users (\
                id INTEGER PRIMARY KEY AUTOINCREMENT, \
                name VARCHAR NOT NULL, \
                hair_color VARCHAR DEFAULT 'Green')")
                .execute(&mut conn)
                .unwrap();
            conn
        }
    } else if #[cfg(feature = "postgres")] {
        extern crate dotenv;

        pub type TestConnection = PgConnection;

        pub fn connection() -> TestConnection {
            let database_url = dotenv::var("PG_DATABASE_URL")
                .or_else(|_| dotenv::var("DATABASE_URL"))
                .expect("DATABASE_URL must be set in order to run tests");
            let mut conn = PgConnection::establish(&database_url).unwrap();
            conn.begin_test_transaction().unwrap();
            sql_query("DROP TABLE IF EXISTS users CASCADE").execute(conn).unwrap();
            sql_query("CREATE TABLE users (\
                id SERIAL PRIMARY KEY, \
                name VARCHAR NOT NULL, \
                hair_color VARCHAR DEFAULT 'Green')")
                .execute(&mut conn)
                .unwrap();
            conn
        }
    } else if #[cfg(feature = "mysql")] {
        extern crate dotenv;

        pub type TestConnection = MysqlConnection;

        pub fn connection() -> TestConnection {
            let database_url = dotenv::var("MYSQL_UNIT_TEST_DATABASE_URL")
                .or_else(|_| dotenv::var("DATABASE_URL"))
                .expect("DATABASE_URL must be set in order to run tests");
            let mut conn = MysqlConnection::establish(&database_url).unwrap();
            sql_query("DROP TABLE IF EXISTS users CASCADE").execute(conn).unwrap();
            sql_query("CREATE TABLE users (\
                id INTEGER PRIMARY KEY AUTO_INCREMENT, \
                name TEXT NOT NULL, \
                hair_color VARCHAR(255) DEFAULT 'Green')")
                .execute(&mut conn)
                .unwrap();
            conn.begin_test_transaction().unwrap();
            conn
        }
    } else {
        compile_error!(
            "At least one backend must be used to test this crate.\n \
            Pass argument `--features \"<backend>\"` with one or more of the following backends, \
            'mysql', 'postgres', or 'sqlite'. \n\n \
            ex. cargo test --features \"mysql postgres sqlite\"\n"
        );
     }
}

pub fn connection_with_sean_and_tess_in_users_table() -> TestConnection {
    use schema::users::dsl::*;

    let mut connection = connection();
    ::diesel::insert_into(users)
        .values(&vec![
            (id.eq(1), name.eq("Sean"), hair_color.eq("black")),
            (id.eq(2), name.eq("Tess"), hair_color.eq("brown")),
        ])
        .execute(&mut connection)
        .unwrap();
    connection
}
<commit_msg>Fix error in diesel_derives<commit_after>use diesel::prelude::*;
use diesel::sql_query;

cfg_if! {
    if #[cfg(feature = "sqlite")] {
        pub type TestConnection = SqliteConnection;

        pub fn connection() -> TestConnection {
            let mut conn = SqliteConnection::establish(":memory:").unwrap();
            sql_query("CREATE TABLE users (\
                id INTEGER PRIMARY KEY AUTOINCREMENT, \
                name VARCHAR NOT NULL, \
                hair_color VARCHAR DEFAULT 'Green')")
                .execute(&mut conn)
                .unwrap();
            conn
        }
    } else if #[cfg(feature = "postgres")] {
        extern crate dotenv;

        pub type TestConnection = PgConnection;

        pub fn connection() -> TestConnection {
            let database_url = dotenv::var("PG_DATABASE_URL")
                .or_else(|_| dotenv::var("DATABASE_URL"))
                .expect("DATABASE_URL must be set in order to run tests");
            let mut conn = PgConnection::establish(&database_url).unwrap();
            conn.begin_test_transaction().unwrap();
            sql_query("DROP TABLE IF EXISTS users CASCADE").execute(&mut conn).unwrap();
            sql_query("CREATE TABLE users (\
                id SERIAL PRIMARY KEY, \
                name VARCHAR NOT NULL, \
                hair_color VARCHAR DEFAULT 'Green')")
                .execute(&mut conn)
                .unwrap();
            conn
        }
    } else if #[cfg(feature = "mysql")] {
        extern crate dotenv;

        pub type TestConnection = MysqlConnection;

        pub fn connection() -> TestConnection {
            let database_url = dotenv::var("MYSQL_UNIT_TEST_DATABASE_URL")
                .or_else(|_| dotenv::var("DATABASE_URL"))
                .expect("DATABASE_URL must be set in order to run tests");
            let mut conn = MysqlConnection::establish(&database_url).unwrap();
            sql_query("DROP TABLE IF EXISTS users CASCADE").execute(&mut conn).unwrap();
            sql_query("CREATE TABLE users (\
                id INTEGER PRIMARY KEY AUTO_INCREMENT, \
                name TEXT NOT NULL, \
                hair_color VARCHAR(255) DEFAULT 'Green')")
                .execute(&mut conn)
                .unwrap();
            conn.begin_test_transaction().unwrap();
            conn
        }
    } else {
        compile_error!(
            "At least one backend must be used to test this crate.\n \
            Pass argument `--features \"<backend>\"` with one or more of the following backends, \
            'mysql', 'postgres', or 'sqlite'. \n\n \
            ex. cargo test --features \"mysql postgres sqlite\"\n"
        );
     }
}

pub fn connection_with_sean_and_tess_in_users_table() -> TestConnection {
    use schema::users::dsl::*;

    let mut connection = connection();
    ::diesel::insert_into(users)
        .values(&vec![
            (id.eq(1), name.eq("Sean"), hair_color.eq("black")),
            (id.eq(2), name.eq("Tess"), hair_color.eq("brown")),
        ])
        .execute(&mut connection)
        .unwrap();
    connection
}
<|endoftext|>


<commit_before>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * io/reader.rs                                           *
 *                                                        *
 * hprose reader for Rust.                                *
 *                                                        *
 * LastModified: Sep 14, 2016                             *
 * Author: Chen Fei <cf@hprose.com>                       *
 *                                                        *
\**********************************************************/

extern crate test;

use super::tags::*;
use super::*;

use super::bool_decoder::bool_decode;
use super::i64_decoder::i64_decode;
use super::u64_decoder::u64_decode;

use std::fmt;
use std::io;
use std::f64;

#[derive(Clone, PartialEq, Debug)]
pub enum ParserError {
    IoError(io::ErrorKind, String),
}

#[derive(Clone, PartialEq, Debug)]
pub enum DecoderError {
    ParserError(ParserError),
    CastError(&'static str, &'static str),
    UnexpectedTag(u8, Option<Bytes>)
}

impl fmt::Display for DecoderError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DecoderError::CastError(srcType, dst_type) => write!(f, "can't convert {} to {}", srcType, dst_type),
            DecoderError::UnexpectedTag(tag, ref expect_tags_option) => {
                match *expect_tags_option {
                    // todo: format tag as 'c'(0xdd)
                    Some(ref expect_tags) => write!(f, "Tag '{:?}' expected, but '{}' found in stream", expect_tags, tag),
                    None => write!(f, "Unexpected serialize tag '{}' in stream", tag)
                }
            },
            _ => fmt::Debug::fmt(self, f)
        }
    }
}

pub type DecodeResult<T> = Result<T, DecoderError>;

pub struct Reader<'a> {
    buf: &'a Bytes,
    off: usize
}

pub trait ByteReader {
    fn read_byte(&mut self) -> Result<u8, ParserError>;
    fn read_i64_with_tag(&mut self, tag: u8) -> Result<i64, ParserError>;
    fn read_i64(&mut self) -> Result<i64, ParserError>;
    fn read_u64(&mut self) -> Result<i64, ParserError>;
    fn read_len(&mut self) -> Result<usize, ParserError>;
    fn read_until(&mut self, tag: u8) -> Result<&[u8], ParserError>;
    fn read_f32(&mut self) -> Result<f32, ParserError>;
    fn read_f64(&mut self) -> Result<f64, ParserError>;
    fn read_inf(&mut self) -> Result<f64, ParserError>;
}

impl<'a> Reader<'a> {
    #[inline]
    pub fn new(buf: &'a Bytes) -> Reader<'a> {
        Reader {
            buf: buf,
            off: 0
        }
    }

    #[inline]
    pub fn unserialize<T: Decodable>(&mut self) -> DecodeResult<T> {
        self.read()
    }

    #[inline]
    pub fn read<T: Decodable>(&mut self) -> DecodeResult<T> {
        Decodable::decode(self)
    }
}

#[inline]
fn io_error_to_error(io: io::Error) -> ParserError {
    ParserError::IoError(io.kind(), io.to_string())
}

impl<'a> ByteReader for Reader<'a> {
    fn read_byte(&mut self) -> Result<u8, ParserError> {
        if self.off >= self.buf.len() {
            return Err(io_error_to_error(io::Error::new(io::ErrorKind::UnexpectedEof, "")))
        }
        let b = self.buf[self.off];
        self.off += 1;
        return Ok(b)
    }

    fn read_i64_with_tag(&mut self, tag: u8) -> Result<i64, ParserError> {
        let mut i: i64 = 0;
        self.read_byte().and_then(|b| {
            if b == tag {
                Ok(i)
            } else {
                let mut neg = false;
                let next = match b {
                    TAG_NEG => {
                        neg = true;
                        self.read_byte()
                    },
                    TAG_POS => self.read_byte(),
                    _ => Ok(b)
                };
                if neg {
                    next.and_then(|mut b| {
                        while b != tag {
                            i = i * 10 - (b as i64 - b'0' as i64);
                            b = match self.read_byte() {
                                Ok(b) => b,
                                Err(e) => return Err(e)
                            }
                        }
                        Ok(i)
                    })
                } else {
                    next.and_then(|mut b| {
                        while b != tag {
                            i = i * 10 + (b as i64 - b'0' as i64);
                            b = match self.read_byte() {
                                Ok(b) => b,
                                Err(e) => return Err(e)
                            }
                        }
                        Ok(i)
                    })
                }
            }
        })
    }

    fn read_i64(&mut self) -> Result<i64, ParserError> {
        unimplemented!()
    }

    fn read_u64(&mut self) -> Result<i64, ParserError> {
        unimplemented!()
    }

    fn read_len(&mut self) -> Result<usize, ParserError> {
        unimplemented!()
    }

    fn read_until(&mut self, tag: u8) -> Result<&[u8], ParserError> {
        let result = &self.buf[self.off..];
        match result.iter().position(|x| *x == tag) {
            Some(idx) => {
                self.off += idx + 1;
                Ok(&result[..idx])
            },
            None => {
                self.off = self.buf.len();
                Err(io_error_to_error(io::Error::new(io::ErrorKind::UnexpectedEof, "")))
            }
        }
    }

    fn read_f32(&mut self) -> Result<f32, ParserError> {
        unimplemented!()
    }

    fn read_f64(&mut self) -> Result<f64, ParserError> {
        unimplemented!()
    }

    fn read_inf(&mut self) -> Result<f64, ParserError> {
        self.read_byte().and_then(|sign| Ok(if sign == TAG_POS { f64::INFINITY } else { f64::NEG_INFINITY }))
    }
}

impl<'a> Decoder for Reader<'a> {
    type Error = DecoderError;

    fn read_nil(&mut self) -> DecodeResult<()> {
        unimplemented!()
    }

    fn read_bool(&mut self) -> DecodeResult<bool> {
        self.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| bool_decode(self, t))
    }

    fn read_i64(&mut self) -> DecodeResult<i64> {
        self.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| i64_decode(self, t))
    }

    fn read_u64(&mut self) -> DecodeResult<u64> {
        self.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| u64_decode(self, t))
    }

    fn read_f32(&mut self) -> DecodeResult<f32> {
        unimplemented!()
    }

    fn read_f64(&mut self) -> DecodeResult<f64> {
        unimplemented!()
    }

    fn read_char(&mut self) -> DecodeResult<char> {
        unimplemented!()
    }

    fn read_string(&mut self) -> DecodeResult<String> {
        unimplemented!()
    }

    fn read_bytes(&mut self) -> DecodeResult<Bytes> {
        unimplemented!()
    }

    fn read_option<T, F>(&mut self, f: F) -> DecodeResult<T> where F: FnMut(&mut Self, bool) -> DecodeResult<T> {
        unimplemented!()
    }

    fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where F: FnOnce(&mut Self, usize) -> DecodeResult<T> {
        unimplemented!()
    }
}

pub fn tagToStr(tag: u8) -> Result<&'static str, DecoderError> {
    match tag {
        b'0'...b'9' | TAG_INTEGER => Ok("i32"),
        TAG_LONG => Ok("big int"),
        TAG_DOUBLE => Ok("f64"),
        TAG_NULL => Ok("nil"),
        TAG_EMPTY => Ok("empty string"),
        TAG_TRUE => Ok("true"),
        TAG_FALSE => Ok("false"),
        TAG_NAN => Ok("NaN"),
        TAG_INFINITY => Ok("Infinity"),
        TAG_DATE | TAG_TIME => Ok("time"),
        TAG_BYTES => Ok("bytes"),
        TAG_UTF8_CHAR | TAG_STRING => Ok("string"),
        TAG_GUID => Ok("GUID"),
        TAG_LIST => Ok("slice"),
        TAG_MAP => Ok("map"),
        TAG_CLASS | TAG_OBJECT => Ok("struct"),
        TAG_REF => Ok("reference"),
        _ => Err(DecoderError::UnexpectedTag(tag, None))
    }
}

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

    #[bench]
    fn benchmark_unserialize_bool(b: &mut Bencher) {
        let bytes = Writer::new(true).serialize(&true).bytes();
        b.iter(|| {
            Reader::new(&bytes).unserialize::<bool>().unwrap();
        });
    }
}
<commit_msg>Added unserialize i64 benchmark.<commit_after>/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * io/reader.rs                                           *
 *                                                        *
 * hprose reader for Rust.                                *
 *                                                        *
 * LastModified: Sep 14, 2016                             *
 * Author: Chen Fei <cf@hprose.com>                       *
 *                                                        *
\**********************************************************/

extern crate test;

use super::tags::*;
use super::*;

use super::bool_decoder::bool_decode;
use super::i64_decoder::i64_decode;
use super::u64_decoder::u64_decode;

use std::fmt;
use std::io;
use std::f64;

#[derive(Clone, PartialEq, Debug)]
pub enum ParserError {
    IoError(io::ErrorKind, String),
}

#[derive(Clone, PartialEq, Debug)]
pub enum DecoderError {
    ParserError(ParserError),
    CastError(&'static str, &'static str),
    UnexpectedTag(u8, Option<Bytes>)
}

impl fmt::Display for DecoderError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            DecoderError::CastError(srcType, dst_type) => write!(f, "can't convert {} to {}", srcType, dst_type),
            DecoderError::UnexpectedTag(tag, ref expect_tags_option) => {
                match *expect_tags_option {
                    // todo: format tag as 'c'(0xdd)
                    Some(ref expect_tags) => write!(f, "Tag '{:?}' expected, but '{}' found in stream", expect_tags, tag),
                    None => write!(f, "Unexpected serialize tag '{}' in stream", tag)
                }
            },
            _ => fmt::Debug::fmt(self, f)
        }
    }
}

pub type DecodeResult<T> = Result<T, DecoderError>;

pub struct Reader<'a> {
    buf: &'a Bytes,
    off: usize
}

pub trait ByteReader {
    fn read_byte(&mut self) -> Result<u8, ParserError>;
    fn read_i64_with_tag(&mut self, tag: u8) -> Result<i64, ParserError>;
    fn read_i64(&mut self) -> Result<i64, ParserError>;
    fn read_u64(&mut self) -> Result<i64, ParserError>;
    fn read_len(&mut self) -> Result<usize, ParserError>;
    fn read_until(&mut self, tag: u8) -> Result<&[u8], ParserError>;
    fn read_f32(&mut self) -> Result<f32, ParserError>;
    fn read_f64(&mut self) -> Result<f64, ParserError>;
    fn read_inf(&mut self) -> Result<f64, ParserError>;
}

impl<'a> Reader<'a> {
    #[inline]
    pub fn new(buf: &'a Bytes) -> Reader<'a> {
        Reader {
            buf: buf,
            off: 0
        }
    }

    #[inline]
    pub fn unserialize<T: Decodable>(&mut self) -> DecodeResult<T> {
        self.read()
    }

    #[inline]
    pub fn read<T: Decodable>(&mut self) -> DecodeResult<T> {
        Decodable::decode(self)
    }
}

#[inline]
fn io_error_to_error(io: io::Error) -> ParserError {
    ParserError::IoError(io.kind(), io.to_string())
}

impl<'a> ByteReader for Reader<'a> {
    fn read_byte(&mut self) -> Result<u8, ParserError> {
        if self.off >= self.buf.len() {
            return Err(io_error_to_error(io::Error::new(io::ErrorKind::UnexpectedEof, "")))
        }
        let b = self.buf[self.off];
        self.off += 1;
        return Ok(b)
    }

    fn read_i64_with_tag(&mut self, tag: u8) -> Result<i64, ParserError> {
        let mut i: i64 = 0;
        self.read_byte().and_then(|b| {
            if b == tag {
                Ok(i)
            } else {
                let mut neg = false;
                let next = match b {
                    TAG_NEG => {
                        neg = true;
                        self.read_byte()
                    },
                    TAG_POS => self.read_byte(),
                    _ => Ok(b)
                };
                if neg {
                    next.and_then(|mut b| {
                        while b != tag {
                            i = i * 10 - (b as i64 - b'0' as i64);
                            b = match self.read_byte() {
                                Ok(b) => b,
                                Err(e) => return Err(e)
                            }
                        }
                        Ok(i)
                    })
                } else {
                    next.and_then(|mut b| {
                        while b != tag {
                            i = i * 10 + (b as i64 - b'0' as i64);
                            b = match self.read_byte() {
                                Ok(b) => b,
                                Err(e) => return Err(e)
                            }
                        }
                        Ok(i)
                    })
                }
            }
        })
    }

    fn read_i64(&mut self) -> Result<i64, ParserError> {
        unimplemented!()
    }

    fn read_u64(&mut self) -> Result<i64, ParserError> {
        unimplemented!()
    }

    fn read_len(&mut self) -> Result<usize, ParserError> {
        unimplemented!()
    }

    fn read_until(&mut self, tag: u8) -> Result<&[u8], ParserError> {
        let result = &self.buf[self.off..];
        match result.iter().position(|x| *x == tag) {
            Some(idx) => {
                self.off += idx + 1;
                Ok(&result[..idx])
            },
            None => {
                self.off = self.buf.len();
                Err(io_error_to_error(io::Error::new(io::ErrorKind::UnexpectedEof, "")))
            }
        }
    }

    fn read_f32(&mut self) -> Result<f32, ParserError> {
        unimplemented!()
    }

    fn read_f64(&mut self) -> Result<f64, ParserError> {
        unimplemented!()
    }

    fn read_inf(&mut self) -> Result<f64, ParserError> {
        self.read_byte().and_then(|sign| Ok(if sign == TAG_POS { f64::INFINITY } else { f64::NEG_INFINITY }))
    }
}

impl<'a> Decoder for Reader<'a> {
    type Error = DecoderError;

    fn read_nil(&mut self) -> DecodeResult<()> {
        unimplemented!()
    }

    fn read_bool(&mut self) -> DecodeResult<bool> {
        self.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| bool_decode(self, t))
    }

    fn read_i64(&mut self) -> DecodeResult<i64> {
        self.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| i64_decode(self, t))
    }

    fn read_u64(&mut self) -> DecodeResult<u64> {
        self.read_byte().map_err(|e| DecoderError::ParserError(e)).and_then(|t| u64_decode(self, t))
    }

    fn read_f32(&mut self) -> DecodeResult<f32> {
        unimplemented!()
    }

    fn read_f64(&mut self) -> DecodeResult<f64> {
        unimplemented!()
    }

    fn read_char(&mut self) -> DecodeResult<char> {
        unimplemented!()
    }

    fn read_string(&mut self) -> DecodeResult<String> {
        unimplemented!()
    }

    fn read_bytes(&mut self) -> DecodeResult<Bytes> {
        unimplemented!()
    }

    fn read_option<T, F>(&mut self, f: F) -> DecodeResult<T> where F: FnMut(&mut Self, bool) -> DecodeResult<T> {
        unimplemented!()
    }

    fn read_seq<T, F>(&mut self, f: F) -> DecodeResult<T> where F: FnOnce(&mut Self, usize) -> DecodeResult<T> {
        unimplemented!()
    }
}

pub fn tagToStr(tag: u8) -> Result<&'static str, DecoderError> {
    match tag {
        b'0'...b'9' | TAG_INTEGER => Ok("i32"),
        TAG_LONG => Ok("big int"),
        TAG_DOUBLE => Ok("f64"),
        TAG_NULL => Ok("nil"),
        TAG_EMPTY => Ok("empty string"),
        TAG_TRUE => Ok("true"),
        TAG_FALSE => Ok("false"),
        TAG_NAN => Ok("NaN"),
        TAG_INFINITY => Ok("Infinity"),
        TAG_DATE | TAG_TIME => Ok("time"),
        TAG_BYTES => Ok("bytes"),
        TAG_UTF8_CHAR | TAG_STRING => Ok("string"),
        TAG_GUID => Ok("GUID"),
        TAG_LIST => Ok("slice"),
        TAG_MAP => Ok("map"),
        TAG_CLASS | TAG_OBJECT => Ok("struct"),
        TAG_REF => Ok("reference"),
        _ => Err(DecoderError::UnexpectedTag(tag, None))
    }
}

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

    #[bench]
    fn benchmark_unserialize_bool(b: &mut Bencher) {
        let bytes = Writer::new(true).serialize(&true).bytes();
        b.iter(|| {
            Reader::new(&bytes).unserialize::<bool>().unwrap();
        });
    }

    #[bench]
    fn benchmark_unserialize_i64(b: &mut Bencher) {
        let bytes = Writer::new(true).serialize(&12345).bytes();
        b.iter(|| {
            Reader::new(&bytes).unserialize::<i64>().unwrap();
        });
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{self, BufRead, BufReader, Cursor, Read, Seek, SeekFrom};
use std::path::Path;

use crate::dynimage::DynamicImage;
use crate::image::ImageFormat;
use crate::{ImageError, ImageResult};

use super::free_functions;

/// A multi-format image reader.
///
/// Wraps an input reader to facilitate automatic detection of an image's format, appropriate
/// decoding method, and dispatches into the set of supported [`ImageDecoder`] implementations.
///
/// ## Usage
///
/// Opening a file, deducing the format based on the file path automatically, and trying to decode
/// the image contained can be performed by constructing the reader and immediately consuming it.
///
/// ```no_run
/// # use image::ImageError;
/// # use image::io::Reader;
/// # fn main() -> Result<(), ImageError> {
/// let image = Reader::open("path/to/image.png")?
///     .decode()?;
/// # Ok(()) }
/// ```
///
/// It is also possible to make a guess based on the content. This is especially handy if the
/// source is some blob in memory and you have constructed the reader in another way. Here is an
/// example with a `pnm` black-and-white subformat that encodes its pixel matrix with ascii values.
///
#[cfg_attr(feature = "pnm", doc = "```")]
#[cfg_attr(not(feature = "pnm"), doc = "```no_run")]
/// # use image::ImageError;
/// # use image::io::Reader;
/// # fn main() -> Result<(), ImageError> {
/// use std::io::Cursor;
/// use image::ImageFormat;
///
/// let raw_data = b"P1 2 2\n\
///     0 1\n\
///     1 0\n";
///
/// let mut reader = Reader::new(Cursor::new(raw_data))
///     .with_guessed_format()
///     .expect("Cursor io never fails");
/// assert_eq!(reader.format(), Some(ImageFormat::Pnm));
///
/// let image = reader.decode()?;
/// # Ok(()) }
/// ```
///
/// As a final fallback or if only a specific format must be used, the reader always allows manual
/// specification of the supposed image format with [`set_format`].
///
/// [`set_format`]: #method.set_format
/// [`ImageDecoder`]: ../trait.ImageDecoder.html
pub struct Reader<R: Read> {
    /// The reader.
    inner: R,
    /// The format, if one has been set or deduced.
    format: Option<ImageFormat>,
}

impl<R: Read> Reader<R> {
    /// Create a new image reader without a preset format.
    ///
    /// It is possible to guess the format based on the content of the read object with
    /// [`guess_format`], or to set the format directly with [`set_format`].
    ///
    /// [`guess_format`]: #method.guess_format
    /// [`set_format`]: method.set_format
    pub fn new(reader: R) -> Self {
        Reader {
            inner: reader,
            format: None,
        }
    }

    /// Construct a reader with specified format.
    pub fn with_format(reader: R, format: ImageFormat) -> Self {
        Reader {
            inner: reader,
            format: Some(format),
        }
    }

    /// Get the currently determined format.
    pub fn format(&self) -> Option<ImageFormat> {
        self.format
    }

    /// Supply the format as which to interpret the read image.
    pub fn set_format(&mut self, format: ImageFormat) {
        self.format = Some(format);
    }

    /// Remove the current information on the image format.
    ///
    /// Note that many operations require format information to be present and will return e.g. an
    /// `ImageError::UnsupportedError` when the image format has not been set.
    pub fn clear_format(&mut self) {
        self.format = None;
    }

    /// Unwrap the reader.
    pub fn into_inner(self) -> R {
        self.inner
    }
}

impl Reader<BufReader<File>> {
    /// Open a file to read, format will be guessed from path.
    ///
    /// This will not attempt any io operation on the opened file.
    ///
    /// If you want to inspect the content for a better guess on the format, which does not depend
    /// on file extensions, follow this call with a call to [`guess_format`].
    ///
    /// [`guess_format`]: #method.guess_format
    pub fn open<P>(path: P) -> io::Result<Self> where P: AsRef<Path> {
        Self::open_impl(path.as_ref())
    }

    fn open_impl(path: &Path) -> io::Result<Self> {
        let file = File::open(path)?;
        Ok(Reader {
            inner: BufReader::new(file),
            format: ImageFormat::from_path(path).ok(),
        })
    }
}

impl<R: BufRead + Seek> Reader<R> {
    /// Make a format guess based on the content, replacing it on success.
    ///
    /// Returns `Ok` with the guess if no io error occurs. Additionally, replaces the current
    /// format if the guess was successful. If the guess was not unable to determine a format then
    /// the current format of the reader is unchanged.
    ///
    /// Returns an error if the underlying reader fails. The format is unchanged. The error is a
    /// `std::io::Error` and not `ImageError` since the only error case is an error when the
    /// underlying reader seeks.
    ///
    /// When an error occurs, the reader may not have been properly reset and it is potentially
    /// hazardous to continue with more io.
    ///
    /// ## Usage
    ///
    /// This supplements the path based type deduction from [`open`](Reader::open) with content based deduction.
    /// This is more common in Linux and UNIX operating systems and also helpful if the path can
    /// not be directly controlled.
    ///
    /// ```no_run
    /// # use image::ImageError;
    /// # use image::io::Reader;
    /// # fn main() -> Result<(), ImageError> {
    /// let image = Reader::open("image.unknown")?
    ///     .with_guessed_format()?
    ///     .decode()?;
    /// # Ok(()) }
    /// ```
    pub fn with_guessed_format(mut self) -> io::Result<Self> {
        let format = self.guess_format()?;
        // Replace format if found, keep current state if not.
        self.format = format.or(self.format);
        Ok(self)
    }

    fn guess_format(&mut self) -> io::Result<Option<ImageFormat>> {
        let mut start = [0; 16];

        // Save current offset, read start, restore offset.
        let cur = self.inner.seek(SeekFrom::Current(0))?;
        let len = io::copy(
            // Accept shorter files but read at most 16 bytes.
            &mut self.inner.by_ref().take(16),
            &mut Cursor::new(&mut start[..]))?;
        self.inner.seek(SeekFrom::Start(cur))?;

        Ok(free_functions::guess_format_impl(&start[..len as usize]))
    }

    /// Read the image dimensions.
    ///
    /// Uses the current format to construct the correct reader for the format.
    ///
    /// If no format was determined, returns an `ImageError::UnsupportedError`.
    pub fn into_dimensions(mut self) -> ImageResult<(u32, u32)> {
        let format = self.require_format()?;
        free_functions::image_dimensions_with_format_impl(self.inner, format)
    }

    /// Read the image (replaces `load`).
    ///
    /// Uses the current format to construct the correct reader for the format.
    ///
    /// If no format was determined, returns an `ImageError::UnsupportedError`.
    pub fn decode(mut self) -> ImageResult<DynamicImage> {
        let format = self.require_format()?;
        free_functions::load(self.inner, format)
    }

    fn require_format(&mut self) -> ImageResult<ImageFormat> {
        self.format.ok_or_else(||
            ImageError::UnsupportedError("Unable to determine image format".into()))
    }
}
<commit_msg>Remove (mentions of) legacy ImageError::UnsupportedError constructor/variant from io::Reader<commit_after>use std::fs::File;
use std::io::{self, BufRead, BufReader, Cursor, Read, Seek, SeekFrom};
use std::path::Path;

use crate::dynimage::DynamicImage;
use crate::image::ImageFormat;
use crate::error::{ImageFormatHint, UnsupportedError, UnsupportedErrorKind};
use crate::{ImageError, ImageResult};

use super::free_functions;

/// A multi-format image reader.
///
/// Wraps an input reader to facilitate automatic detection of an image's format, appropriate
/// decoding method, and dispatches into the set of supported [`ImageDecoder`] implementations.
///
/// ## Usage
///
/// Opening a file, deducing the format based on the file path automatically, and trying to decode
/// the image contained can be performed by constructing the reader and immediately consuming it.
///
/// ```no_run
/// # use image::ImageError;
/// # use image::io::Reader;
/// # fn main() -> Result<(), ImageError> {
/// let image = Reader::open("path/to/image.png")?
///     .decode()?;
/// # Ok(()) }
/// ```
///
/// It is also possible to make a guess based on the content. This is especially handy if the
/// source is some blob in memory and you have constructed the reader in another way. Here is an
/// example with a `pnm` black-and-white subformat that encodes its pixel matrix with ascii values.
///
#[cfg_attr(feature = "pnm", doc = "```")]
#[cfg_attr(not(feature = "pnm"), doc = "```no_run")]
/// # use image::ImageError;
/// # use image::io::Reader;
/// # fn main() -> Result<(), ImageError> {
/// use std::io::Cursor;
/// use image::ImageFormat;
///
/// let raw_data = b"P1 2 2\n\
///     0 1\n\
///     1 0\n";
///
/// let mut reader = Reader::new(Cursor::new(raw_data))
///     .with_guessed_format()
///     .expect("Cursor io never fails");
/// assert_eq!(reader.format(), Some(ImageFormat::Pnm));
///
/// let image = reader.decode()?;
/// # Ok(()) }
/// ```
///
/// As a final fallback or if only a specific format must be used, the reader always allows manual
/// specification of the supposed image format with [`set_format`].
///
/// [`set_format`]: #method.set_format
/// [`ImageDecoder`]: ../trait.ImageDecoder.html
pub struct Reader<R: Read> {
    /// The reader.
    inner: R,
    /// The format, if one has been set or deduced.
    format: Option<ImageFormat>,
}

impl<R: Read> Reader<R> {
    /// Create a new image reader without a preset format.
    ///
    /// It is possible to guess the format based on the content of the read object with
    /// [`guess_format`], or to set the format directly with [`set_format`].
    ///
    /// [`guess_format`]: #method.guess_format
    /// [`set_format`]: method.set_format
    pub fn new(reader: R) -> Self {
        Reader {
            inner: reader,
            format: None,
        }
    }

    /// Construct a reader with specified format.
    pub fn with_format(reader: R, format: ImageFormat) -> Self {
        Reader {
            inner: reader,
            format: Some(format),
        }
    }

    /// Get the currently determined format.
    pub fn format(&self) -> Option<ImageFormat> {
        self.format
    }

    /// Supply the format as which to interpret the read image.
    pub fn set_format(&mut self, format: ImageFormat) {
        self.format = Some(format);
    }

    /// Remove the current information on the image format.
    ///
    /// Note that many operations require format information to be present and will return e.g. an
    /// `ImageError::Unsupported` when the image format has not been set.
    pub fn clear_format(&mut self) {
        self.format = None;
    }

    /// Unwrap the reader.
    pub fn into_inner(self) -> R {
        self.inner
    }
}

impl Reader<BufReader<File>> {
    /// Open a file to read, format will be guessed from path.
    ///
    /// This will not attempt any io operation on the opened file.
    ///
    /// If you want to inspect the content for a better guess on the format, which does not depend
    /// on file extensions, follow this call with a call to [`guess_format`].
    ///
    /// [`guess_format`]: #method.guess_format
    pub fn open<P>(path: P) -> io::Result<Self> where P: AsRef<Path> {
        Self::open_impl(path.as_ref())
    }

    fn open_impl(path: &Path) -> io::Result<Self> {
        let file = File::open(path)?;
        Ok(Reader {
            inner: BufReader::new(file),
            format: ImageFormat::from_path(path).ok(),
        })
    }
}

impl<R: BufRead + Seek> Reader<R> {
    /// Make a format guess based on the content, replacing it on success.
    ///
    /// Returns `Ok` with the guess if no io error occurs. Additionally, replaces the current
    /// format if the guess was successful. If the guess was not unable to determine a format then
    /// the current format of the reader is unchanged.
    ///
    /// Returns an error if the underlying reader fails. The format is unchanged. The error is a
    /// `std::io::Error` and not `ImageError` since the only error case is an error when the
    /// underlying reader seeks.
    ///
    /// When an error occurs, the reader may not have been properly reset and it is potentially
    /// hazardous to continue with more io.
    ///
    /// ## Usage
    ///
    /// This supplements the path based type deduction from [`open`](Reader::open) with content based deduction.
    /// This is more common in Linux and UNIX operating systems and also helpful if the path can
    /// not be directly controlled.
    ///
    /// ```no_run
    /// # use image::ImageError;
    /// # use image::io::Reader;
    /// # fn main() -> Result<(), ImageError> {
    /// let image = Reader::open("image.unknown")?
    ///     .with_guessed_format()?
    ///     .decode()?;
    /// # Ok(()) }
    /// ```
    pub fn with_guessed_format(mut self) -> io::Result<Self> {
        let format = self.guess_format()?;
        // Replace format if found, keep current state if not.
        self.format = format.or(self.format);
        Ok(self)
    }

    fn guess_format(&mut self) -> io::Result<Option<ImageFormat>> {
        let mut start = [0; 16];

        // Save current offset, read start, restore offset.
        let cur = self.inner.seek(SeekFrom::Current(0))?;
        let len = io::copy(
            // Accept shorter files but read at most 16 bytes.
            &mut self.inner.by_ref().take(16),
            &mut Cursor::new(&mut start[..]))?;
        self.inner.seek(SeekFrom::Start(cur))?;

        Ok(free_functions::guess_format_impl(&start[..len as usize]))
    }

    /// Read the image dimensions.
    ///
    /// Uses the current format to construct the correct reader for the format.
    ///
    /// If no format was determined, returns an `ImageError::Unsupported`.
    pub fn into_dimensions(mut self) -> ImageResult<(u32, u32)> {
        let format = self.require_format()?;
        free_functions::image_dimensions_with_format_impl(self.inner, format)
    }

    /// Read the image (replaces `load`).
    ///
    /// Uses the current format to construct the correct reader for the format.
    ///
    /// If no format was determined, returns an `ImageError::Unsupported`.
    pub fn decode(mut self) -> ImageResult<DynamicImage> {
        let format = self.require_format()?;
        free_functions::load(self.inner, format)
    }

    fn require_format(&mut self) -> ImageResult<ImageFormat> {
        self.format.ok_or_else(||
            ImageError::Unsupported(UnsupportedError::from_format_and_kind(
                ImageFormatHint::Unknown,
                UnsupportedErrorKind::Format(ImageFormatHint::Unknown))))
    }
}
<|endoftext|>