<commit_before>use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};

use super::{ArrayLength, GenericArray};

use crate::functional::*;
use crate::sequence::*;

impl<T: Default, N> Default for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline]
    fn default() -> Self {
        Self::generate(|_| T::default())
    }
}

impl<T: Clone, N> Clone for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn clone(&self) -> GenericArray<T, N> {
        self.map(Clone::clone)
    }
}

impl<T: Copy, N> Copy for GenericArray<T, N>
where
    N: ArrayLength<T>,
    N::ArrayType: Copy,
{
}

impl<T: PartialEq, N> PartialEq for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn eq(&self, other: &Self) -> bool {
        **self == **other
    }
}
impl<T: Eq, N> Eq for GenericArray<T, N> where N: ArrayLength<T> {}

impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {
        PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
    }
}

impl<T: Ord, N> Ord for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {
        Ord::cmp(self.as_slice(), other.as_slice())
    }
}

impl<T: Debug, N> Debug for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self[..].fmt(fmt)
    }
}

impl<T, N> Borrow<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline(always)]
    fn borrow(&self) -> &[T] {
        &self[..]
    }
}

impl<T, N> BorrowMut<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline(always)]
    fn borrow_mut(&mut self) -> &mut [T] {
        &mut self[..]
    }
}

impl<T, N> AsRef<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline(always)]
    fn as_ref(&self) -> &[T] {
        &self[..]
    }
}

impl<T, N> AsMut<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline(always)]
    fn as_mut(&mut self) -> &mut [T] {
        &mut self[..]
    }
}

impl<T: Hash, N> Hash for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn hash<H>(&self, state: &mut H)
    where
        H: Hasher,
    {
        Hash::hash(&self[..], state)
    }
}

macro_rules! impl_from {
    ($($n: expr => $ty: ty),*) => {
        $(
            impl<T> From<[T; $n]> for GenericArray<T, $ty> {
                #[inline(always)]
                fn from(arr: [T; $n]) -> Self {
                    unsafe { $crate::transmute(arr) }
                }
            }

            impl<T> Into<[T; $n]> for GenericArray<T, $ty> {
                #[inline(always)]
                fn into(self) -> [T; $n] {
                    unsafe { $crate::transmute(self) }
                }
            }
        )*
    }
}

impl_from! {
    1  => ::typenum::U1,
    2  => ::typenum::U2,
    3  => ::typenum::U3,
    4  => ::typenum::U4,
    5  => ::typenum::U5,
    6  => ::typenum::U6,
    7  => ::typenum::U7,
    8  => ::typenum::U8,
    9  => ::typenum::U9,
    10 => ::typenum::U10,
    11 => ::typenum::U11,
    12 => ::typenum::U12,
    13 => ::typenum::U13,
    14 => ::typenum::U14,
    15 => ::typenum::U15,
    16 => ::typenum::U16,
    17 => ::typenum::U17,
    18 => ::typenum::U18,
    19 => ::typenum::U19,
    20 => ::typenum::U20,
    21 => ::typenum::U21,
    22 => ::typenum::U22,
    23 => ::typenum::U23,
    24 => ::typenum::U24,
    25 => ::typenum::U25,
    26 => ::typenum::U26,
    27 => ::typenum::U27,
    28 => ::typenum::U28,
    29 => ::typenum::U29,
    30 => ::typenum::U30,
    31 => ::typenum::U31,
    32 => ::typenum::U32
}
<commit_msg>Implement more to/from array lengths<commit_after>use core::borrow::{Borrow, BorrowMut};
use core::cmp::Ordering;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};

use super::{ArrayLength, GenericArray};

use crate::functional::*;
use crate::sequence::*;

impl<T: Default, N> Default for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline]
    fn default() -> Self {
        Self::generate(|_| T::default())
    }
}

impl<T: Clone, N> Clone for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn clone(&self) -> GenericArray<T, N> {
        self.map(Clone::clone)
    }
}

impl<T: Copy, N> Copy for GenericArray<T, N>
where
    N: ArrayLength<T>,
    N::ArrayType: Copy,
{
}

impl<T: PartialEq, N> PartialEq for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn eq(&self, other: &Self) -> bool {
        **self == **other
    }
}
impl<T: Eq, N> Eq for GenericArray<T, N> where N: ArrayLength<T> {}

impl<T: PartialOrd, N> PartialOrd for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn partial_cmp(&self, other: &GenericArray<T, N>) -> Option<Ordering> {
        PartialOrd::partial_cmp(self.as_slice(), other.as_slice())
    }
}

impl<T: Ord, N> Ord for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn cmp(&self, other: &GenericArray<T, N>) -> Ordering {
        Ord::cmp(self.as_slice(), other.as_slice())
    }
}

impl<T: Debug, N> Debug for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self[..].fmt(fmt)
    }
}

impl<T, N> Borrow<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline(always)]
    fn borrow(&self) -> &[T] {
        &self[..]
    }
}

impl<T, N> BorrowMut<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline(always)]
    fn borrow_mut(&mut self) -> &mut [T] {
        &mut self[..]
    }
}

impl<T, N> AsRef<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline(always)]
    fn as_ref(&self) -> &[T] {
        &self[..]
    }
}

impl<T, N> AsMut<[T]> for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    #[inline(always)]
    fn as_mut(&mut self) -> &mut [T] {
        &mut self[..]
    }
}

impl<T: Hash, N> Hash for GenericArray<T, N>
where
    N: ArrayLength<T>,
{
    fn hash<H>(&self, state: &mut H)
    where
        H: Hasher,
    {
        Hash::hash(&self[..], state)
    }
}

macro_rules! impl_from {
    ($($n: expr => $ty: ty),*) => {
        $(
            impl<T> From<[T; $n]> for GenericArray<T, $ty> {
                #[inline(always)]
                fn from(arr: [T; $n]) -> Self {
                    unsafe { $crate::transmute(arr) }
                }
            }

            impl<T> Into<[T; $n]> for GenericArray<T, $ty> {
                #[inline(always)]
                fn into(self) -> [T; $n] {
                    unsafe { $crate::transmute(self) }
                }
            }
        )*
    }
}

impl_from! {
    1  => ::typenum::U1,
    2  => ::typenum::U2,
    3  => ::typenum::U3,
    4  => ::typenum::U4,
    5  => ::typenum::U5,
    6  => ::typenum::U6,
    7  => ::typenum::U7,
    8  => ::typenum::U8,
    9  => ::typenum::U9,
    10 => ::typenum::U10,
    11 => ::typenum::U11,
    12 => ::typenum::U12,
    13 => ::typenum::U13,
    14 => ::typenum::U14,
    15 => ::typenum::U15,
    16 => ::typenum::U16,
    17 => ::typenum::U17,
    18 => ::typenum::U18,
    19 => ::typenum::U19,
    20 => ::typenum::U20,
    21 => ::typenum::U21,
    22 => ::typenum::U22,
    23 => ::typenum::U23,
    24 => ::typenum::U24,
    25 => ::typenum::U25,
    26 => ::typenum::U26,
    27 => ::typenum::U27,
    28 => ::typenum::U28,
    29 => ::typenum::U29,
    30 => ::typenum::U30,
    31 => ::typenum::U31,
    32 => ::typenum::U32,

    33 => ::typenum::U33,
    34 => ::typenum::U34,
    35 => ::typenum::U35,
    36 => ::typenum::U36,
    37 => ::typenum::U37,
    38 => ::typenum::U38,
    39 => ::typenum::U39,
    40 => ::typenum::U40,
    41 => ::typenum::U41,
    42 => ::typenum::U42,
    43 => ::typenum::U43,
    44 => ::typenum::U44,
    45 => ::typenum::U45,
    46 => ::typenum::U46,
    47 => ::typenum::U47,
    48 => ::typenum::U48,
    49 => ::typenum::U49,
    50 => ::typenum::U50,
    51 => ::typenum::U51,
    52 => ::typenum::U52,
    53 => ::typenum::U53,
    54 => ::typenum::U54,
    55 => ::typenum::U55,
    56 => ::typenum::U56,
    57 => ::typenum::U57,
    58 => ::typenum::U58,
    59 => ::typenum::U59,
    60 => ::typenum::U60,
    61 => ::typenum::U61,
    62 => ::typenum::U62,
    63 => ::typenum::U63,
    64 => ::typenum::U64,

    70 => ::typenum::U70,
    80 => ::typenum::U80,
    90 => ::typenum::U90,

    100 => ::typenum::U100,
    200 => ::typenum::U200,
    300 => ::typenum::U300,
    400 => ::typenum::U400,
    500 => ::typenum::U500,

    128 => ::typenum::U128,
    256 => ::typenum::U256,
    512 => ::typenum::U512,

    1000 => ::typenum::U1000,
    1024 => ::typenum::U1024
}
<|endoftext|>


<commit_before>
/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
///
/// ## Alpha blending
/// The default behavior for alpha blending is assumed to be turned off.
/// A back-end might choose to turn it on by default and ignore enable/disable.
/// The default behavior for not supporting alpha blending is ignoring enable/disable.
/// Alpha blending is assumed to be expensive and turned off when not needed.
/// For cases when alpha blending is explicitly not wanted there will be own methods,
/// in case the back-end needs to restore to its own default afterwards.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_clear_rgba(&self) -> bool { false }

    /// Clears background with a color.
    fn clear_rgba(&mut self, _r: f32, _g: f32, _b: f32, _a: f32) {}

    /// Turns on alpha blending.
    fn enable_alpha_blend(&mut self) {}

    /// Turns off alpha blending.
    fn disable_alpha_blend(&mut self) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_f64_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_f64_rgba_f32(
        &mut self,
        _vertices: &[f64],
        _colors: &[f32]
    ) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        _vertices: &[f32],
        _colors: &[f32]
    ) {}
}

<commit_msg>Added texture support to `BackEnd`<commit_after>
/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
///
/// ## Alpha blending
/// The default behavior for alpha blending is assumed to be turned off.
/// A back-end might choose to turn it on by default and ignore enable/disable.
/// The default behavior for not supporting alpha blending is ignoring enable/disable.
/// Alpha blending is assumed to be expensive and turned off when not needed.
/// For cases when alpha blending is explicitly not wanted there will be own methods,
/// in case the back-end needs to restore to its own default afterwards.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_clear_rgba(&self) -> bool { false }

    /// Clears background with a color.
    fn clear_rgba(&mut self, _r: f32, _g: f32, _b: f32, _a: f32) {}

    /// Turns on alpha blending.
    fn enable_alpha_blend(&mut self) {}

    /// Turns off alpha blending.
    fn disable_alpha_blend(&mut self) {}

    /// Returns true if texture feature is supported.
    #[inline(always)]
    fn supports_single_texture(&self) -> bool { false }

    /// Sets the current single-texture.
    fn enable_single_texture(&mut self, _texture_id: uint) {}

    /// Disables single-texture.
    fn disable_single_texture(&mut self) {}

    /// Should return true if texture has alpha channel.
    ///
    /// This will enable alpha blending.
    /// Alpha blending might be enabled if color per vertex has alpha.
    /// Ignore if alpha blending is not supported.
    /// Ignore if alpha channel is not used.
    #[inline(always)]
    fn has_texture_alpha(&self, _texture_id: uint) -> bool { false }

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_f64_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_f64_rgba_f32(
        &mut self,
        _vertices: &[f64],
        _colors: &[f32]
    ) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_f32_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_f32_rgba_f32(
        &mut self,
        _vertices: &[f32],
        _colors: &[f32]
    ) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_f32_rgba_f32_uv_f32(&self) -> bool { false }

    /// Renders list of 2d triangles.
    ///
    /// A color and a texture coordinate is assigned per vertex.
    /// The texture coordinates refers to the current single-texture.
    fn tri_list_xy_f32_rgba_f32_uv_f32(
        &mut self,
        _vertices: &[f32],
        _colors: &[f32],
        _texture_coords: &[f32]
    ) {}
}

<|endoftext|>


<commit_before>
/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_clear_rgba(&self) -> bool { false }

    /// Clears background with a color.
    fn clear_rgba(&mut self, _r: f32, _g: f32, _b: f32, _a: f32) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f64(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f64(&mut self, _vertices: &[f64], _colors: &[f64]) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f32(&mut self, _vertices: &[f32], _colors: &[f32]) {}
}
<commit_msg>Added alpha_blend to BackEnd<commit_after>
/// Implemented by all graphics back-ends.
/// This trait uses default methods to simplify implementation.
pub trait BackEnd {
    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_clear_rgba(&self) -> bool { false }

    /// Clears background with a color.
    fn clear_rgba(&mut self, _r: f32, _g: f32, _b: f32, _a: f32) {}

    /// Turns on/off alpha blending.
    /// The default state is assumed to be 'off'.
    /// The default behavior is to ignore it if not supported.
    /// Alpha blending is assumed to be expensive and turned off when not needed.
    fn alpha_blend(_on: bool) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f64(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f64(&mut self, _vertices: &[f64], _colors: &[f64]) {}

    /// Returns true if feature is supported.
    #[inline(always)]
    fn supports_tri_list_xy_rgba_f32(&self) -> bool { false }

    /// Renders list of 2d triangles with color assigned per vertex.
    fn tri_list_xy_rgba_f32(&mut self, _vertices: &[f32], _colors: &[f32]) {}
}
<|endoftext|>


<commit_before>#![deny(warnings)]
extern crate coreutils;
use coreutils::extra::OptionalExt;
use std::env::args;
use std::io;
use std::io::Write;
//use std::rand::FloatMath::*;

#[derive(Debug, Clone)]
pub enum Token {
    Plus,
    Minus,
    Divide,
    Multiply,
    Exponent,
    OpenParen,
    CloseParen,
    Number(String),
}

impl Token {
    pub fn to_str(&self) -> &'static str {
        match self {
            &Token::Plus       => "Plus",
            &Token::Minus      => "Minus",
            &Token::Divide     => "Divide",
            &Token::Multiply   => "Multiply",
            &Token::Exponent   => "Exponent",
            &Token::OpenParen  => "OpenParen",
            &Token::CloseParen => "CloseParen",
            &Token::Number(_)  => "Number",
        }
    }

    pub fn to_string(&self) -> String {
        self.to_str().to_owned()
    }
}

#[derive(Debug,  Clone)]
pub enum ParseError {
    InvalidNumber(String),
    UnrecognizedToken(String),
    UnexpectedToken(String, &'static str),
    UnexpectedEndOfInput,
    OtherError(String),
}

#[derive(Clone,Debug)]
pub struct IntermediateResult {
    value: f64,
    tokens_read: usize,
}

impl IntermediateResult {
    fn new(value: f64, tokens_read: usize) -> Self {
        IntermediateResult {
            value: value,
            tokens_read: tokens_read,
        }
    }
}

pub trait OperatorFunctions {
    fn is_operator(self) -> bool;
    fn operator_type(self) -> Token;
}

impl OperatorFunctions for char {
    fn is_operator(self) -> bool {
        self == '+' ||
        self == '-' ||
        self == '*' ||
        self == '/' ||
        self == '^' ||
        self == '(' ||
        self == ')'
    }

    fn operator_type(self) -> Token {
        match self {
            '+' => Token::Plus,
            '-' => Token::Minus,
            '/' => Token::Divide,
            '*' => Token::Multiply,
            '^' => Token::Exponent,
            '(' => Token::OpenParen,
            ')' => Token::CloseParen,
            _   => coreutils::extra::fail("Invalid operator", &mut io::stderr())
        }
    }
}

pub fn tokenize(input: &str) -> Result<Vec<Token>, ParseError> {
    // CONSIDER: any smarter way to guess an initial capacity?
    let mut tokens: Vec<Token> = Vec::with_capacity(25);

    // TODO: Not this. Modify to use iterator
    let chars: Vec<char> = input.chars().collect();

    let input_length = chars.len();
    let mut current_pos = 0;
    while current_pos < input_length {
        let c : char = chars[current_pos];
        if c.is_digit(10) {
            let token_string = consume_number(&chars[current_pos..]);
            current_pos += token_string.len();
            tokens.push(Token::Number(token_string));
        } else if c.is_operator() {
            tokens.push(c.operator_type());
            current_pos += 1;
        } else if c.is_whitespace() {
            current_pos += 1;
        } else {
            let token_string = consume_until_new_token(&chars[current_pos..]);
            return Err(ParseError::UnrecognizedToken(token_string));
        }
    }
    Ok(tokens)
}

fn consume_number(input: &[char]) -> String {
    // CONSIDER: input.len seems a bit generous
    let mut number = String::with_capacity(input.len());
    let mut has_decimal_point = false;
    for &c in input {
        if c == '.' {
            if has_decimal_point {
                break;
            } else {
                number.push(c);
                has_decimal_point = true;
            }
        } else if c.is_digit(10) {
            number.push(c);
        } else {
            break;
        }
    }
    number
}

fn consume_until_new_token(input: &[char]) -> String {
    input.iter()
         .take_while(|c| !(c.is_whitespace() || c.is_operator() || c.is_digit(10)))
         .map(|&c| c)
         .collect()
}

// Addition and subtraction
pub fn e_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut t1 = try!(t_expr(token_list));
    let mut index = t1.tokens_read;

    while index < token_list.len() {
        match token_list[index] {
            Token::Plus => {
                let t2 = try!(t_expr(&token_list[index+1..]));
                t1.value += t2.value;
                t1.tokens_read += t2.tokens_read + 1;
            }
            Token::Minus => {
                let t2 = try!(t_expr(&token_list[index+1..]));
                t1.value -= t2.value;
                t1.tokens_read += t2.tokens_read + 1;
            }
            Token::Number(ref n) => return Err(ParseError::UnexpectedToken(n.clone(),"operator")),
            _ => break,
        };
        index = t1.tokens_read;
    }
    Ok(t1)
}

// Multiplication and division
pub fn t_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut f1 = try!(f_expr(token_list));
    let mut index = f1.tokens_read;

    while index < token_list.len() {
        match token_list[index] {
            Token::Multiply => {
                let f2 = try!(f_expr(&token_list[index+1..]));
                f1.value *= f2.value;
                f1.tokens_read += f2.tokens_read + 1;
            }
            Token::Divide => {
                let f2 = try!(f_expr(&token_list[index+1..]));
                if f2.value == 0.0 {
                    return Err(ParseError::OtherError("Divide by zero error".to_owned()));
                } else {
                    f1.value /= f2.value;
                    f1.tokens_read += f2.tokens_read + 1;
                }
            }
            Token::Number(ref n) => return Err(ParseError::UnexpectedToken(n.clone(),"operator")),
            _ => break,
        }
        index = f1.tokens_read;
    }
    Ok(f1)
}

// Exponentiation
pub fn f_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut g1 = try!(g_expr(token_list));
    let mut index = g1.tokens_read;
    let token_len = token_list.len();
    while index < token_len {
        match token_list[index] {
            Token::Exponent => {
                let f = try!(f_expr(&token_list[index+1..]));
                g1.value = g1.value.powf(f.value);
                g1.tokens_read += f.tokens_read + 1;
            }
            Token::Number(ref n) => return Err(ParseError::UnexpectedToken(n.clone(),"operator")),
            _ => break,
        }
        index = g1.tokens_read;
    }
    Ok(g1)
}

// Numbers and parenthesized expressions
pub fn g_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    if !token_list.is_empty() {
        match token_list[0] {
            Token::Number(ref n) => {
                n.parse::<f64>()
                 .map_err(|_| ParseError::InvalidNumber(n.clone()))
                 .and_then(|num| Ok(IntermediateResult::new(num, 1)))
            }
            Token::Minus => {
                if token_list.len() > 1 {
                    if let Token::Number(ref n) = token_list[1] {
                        n.parse::<f64>()
                         .map_err(|_| ParseError::InvalidNumber(n.clone()))
                         .and_then(|num| Ok(IntermediateResult::new(-1.0 * num, 2)))
                    } else {
                        Err(ParseError::UnexpectedToken(token_list[1].to_string(), "number"))
                    }
                } else {
                    Err(ParseError::UnexpectedEndOfInput)
                }
            }
            Token::OpenParen => {
                let expr = e_expr(&token_list[1..]);
                match expr {
                    Ok(ir) => {
                        let close_paren = ir.tokens_read + 1;
                        if close_paren < token_list.len() {
                            match token_list[close_paren] {
                                Token::CloseParen => Ok(IntermediateResult::new(ir.value, close_paren+1)),
                                _ => Err(ParseError::UnexpectedToken(token_list[close_paren].to_string(), ")")),
                            }
                        } else {
                            Err(ParseError::OtherError("no matching close parenthesis found.".to_owned()))
                        }
                    }
                    Err(e) => Err(e),
                }
            }
            _ => Err(ParseError::UnexpectedToken(token_list[0].to_string(), "number"))
        }
    } else {
        Err(ParseError::UnexpectedEndOfInput)
    }
}

pub fn parse(tokens: Vec<Token>) -> Result<String, ParseError> {
    e_expr(&tokens[..]).map(|answer| answer.value.to_string())
}

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

    #[test]
    fn simple_addition() {
        assert_eq!(tokenize("12+3").and_then(parse).unwrap(), "15");
    }

    #[test]
    fn addition() {
        assert_eq!(tokenize("12+3+5").and_then(parse).unwrap(), "20");
    }

    #[test]
    fn simple_subtraction() {
        assert_eq!(tokenize("12-3").and_then(parse).unwrap(), "9");
    }

    #[test]
    fn subtraction() {
        assert_eq!(tokenize("12-3-4").and_then(parse).unwrap(), "5");
    }

    #[test]
    fn mixed_addition_and_subtraction() {
        assert_eq!(tokenize("12+3-4+8-2-3").and_then(parse).unwrap(), "14");
    }

    #[test]
    fn simple_parentheses() {
        assert_eq!(tokenize("((3))").and_then(parse).unwrap(), "3");
        assert_eq!(tokenize("(12+(2+3))").and_then(parse).unwrap(), "17");
        assert_eq!(tokenize("12+(2+3)").and_then(parse).unwrap(), "17");
    }

    #[test]
    fn parentheses() {
        assert_eq!(tokenize("12+(2+(3+5))+4+(((6)))").and_then(parse).unwrap(), "32");
    }

    #[test]
    fn multiplication() {
        assert_eq!(tokenize("3*3").and_then(parse).unwrap(), "9");
        assert_eq!(tokenize("3*5").and_then(parse).unwrap(), "15");
        assert_eq!(tokenize("0*5").and_then(parse).unwrap(), "0");
        assert_eq!(tokenize("5*4*3*2*1").and_then(parse).unwrap(), "120");
        assert_eq!(tokenize("(5*4)*3*(2*1)").and_then(parse).unwrap(), "120");
    }

    #[test]
    fn division() {
        assert_eq!(tokenize("12/4").and_then(parse).unwrap(), "3");
        assert_eq!(tokenize("12/3").and_then(parse).unwrap(), "4");
        assert_eq!(tokenize("5/2").and_then(parse).unwrap(), "2.5");
        assert_eq!(tokenize("120/5/4/3/2").and_then(parse).unwrap(), "1");
        assert_eq!(tokenize("(120/5)/4/(3/2)").and_then(parse).unwrap(), "4");
    }

    #[test]
    fn exponentiation() {
        assert_eq!(tokenize("3^2").and_then(parse).unwrap(), "9");
        assert_eq!(tokenize("2^3^2").and_then(parse).unwrap(), "512");
        assert_eq!(tokenize("2^(2+1)^2").and_then(parse).unwrap(), "512");
    }
}

fn eval(input: &str) -> String {
    match tokenize(input).and_then(parse) {
        Ok(s) => s,
        Err(e) => match e {
            ParseError::InvalidNumber(s) => ["Invalid number: ", s.as_str() ].join(""),
            ParseError::UnrecognizedToken(s) => ["Unrecognized token: ", s.as_str()].join(""),
            ParseError::UnexpectedToken(found, expected) => ["Unexpected token: expected [", expected, "] but found '", found.as_str(), "'"].join(""),
            ParseError::UnexpectedEndOfInput => "Error: Unexpected end of input.".to_owned(),
            ParseError::OtherError(s) => s,
        }
    }
}

fn main() {
    let args = args();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();
    if args.len() > 1 {
        let input: Vec<String> = args.skip(1).collect();
        println!("{}", eval(&input.join("")));
    } else {
        let prompt = "[]> ".as_bytes();
        loop {
            stdout.write(prompt).try(&mut stderr);
            stdout.flush().try(&mut stderr);
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                       .try(&mut stderr);
            match input.trim() {
                "exit" => break,
                s => {
                    stdout.write(eval(s).as_bytes()).try(&mut stderr);
                    stdout.write("\n".as_bytes()).try(&mut stderr);
                    stdout.flush().try(&mut stderr);
                },
            }
        }
    }
}
<commit_msg>join -> concat, write->writeln, make errors consistent<commit_after>#![deny(warnings)]
extern crate coreutils;
use coreutils::extra::{OptionalExt,WriteExt};
use std::env::args;
use std::io;
use std::io::Write;

#[derive(Debug, Clone)]
pub enum Token {
    Plus,
    Minus,
    Divide,
    Multiply,
    Exponent,
    OpenParen,
    CloseParen,
    Number(String),
}

impl Token {
    pub fn to_str(&self) -> &'static str {
        match self {
            &Token::Plus       => "Plus",
            &Token::Minus      => "Minus",
            &Token::Divide     => "Divide",
            &Token::Multiply   => "Multiply",
            &Token::Exponent   => "Exponent",
            &Token::OpenParen  => "OpenParen",
            &Token::CloseParen => "CloseParen",
            &Token::Number(_)  => "Number",
        }
    }

    pub fn to_string(&self) -> String {
        self.to_str().to_owned()
    }
}

#[derive(Debug,  Clone)]
pub enum ParseError {
    InvalidNumber(String),
    UnrecognizedToken(String),
    UnexpectedToken(String, &'static str),
    UnexpectedEndOfInput,
    OtherError(String),
}

#[derive(Clone,Debug)]
pub struct IntermediateResult {
    value: f64,
    tokens_read: usize,
}

impl IntermediateResult {
    fn new(value: f64, tokens_read: usize) -> Self {
        IntermediateResult {
            value: value,
            tokens_read: tokens_read,
        }
    }
}

pub trait OperatorFunctions {
    fn is_operator(self) -> bool;
    fn operator_type(self) -> Token;
}

impl OperatorFunctions for char {
    fn is_operator(self) -> bool {
        self == '+' ||
        self == '-' ||
        self == '*' ||
        self == '/' ||
        self == '^' ||
        self == '(' ||
        self == ')'
    }

    fn operator_type(self) -> Token {
        match self {
            '+' => Token::Plus,
            '-' => Token::Minus,
            '/' => Token::Divide,
            '*' => Token::Multiply,
            '^' => Token::Exponent,
            '(' => Token::OpenParen,
            ')' => Token::CloseParen,
            _   => coreutils::extra::fail("Invalid operator", &mut io::stderr())
        }
    }
}

pub fn tokenize(input: &str) -> Result<Vec<Token>, ParseError> {
    // CONSIDER: input.len() too generous?
    let mut tokens = Vec::with_capacity(input.len());

    // TODO: Not this. Modify to use iterator
    let chars: Vec<char> = input.chars().collect();

    let input_length = chars.len();
    let mut current_pos = 0;
    while current_pos < input_length {
        let c = chars[current_pos];
        if c.is_digit(10) {
            let token_string = consume_number(&chars[current_pos..]);
            current_pos += token_string.len();
            tokens.push(Token::Number(token_string));
        } else if c.is_operator() {
            tokens.push(c.operator_type());
            current_pos += 1;
        } else if c.is_whitespace() {
            current_pos += 1;
        } else {
            let token_string = consume_until_new_token(&chars[current_pos..]);
            return Err(ParseError::UnrecognizedToken(token_string));
        }
    }
    Ok(tokens)
}

fn consume_number(input: &[char]) -> String {
    // CONSIDER: input.len seems a bit generous
    let mut number = String::with_capacity(input.len());
    let mut has_decimal_point = false;
    for &c in input {
        if c == '.' {
            if has_decimal_point {
                break;
            } else {
                number.push(c);
                has_decimal_point = true;
            }
        } else if c.is_digit(10) {
            number.push(c);
        } else {
            break;
        }
    }
    number
}

fn consume_until_new_token(input: &[char]) -> String {
    input.iter()
         .take_while(|c| !(c.is_whitespace() || c.is_operator() || c.is_digit(10)))
         .map(|&c| c)
         .collect()
}

// Addition and subtraction
pub fn e_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut t1 = try!(t_expr(token_list));
    let mut index = t1.tokens_read;

    while index < token_list.len() {
        match token_list[index] {
            Token::Plus => {
                let t2 = try!(t_expr(&token_list[index+1..]));
                t1.value += t2.value;
                t1.tokens_read += t2.tokens_read + 1;
            }
            Token::Minus => {
                let t2 = try!(t_expr(&token_list[index+1..]));
                t1.value -= t2.value;
                t1.tokens_read += t2.tokens_read + 1;
            }
            Token::Number(ref n) => return Err(ParseError::UnexpectedToken(n.clone(),"operator")),
            _ => break,
        };
        index = t1.tokens_read;
    }
    Ok(t1)
}

// Multiplication and division
pub fn t_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut f1 = try!(f_expr(token_list));
    let mut index = f1.tokens_read;

    while index < token_list.len() {
        match token_list[index] {
            Token::Multiply => {
                let f2 = try!(f_expr(&token_list[index+1..]));
                f1.value *= f2.value;
                f1.tokens_read += f2.tokens_read + 1;
            }
            Token::Divide => {
                let f2 = try!(f_expr(&token_list[index+1..]));
                if f2.value == 0.0 {
                    return Err(ParseError::OtherError("Divide by zero error".to_owned()));
                } else {
                    f1.value /= f2.value;
                    f1.tokens_read += f2.tokens_read + 1;
                }
            }
            Token::Number(ref n) => return Err(ParseError::UnexpectedToken(n.clone(),"operator")),
            _ => break,
        }
        index = f1.tokens_read;
    }
    Ok(f1)
}

// Exponentiation
pub fn f_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    let mut g1 = try!(g_expr(token_list));
    let mut index = g1.tokens_read;
    let token_len = token_list.len();
    while index < token_len {
        match token_list[index] {
            Token::Exponent => {
                let f = try!(f_expr(&token_list[index+1..]));
                g1.value = g1.value.powf(f.value);
                g1.tokens_read += f.tokens_read + 1;
            }
            Token::Number(ref n) => return Err(ParseError::UnexpectedToken(n.clone(),"operator")),
            _ => break,
        }
        index = g1.tokens_read;
    }
    Ok(g1)
}

// Numbers and parenthesized expressions
pub fn g_expr(token_list: &[Token]) -> Result<IntermediateResult, ParseError> {
    if !token_list.is_empty() {
        match token_list[0] {
            Token::Number(ref n) => {
                n.parse::<f64>()
                 .map_err(|_| ParseError::InvalidNumber(n.clone()))
                 .and_then(|num| Ok(IntermediateResult::new(num, 1)))
            }
            Token::Minus => {
                if token_list.len() > 1 {
                    if let Token::Number(ref n) = token_list[1] {
                        n.parse::<f64>()
                         .map_err(|_| ParseError::InvalidNumber(n.clone()))
                         .and_then(|num| Ok(IntermediateResult::new(-1.0 * num, 2)))
                    } else {
                        Err(ParseError::UnexpectedToken(token_list[1].to_string(), "number"))
                    }
                } else {
                    Err(ParseError::UnexpectedEndOfInput)
                }
            }
            Token::OpenParen => {
                let expr = e_expr(&token_list[1..]);
                match expr {
                    Ok(ir) => {
                        let close_paren = ir.tokens_read + 1;
                        if close_paren < token_list.len() {
                            match token_list[close_paren] {
                                Token::CloseParen => Ok(IntermediateResult::new(ir.value, close_paren+1)),
                                _ => Err(ParseError::UnexpectedToken(token_list[close_paren].to_string(), ")")),
                            }
                        } else {
                            Err(ParseError::OtherError("no matching close parenthesis found.".to_owned()))
                        }
                    }
                    Err(e) => Err(e),
                }
            }
            _ => Err(ParseError::UnexpectedToken(token_list[0].to_string(), "number"))
        }
    } else {
        Err(ParseError::UnexpectedEndOfInput)
    }
}

pub fn parse(tokens: Vec<Token>) -> Result<String, ParseError> {
    e_expr(&tokens).map(|answer| answer.value.to_string())
}

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

    #[test]
    fn simple_addition() {
        assert_eq!(tokenize("12+3").and_then(parse).unwrap(), "15");
    }

    #[test]
    fn addition() {
        assert_eq!(tokenize("12+3+5").and_then(parse).unwrap(), "20");
    }

    #[test]
    fn simple_subtraction() {
        assert_eq!(tokenize("12-3").and_then(parse).unwrap(), "9");
    }

    #[test]
    fn subtraction() {
        assert_eq!(tokenize("12-3-4").and_then(parse).unwrap(), "5");
    }

    #[test]
    fn mixed_addition_and_subtraction() {
        assert_eq!(tokenize("12+3-4+8-2-3").and_then(parse).unwrap(), "14");
    }

    #[test]
    fn simple_parentheses() {
        assert_eq!(tokenize("((3))").and_then(parse).unwrap(), "3");
        assert_eq!(tokenize("(12+(2+3))").and_then(parse).unwrap(), "17");
        assert_eq!(tokenize("12+(2+3)").and_then(parse).unwrap(), "17");
    }

    #[test]
    fn parentheses() {
        assert_eq!(tokenize("12+(2+(3+5))+4+(((6)))").and_then(parse).unwrap(), "32");
    }

    #[test]
    fn multiplication() {
        assert_eq!(tokenize("3*3").and_then(parse).unwrap(), "9");
        assert_eq!(tokenize("3*5").and_then(parse).unwrap(), "15");
        assert_eq!(tokenize("0*5").and_then(parse).unwrap(), "0");
        assert_eq!(tokenize("5*4*3*2*1").and_then(parse).unwrap(), "120");
        assert_eq!(tokenize("(5*4)*3*(2*1)").and_then(parse).unwrap(), "120");
    }

    #[test]
    fn division() {
        assert_eq!(tokenize("12/4").and_then(parse).unwrap(), "3");
        assert_eq!(tokenize("12/3").and_then(parse).unwrap(), "4");
        assert_eq!(tokenize("5/2").and_then(parse).unwrap(), "2.5");
        assert_eq!(tokenize("120/5/4/3/2").and_then(parse).unwrap(), "1");
        assert_eq!(tokenize("(120/5)/4/(3/2)").and_then(parse).unwrap(), "4");
    }

    #[test]
    fn exponentiation() {
        assert_eq!(tokenize("3^2").and_then(parse).unwrap(), "9");
        assert_eq!(tokenize("2^3^2").and_then(parse).unwrap(), "512");
        assert_eq!(tokenize("2^(2+1)^2").and_then(parse).unwrap(), "512");
    }
}

fn eval(input: &str) -> String {
    match tokenize(input).and_then(parse) {
        Ok(s) => s,
        Err(e) => match e {
            ParseError::InvalidNumber(s) => ["Error: Invalid number: ", s.as_str() ].concat(),
            ParseError::UnrecognizedToken(s) => ["Error: Unrecognized token: ", s.as_str()].concat(),
            ParseError::UnexpectedToken(found, expected) => ["Error: Unexpected token: expected [", expected, "] but found '", found.as_str(), "'"].concat(),
            ParseError::UnexpectedEndOfInput => "Error: Unexpected end of input.".to_owned(),
            ParseError::OtherError(s) => s,
        }
    }
}

fn main() {
    let args = args();
    let stdout = io::stdout();
    let mut stdout = stdout.lock();
    let mut stderr = io::stderr();
    if args.len() > 1 {
        let input: Vec<String> = args.skip(1).collect();
        stdout.writeln(eval(&input.join("")).as_bytes()).try(&mut stderr);
    } else {
        let prompt = "[]> ".as_bytes();
        loop {
            stdout.write(prompt).try(&mut stderr);
            stdout.flush().try(&mut stderr);
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                       .try(&mut stderr);
            match input.trim() {
                "exit" => break,
                s => {
                    stdout.writeln(eval(s).as_bytes()).try(&mut stderr);
                    stdout.flush().try(&mut stderr);
                },
            }
        }
    }
}
<|endoftext|>


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

//! Combines data chunks into larger blobs to be stored externally.

use backend::StoreBackend;
use capnp;
use errors;
use hash::Hash;
use hash::tree::HashRef;
use std::borrow::Cow;
use std::mem;
use std::sync::{Arc, Mutex, MutexGuard};
use std::thread;
use tags;
use util::FnBox;
use key;

mod chunk;
mod blob;
mod index;
#[cfg(test)]
pub mod tests;

#[cfg(all(test, feature = "benchmarks"))]
mod benchmarks;

pub use self::blob::Blob;
pub use self::chunk::{ChunkRef, Key, NodeType, LeafType, Packing};
pub use self::index::{BlobDesc, BlobIndex};

error_type! {
    #[derive(Debug)]
    pub enum BlobError {
        Message(Cow<'static, str>) {
            desc (e) &**e;
            from (s: &'static str) s.into();
            from (s: String) s.into();
        },
        CryptoError(errors::CryptoError) {
            cause;
        },
        DataSerialization(capnp::Error) {
            cause;
        }
    }
}

pub struct BlobStore<B>(Arc<Mutex<StoreInner<B>>>);

pub struct StoreInner<B> {
    backend: Arc<B>,
    blob_index: Arc<BlobIndex>,
    blob_desc: BlobDesc,
    blob_refs: Vec<(Box<FnBox<(), ()>>)>,
    blob: Blob,
}

impl<B> Drop for StoreInner<B> {
    fn drop(&mut self) {
        // Sanity check that we flushed this blob store before dropping it.
        assert_eq!(0, self.blob.upperbound_len());
    }
}

impl<B: StoreBackend> StoreInner<B> {
    fn new(index: Arc<BlobIndex>, backend: Arc<B>, max_blob_size: usize) -> StoreInner<B> {
        let mut bs = StoreInner {
            backend: backend,
            blob_index: index,
            blob_desc: Default::default(),
            blob_refs: Vec::new(),
            blob: Blob::new(max_blob_size),
        };
        bs.reserve_new_blob();
        bs
    }

    fn reserve_new_blob(&mut self) -> BlobDesc {
        mem::replace(&mut self.blob_desc, self.blob_index.reserve())
    }

    fn flush(&mut self) {
        let ct = match self.blob.to_ciphertext() {
            None => return,
            Some(ct) => ct,
        };

        // Replace blob id
        let old_blob_desc = self.reserve_new_blob();

        self.blob_index.in_air(&old_blob_desc);
        self.backend
            .store(&old_blob_desc.name[..], &ct)
            .expect("Store operation failed");
        self.blob_index.commit_done(&old_blob_desc);

        // Go through callbacks
        while let Some(callback) = self.blob_refs.pop() {
            callback.call(());
        }
    }

    fn store(&mut self,
             chunk: &[u8],
             hash: Hash,
             node: NodeType,
             leaf: LeafType,
             info: Option<&key::Info>,
             callback: Box<FnBox<(), ()>>)
             -> HashRef {
        let mut href = HashRef {
            hash: hash,
            node: node,
            leaf: leaf,
            info: info.cloned(),
            persistent_ref: ChunkRef {
                blob_id: Some(0),
                blob_name: vec![0],
                packing: None,
                // Updated by try_append.
                offset: 0,
                length: 0,
                key: None,
            },
        };

        if chunk.is_empty() {
            // We are not going to store an empty chunk, so commit it ASAP.
            thread::spawn(move || callback.call(()));
        } else {
            href.persistent_ref.blob_id = Some(self.blob_desc.id);
            href.persistent_ref.blob_name = self.blob_desc.name.clone();
            if let Err(()) = self.blob.try_append(chunk, &mut href) {
                self.flush();
                href.persistent_ref.blob_id = Some(self.blob_desc.id);
                href.persistent_ref.blob_name = self.blob_desc.name.clone();

                self.blob.try_append(chunk, &mut href).unwrap();
            }

            // Queue the callback; we will trigger it when the blob has been pushed.
            self.blob_refs.push(callback);
        }

        // Info is internal to the blob only.
        href.info = None;
        // To avoid unnecessary blocking, we reply with the ID *before* possibly flushing.
        href
    }

    fn retrieve(&mut self, hash: &Hash, cref: &ChunkRef) -> Result<Option<Vec<u8>>, BlobError> {
        if cref.offset == 0 && cref.length == 0 {
            return Ok(Some(Vec::new()));
        }
        match self.backend.retrieve(&cref.blob_name[..]) {
            Ok(Some(blob)) => Ok(Some(Blob::read_chunk(&blob, hash, cref)?)),
            Ok(None) => Ok(None),
            Err(e) => Err(e.into()),
        }
    }

    fn retrieve_refs(&mut self, blob: BlobDesc) -> Result<Option<Vec<HashRef>>, BlobError> {
        match self.backend.retrieve(&blob.name[..])? {
            None => Ok(None),
            Some(ct) => {
                let hrefs = self.blob.refs_from_bytes(&ct)?;
                if hrefs.len() == 0 {
                    Ok(None)
                } else {
                    assert_eq!(&blob.name[..], &hrefs[0].persistent_ref.blob_name[..]);
                    Ok(Some(hrefs))
                }
            }
        }
    }

    fn recover(&mut self) -> Result<(), String> {
        self.backend.list()?.into_iter()
            .filter(|b| b.len() > 4)  // FIXME(jos): Remove when "root" is gone.
            .map(|b| self.blob_index.recover(b.into_vec())).last();
        Ok(())
    }

    fn tag(&mut self, chunk: ChunkRef, tag: tags::Tag) {
        self.blob_index.tag(&BlobDesc {
                                id: chunk.blob_id.unwrap_or(0),
                                name: chunk.blob_name,
                            },
                            tag);
    }

    fn tag_all(&mut self, tag: tags::Tag) {
        self.blob_index.tag_all(tag);
    }

    fn delete_by_tag(&mut self, tag: tags::Tag) -> Result<(), String> {
        let blobs = self.blob_index.list_by_tag(tag);
        for b in &blobs {
            self.backend.delete(&b.name)?;
        }
        self.blob_index.delete_by_tag(tag);
        Ok(())
    }
}

impl<B: StoreBackend> BlobStore<B> {
    pub fn new(index: Arc<BlobIndex>, backend: Arc<B>, max_blob_size: usize) -> BlobStore<B> {
        BlobStore(Arc::new(Mutex::new(StoreInner::new(index, backend, max_blob_size))))
    }

    fn lock(&self) -> MutexGuard<StoreInner<B>> {
        self.0.lock().expect("Blob store was poisoned")
    }

    /// Store a new data chunk into the current blob. The callback is triggered after the blob
    /// containing the chunk has been committed to persistent storage (it is then safe to use the
    /// `ChunkRef` as persistent reference).
    pub fn store(&self,
                 chunk: &[u8],
                 hash: Hash,
                 node: NodeType,
                 leaf: LeafType,
                 info: Option<&key::Info>,
                 callback: Box<FnBox<(), ()>>)
                 -> HashRef {
        let mut guard = self.lock();
        guard.store(chunk, hash, node, leaf, info, callback)
    }

    /// Retrieve the data chunk identified by `ChunkRef`.
    pub fn retrieve(&self, hash: &Hash, cref: &ChunkRef) -> Result<Option<Vec<u8>>, BlobError> {
        self.lock().retrieve(hash, cref)
    }

    /// Fetch a blob and recover the HashRefs for its contents.
    pub fn retrieve_refs(&self, blob: BlobDesc) -> Result<Option<Vec<HashRef>>, BlobError> {
        self.lock().retrieve_refs(blob)
    }

    /// Reinstall a blob recovered from external storage.
    pub fn recover(&self) -> Result<(), String> {
        self.lock().recover()
    }

    pub fn tag(&self, chunk: ChunkRef, tag: tags::Tag) {
        self.lock().tag(chunk, tag)
    }

    pub fn tag_all(&self, tag: tags::Tag) {
        self.lock().tag_all(tag)
    }

    pub fn delete_by_tag(&self, tag: tags::Tag) -> Result<(), String> {
        self.lock().delete_by_tag(tag)
    }

    pub fn list_by_tag(&self, tag: tags::Tag) -> Vec<BlobDesc> {
        self.lock().blob_index.list_by_tag(tag)
    }

    pub fn find(&self, name: &[u8]) -> Option<BlobDesc> {
        self.lock().blob_index.find(name)
    }

    /// Flush the current blob, independent of its size.
    pub fn flush(&self) {
        let mut guard = self.lock();
        guard.flush();
        guard.blob_index.flush();
    }
}
<commit_msg>Add corner-case: we can find our empty blob [0].<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Combines data chunks into larger blobs to be stored externally.

use backend::StoreBackend;
use capnp;
use errors;
use hash::Hash;
use hash::tree::HashRef;
use std::borrow::Cow;
use std::mem;
use std::sync::{Arc, Mutex, MutexGuard};
use std::thread;
use tags;
use util::FnBox;
use key;

mod chunk;
mod blob;
mod index;
#[cfg(test)]
pub mod tests;

#[cfg(all(test, feature = "benchmarks"))]
mod benchmarks;

pub use self::blob::Blob;
pub use self::chunk::{ChunkRef, Key, NodeType, LeafType, Packing};
pub use self::index::{BlobDesc, BlobIndex};

error_type! {
    #[derive(Debug)]
    pub enum BlobError {
        Message(Cow<'static, str>) {
            desc (e) &**e;
            from (s: &'static str) s.into();
            from (s: String) s.into();
        },
        CryptoError(errors::CryptoError) {
            cause;
        },
        DataSerialization(capnp::Error) {
            cause;
        }
    }
}

pub struct BlobStore<B>(Arc<Mutex<StoreInner<B>>>);

pub struct StoreInner<B> {
    backend: Arc<B>,
    blob_index: Arc<BlobIndex>,
    blob_desc: BlobDesc,
    blob_refs: Vec<(Box<FnBox<(), ()>>)>,
    blob: Blob,
}

impl<B> Drop for StoreInner<B> {
    fn drop(&mut self) {
        // Sanity check that we flushed this blob store before dropping it.
        assert_eq!(0, self.blob.upperbound_len());
    }
}

impl<B: StoreBackend> StoreInner<B> {
    fn new(index: Arc<BlobIndex>, backend: Arc<B>, max_blob_size: usize) -> StoreInner<B> {
        let mut bs = StoreInner {
            backend: backend,
            blob_index: index,
            blob_desc: Default::default(),
            blob_refs: Vec::new(),
            blob: Blob::new(max_blob_size),
        };
        bs.reserve_new_blob();
        bs
    }

    fn reserve_new_blob(&mut self) -> BlobDesc {
        mem::replace(&mut self.blob_desc, self.blob_index.reserve())
    }

    fn flush(&mut self) {
        let ct = match self.blob.to_ciphertext() {
            None => return,
            Some(ct) => ct,
        };

        // Replace blob id
        let old_blob_desc = self.reserve_new_blob();

        self.blob_index.in_air(&old_blob_desc);
        self.backend
            .store(&old_blob_desc.name[..], &ct)
            .expect("Store operation failed");
        self.blob_index.commit_done(&old_blob_desc);

        // Go through callbacks
        while let Some(callback) = self.blob_refs.pop() {
            callback.call(());
        }
    }

    fn store(&mut self,
             chunk: &[u8],
             hash: Hash,
             node: NodeType,
             leaf: LeafType,
             info: Option<&key::Info>,
             callback: Box<FnBox<(), ()>>)
             -> HashRef {
        let mut href = HashRef {
            hash: hash,
            node: node,
            leaf: leaf,
            info: info.cloned(),
            persistent_ref: ChunkRef {
                blob_id: Some(0),
                blob_name: vec![0],
                packing: None,
                // Updated by try_append.
                offset: 0,
                length: 0,
                key: None,
            },
        };

        if chunk.is_empty() {
            // We are not going to store an empty chunk, so commit it ASAP.
            thread::spawn(move || callback.call(()));
        } else {
            href.persistent_ref.blob_id = Some(self.blob_desc.id);
            href.persistent_ref.blob_name = self.blob_desc.name.clone();
            if let Err(()) = self.blob.try_append(chunk, &mut href) {
                self.flush();
                href.persistent_ref.blob_id = Some(self.blob_desc.id);
                href.persistent_ref.blob_name = self.blob_desc.name.clone();

                self.blob.try_append(chunk, &mut href).unwrap();
            }

            // Queue the callback; we will trigger it when the blob has been pushed.
            self.blob_refs.push(callback);
        }

        // Info is internal to the blob only.
        href.info = None;
        // To avoid unnecessary blocking, we reply with the ID *before* possibly flushing.
        href
    }

    fn retrieve(&mut self, hash: &Hash, cref: &ChunkRef) -> Result<Option<Vec<u8>>, BlobError> {
        if cref.offset == 0 && cref.length == 0 {
            return Ok(Some(Vec::new()));
        }
        match self.backend.retrieve(&cref.blob_name[..]) {
            Ok(Some(blob)) => Ok(Some(Blob::read_chunk(&blob, hash, cref)?)),
            Ok(None) => Ok(None),
            Err(e) => Err(e.into()),
        }
    }

    fn retrieve_refs(&mut self, blob: BlobDesc) -> Result<Option<Vec<HashRef>>, BlobError> {
        match self.backend.retrieve(&blob.name[..])? {
            None => Ok(None),
            Some(ct) => {
                let hrefs = self.blob.refs_from_bytes(&ct)?;
                if hrefs.len() == 0 {
                    Ok(None)
                } else {
                    assert_eq!(&blob.name[..], &hrefs[0].persistent_ref.blob_name[..]);
                    Ok(Some(hrefs))
                }
            }
        }
    }

    fn recover(&mut self) -> Result<(), String> {
        self.backend.list()?.into_iter()
            .filter(|b| b.len() > 4)  // FIXME(jos): Remove when "root" is gone.
            .map(|b| self.blob_index.recover(b.into_vec())).last();
        Ok(())
    }

    fn tag(&mut self, chunk: ChunkRef, tag: tags::Tag) {
        self.blob_index.tag(&BlobDesc {
                                id: chunk.blob_id.unwrap_or(0),
                                name: chunk.blob_name,
                            },
                            tag);
    }

    fn tag_all(&mut self, tag: tags::Tag) {
        self.blob_index.tag_all(tag);
    }

    fn delete_by_tag(&mut self, tag: tags::Tag) -> Result<(), String> {
        let blobs = self.blob_index.list_by_tag(tag);
        for b in &blobs {
            self.backend.delete(&b.name)?;
        }
        self.blob_index.delete_by_tag(tag);
        Ok(())
    }
}

impl<B: StoreBackend> BlobStore<B> {
    pub fn new(index: Arc<BlobIndex>, backend: Arc<B>, max_blob_size: usize) -> BlobStore<B> {
        BlobStore(Arc::new(Mutex::new(StoreInner::new(index, backend, max_blob_size))))
    }

    fn lock(&self) -> MutexGuard<StoreInner<B>> {
        self.0.lock().expect("Blob store was poisoned")
    }

    /// Store a new data chunk into the current blob. The callback is triggered after the blob
    /// containing the chunk has been committed to persistent storage (it is then safe to use the
    /// `ChunkRef` as persistent reference).
    pub fn store(&self,
                 chunk: &[u8],
                 hash: Hash,
                 node: NodeType,
                 leaf: LeafType,
                 info: Option<&key::Info>,
                 callback: Box<FnBox<(), ()>>)
                 -> HashRef {
        let mut guard = self.lock();
        guard.store(chunk, hash, node, leaf, info, callback)
    }

    /// Retrieve the data chunk identified by `ChunkRef`.
    pub fn retrieve(&self, hash: &Hash, cref: &ChunkRef) -> Result<Option<Vec<u8>>, BlobError> {
        self.lock().retrieve(hash, cref)
    }

    /// Fetch a blob and recover the HashRefs for its contents.
    pub fn retrieve_refs(&self, blob: BlobDesc) -> Result<Option<Vec<HashRef>>, BlobError> {
        self.lock().retrieve_refs(blob)
    }

    /// Reinstall a blob recovered from external storage.
    pub fn recover(&self) -> Result<(), String> {
        self.lock().recover()
    }

    pub fn tag(&self, chunk: ChunkRef, tag: tags::Tag) {
        self.lock().tag(chunk, tag)
    }

    pub fn tag_all(&self, tag: tags::Tag) {
        self.lock().tag_all(tag)
    }

    pub fn delete_by_tag(&self, tag: tags::Tag) -> Result<(), String> {
        self.lock().delete_by_tag(tag)
    }

    pub fn list_by_tag(&self, tag: tags::Tag) -> Vec<BlobDesc> {
        self.lock().blob_index.list_by_tag(tag)
    }

    pub fn find(&self, name: &[u8]) -> Option<BlobDesc> {
        if &name[..] == [0] {
            Some(BlobDesc {
                name: vec![0],
                id: 0,
            })
        } else {
            self.lock().blob_index.find(name)
        }
    }

    /// Flush the current blob, independent of its size.
    pub fn flush(&self) {
        let mut guard = self.lock();
        guard.flush();
        guard.blob_index.flush();
    }
}
<|endoftext|>


<commit_before>use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned;

const ODD_FUNCTIONS_WHITELIST: [&str; 14] = [
    "asin",
    "asinh",
    "atan",
    "atanh",
    "cbrt",
    "fract",
    "round",
    "signum",
    "sin",
    "sinh",
    "tan",
    "tanh",
    "to_degrees",
    "to_radians",
];

declare_clippy_lint! {
    /// **What it does:** Checks for operations where precedence may be unclear
    /// and suggests to add parentheses. Currently it catches the following:
    /// * mixed usage of arithmetic and bit shifting/combining operators without
    /// parentheses
    /// * a "negative" numeric literal (which is really a unary `-` followed by a
    /// numeric literal)
    ///   followed by a method call
    ///
    /// **Why is this bad?** Not everyone knows the precedence of those operators by
    /// heart, so expressions like these may trip others trying to reason about the
    /// code.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7
    /// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1
    pub PRECEDENCE,
    complexity,
    "operations where precedence may be unclear"
}

declare_lint_pass!(Precedence => [PRECEDENCE]);

impl EarlyLintPass for Precedence {
    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
        if expr.span.from_expansion() {
            return;
        }

        if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.kind {
            let span_sugg = |expr: &Expr, sugg, appl| {
                span_lint_and_sugg(
                    cx,
                    PRECEDENCE,
                    expr.span,
                    "operator precedence can trip the unwary",
                    "consider parenthesizing your expression",
                    sugg,
                    appl,
                );
            };

            if !is_bit_op(op) {
                return;
            }
            let mut applicability = Applicability::MachineApplicable;
            match (is_arith_expr(left), is_arith_expr(right)) {
                (true, true) => {
                    let sugg = format!(
                        "({}) {} ({})",
                        snippet_with_applicability(cx, left.span, "..", &mut applicability),
                        op.to_string(),
                        snippet_with_applicability(cx, right.span, "..", &mut applicability)
                    );
                    span_sugg(expr, sugg, applicability);
                },
                (true, false) => {
                    let sugg = format!(
                        "({}) {} {}",
                        snippet_with_applicability(cx, left.span, "..", &mut applicability),
                        op.to_string(),
                        snippet_with_applicability(cx, right.span, "..", &mut applicability)
                    );
                    span_sugg(expr, sugg, applicability);
                },
                (false, true) => {
                    let sugg = format!(
                        "{} {} ({})",
                        snippet_with_applicability(cx, left.span, "..", &mut applicability),
                        op.to_string(),
                        snippet_with_applicability(cx, right.span, "..", &mut applicability)
                    );
                    span_sugg(expr, sugg, applicability);
                },
                (false, false) => (),
            }
        }

        if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.kind {
            if let ExprKind::MethodCall(ref path_segment, ref args) = rhs.kind {
                if let Some(slf) = args.first() {
                    if let ExprKind::Lit(ref lit) = slf.kind {
                        match lit.kind {
                            LitKind::Int(..) | LitKind::Float(..) => {
                                for &odd_function in &ODD_FUNCTIONS_WHITELIST {
                                    if odd_function == &*path_segment.ident.name.as_str() {
                                        return;
                                    }
                                }
                                let mut applicability = Applicability::MachineApplicable;
                                span_lint_and_sugg(
                                    cx,
                                    PRECEDENCE,
                                    expr.span,
                                    "unary minus has lower precedence than method call",
                                    "consider adding parentheses to clarify your intent",
                                    format!(
                                        "-({})",
                                        snippet_with_applicability(cx, rhs.span, "..", &mut applicability)
                                    ),
                                    applicability,
                                );
                            },
                            _ => (),
                        }
                    }
                }
            }
        }
    }
}

fn is_arith_expr(expr: &Expr) -> bool {
    match expr.kind {
        ExprKind::Binary(Spanned { node: op, .. }, _, _) => is_arith_op(op),
        _ => false,
    }
}

#[must_use]
fn is_bit_op(op: BinOpKind) -> bool {
    use rustc_ast::ast::BinOpKind::{BitAnd, BitOr, BitXor, Shl, Shr};
    match op {
        BitXor | BitAnd | BitOr | Shl | Shr => true,
        _ => false,
    }
}

#[must_use]
fn is_arith_op(op: BinOpKind) -> bool {
    use rustc_ast::ast::BinOpKind::{Add, Div, Mul, Rem, Sub};
    match op {
        Add | Sub | Mul | Div | Rem => true,
        _ => false,
    }
}
<commit_msg>Integrate more idiomatic rust changes.<commit_after>use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Spanned;

const ODD_FUNCTIONS_WHITELIST: [&str; 14] = [
    "asin",
    "asinh",
    "atan",
    "atanh",
    "cbrt",
    "fract",
    "round",
    "signum",
    "sin",
    "sinh",
    "tan",
    "tanh",
    "to_degrees",
    "to_radians",
];

declare_clippy_lint! {
    /// **What it does:** Checks for operations where precedence may be unclear
    /// and suggests to add parentheses. Currently it catches the following:
    /// * mixed usage of arithmetic and bit shifting/combining operators without
    /// parentheses
    /// * a "negative" numeric literal (which is really a unary `-` followed by a
    /// numeric literal)
    ///   followed by a method call
    ///
    /// **Why is this bad?** Not everyone knows the precedence of those operators by
    /// heart, so expressions like these may trip others trying to reason about the
    /// code.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// * `1 << 2 + 3` equals 32, while `(1 << 2) + 3` equals 7
    /// * `-1i32.abs()` equals -1, while `(-1i32).abs()` equals 1
    pub PRECEDENCE,
    complexity,
    "operations where precedence may be unclear"
}

declare_lint_pass!(Precedence => [PRECEDENCE]);

impl EarlyLintPass for Precedence {
    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
        if expr.span.from_expansion() {
            return;
        }

        if let ExprKind::Binary(Spanned { node: op, .. }, ref left, ref right) = expr.kind {
            let span_sugg = |expr: &Expr, sugg, appl| {
                span_lint_and_sugg(
                    cx,
                    PRECEDENCE,
                    expr.span,
                    "operator precedence can trip the unwary",
                    "consider parenthesizing your expression",
                    sugg,
                    appl,
                );
            };

            if !is_bit_op(op) {
                return;
            }
            let mut applicability = Applicability::MachineApplicable;
            match (is_arith_expr(left), is_arith_expr(right)) {
                (true, true) => {
                    let sugg = format!(
                        "({}) {} ({})",
                        snippet_with_applicability(cx, left.span, "..", &mut applicability),
                        op.to_string(),
                        snippet_with_applicability(cx, right.span, "..", &mut applicability)
                    );
                    span_sugg(expr, sugg, applicability);
                },
                (true, false) => {
                    let sugg = format!(
                        "({}) {} {}",
                        snippet_with_applicability(cx, left.span, "..", &mut applicability),
                        op.to_string(),
                        snippet_with_applicability(cx, right.span, "..", &mut applicability)
                    );
                    span_sugg(expr, sugg, applicability);
                },
                (false, true) => {
                    let sugg = format!(
                        "{} {} ({})",
                        snippet_with_applicability(cx, left.span, "..", &mut applicability),
                        op.to_string(),
                        snippet_with_applicability(cx, right.span, "..", &mut applicability)
                    );
                    span_sugg(expr, sugg, applicability);
                },
                (false, false) => (),
            }
        }

        if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.kind {
            if let ExprKind::MethodCall(ref path_segment, ref args) = rhs.kind {
                let path_segment_str = path_segment.ident.name.as_str();
                if let Some(slf) = args.first() {
                    if let ExprKind::Lit(ref lit) = slf.kind {
                        match lit.kind {
                            LitKind::Int(..) | LitKind::Float(..) => {
                                if ODD_FUNCTIONS_WHITELIST
                                    .iter()
                                    .any(|odd_function| **odd_function == *path_segment_str)
                                {
                                    return;
                                }
                                let mut applicability = Applicability::MachineApplicable;
                                span_lint_and_sugg(
                                    cx,
                                    PRECEDENCE,
                                    expr.span,
                                    "unary minus has lower precedence than method call",
                                    "consider adding parentheses to clarify your intent",
                                    format!(
                                        "-({})",
                                        snippet_with_applicability(cx, rhs.span, "..", &mut applicability)
                                    ),
                                    applicability,
                                );
                            },
                            _ => (),
                        }
                    }
                }
            }
        }
    }
}

fn is_arith_expr(expr: &Expr) -> bool {
    match expr.kind {
        ExprKind::Binary(Spanned { node: op, .. }, _, _) => is_arith_op(op),
        _ => false,
    }
}

#[must_use]
fn is_bit_op(op: BinOpKind) -> bool {
    use rustc_ast::ast::BinOpKind::{BitAnd, BitOr, BitXor, Shl, Shr};
    match op {
        BitXor | BitAnd | BitOr | Shl | Shr => true,
        _ => false,
    }
}

#[must_use]
fn is_arith_op(op: BinOpKind) -> bool {
    use rustc_ast::ast::BinOpKind::{Add, Div, Mul, Rem, Sub};
    match op {
        Add | Sub | Mul | Div | Rem => true,
        _ => false,
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;

use std::io::Write;
use note::Note;
use note;
use std::fs::File;
use std::io::Error;
use std::str;
use std::string::String;
use std::io::Read;
use file_operations;

pub fn add_note(file: &mut File, note_content: String, id: usize) {

    if id <= 0 {
        panic!("The id for a note should be higher than zero.");
    }
    if note_content.is_empty() {
        panic!("The note should be provided a valid note content.");
    }

    let note = Note::new(id, note_content);
    let mut json_note = serde_json::to_string(&note).unwrap();
    json_note.push('\n');

    file.write_all(json_note.as_bytes());
}

pub fn remove_note(file: &mut File, id_input: String) {
    let mut contents: Vec<String> = Vec::new();
    let mut buffer = String::new();
    let mut id = 1;
    file.read_to_string(&mut buffer);

    let lines = buffer.lines();

    for line in lines {
        let mut note: Note = serde_json::from_str(line).unwrap();
        let id_as_number: usize = id_input.parse().unwrap();

        if id_as_number != note.get_id() {
            contents.push(note.get_content());
        }
    }
    file_operations::erase_file_content();

    for content in contents {
        add_note(file, content, id);
        id += 1;
    }
}

pub fn list_notes(file: &mut File) {

    let mut buffer = String::new();
    file.read_to_string(&mut buffer);

    let lines = buffer.lines();

    for line in lines {
        let note: Note = serde_json::from_str(line).unwrap();
        note.print();
    }
}

pub fn help() {
    println!("");
    println!("Usage : rusty-notes <command> [<args>]");
    println!("");

    println!("  add \"note\"   : Adds a new note which is between quotes.");
    println!("  list         : Prints all saved notes.");
    println!("  remove <id>  : Removes the note assigned to id.");
    println!("  help         : Prints help.");
}

pub fn number_of_notes(file: &mut File) -> usize {
    let mut buffer = String::new();
    file.read_to_string(&mut buffer);
    let lines = buffer.lines();
    lines.count()
}

#[cfg(test)]
mod tests {
    extern crate tempdir;
    use super::*;
    use self::tempdir::TempDir;

    fn create_temp_dir_and_file() -> (TempDir, File) {
        let dir = match TempDir::new("test_directory") {
            Ok(directory) => directory,
            Err(err) => panic!("Temporary directory could not be created"),
        };
        let file_path = dir.path().join("test_notes.txt");

        let mut file = match File::create(file_path) {
            Ok(f) => f,
            Err(err) => panic!("Could not create a testing file"),
        };
        (dir, file)
    }

    #[test]
    #[should_panic(expected = "The id for a note should be higher than zero.")]
    fn adding_a_note_without_id_should_panic() {
        let id = 0;
        let (dir, mut file) = create_temp_dir_and_file();

        add_note(&mut file, String::from("This is the content"), id);
        dir.close();
    }

    #[test]
    #[should_panic(expected = "The note should be provided a valid note content.")]
    fn adding_a_note_without_content_should_panic() {
        let (dir, mut file) = create_temp_dir_and_file();
        add_note(&mut file, String::from(""), 1);
        dir.close();
    }

    #[test]
    fn added_note_should_be_in_file() {
        let (dir, mut file) = create_temp_dir_and_file();
        let number_notes = number_of_notes(&mut file);
        assert_eq!(1, number_notes);
        dir.close();
    }
}
<commit_msg>Removed a test.<commit_after>extern crate serde;
extern crate serde_json;

use std::io::Write;
use note::Note;
use note;
use std::fs::File;
use std::io::Error;
use std::str;
use std::string::String;
use std::io::Read;
use file_operations;

pub fn add_note(file: &mut File, note_content: String, id: usize) {

    if id <= 0 {
        panic!("The id for a note should be higher than zero.");
    }
    if note_content.is_empty() {
        panic!("The note should be provided a valid note content.");
    }

    let note = Note::new(id, note_content);
    let mut json_note = serde_json::to_string(&note).unwrap();
    json_note.push('\n');

    file.write_all(json_note.as_bytes());
}

pub fn remove_note(file: &mut File, id_input: String) {
    let mut contents: Vec<String> = Vec::new();
    let mut buffer = String::new();
    let mut id = 1;
    file.read_to_string(&mut buffer);

    let lines = buffer.lines();

    for line in lines {
        let mut note: Note = serde_json::from_str(line).unwrap();
        let id_as_number: usize = id_input.parse().unwrap();

        if id_as_number != note.get_id() {
            contents.push(note.get_content());
        }
    }
    file_operations::erase_file_content();

    for content in contents {
        add_note(file, content, id);
        id += 1;
    }
}

pub fn list_notes(file: &mut File) {

    let mut buffer = String::new();
    file.read_to_string(&mut buffer);

    let lines = buffer.lines();

    for line in lines {
        let note: Note = serde_json::from_str(line).unwrap();
        note.print();
    }
}

pub fn help() {
    println!("");
    println!("Usage : rusty-notes <command> [<args>]");
    println!("");

    println!("  add \"note\"   : Adds a new note which is between quotes.");
    println!("  list         : Prints all saved notes.");
    println!("  remove <id>  : Removes the note assigned to id.");
    println!("  help         : Prints help.");
}

pub fn number_of_notes(file: &mut File) -> usize {
    let mut buffer = String::new();
    file.read_to_string(&mut buffer);
    let lines = buffer.lines();
    lines.count()
}

#[cfg(test)]
mod tests {
    extern crate tempdir;
    use super::*;
    use self::tempdir::TempDir;

    fn create_temp_dir_and_file() -> (TempDir, File) {
        let dir = match TempDir::new("test_directory") {
            Ok(directory) => directory,
            Err(err) => panic!("Temporary directory could not be created"),
        };
        let file_path = dir.path().join("test_notes.txt");

        let mut file = match File::create(file_path) {
            Ok(f) => f,
            Err(err) => panic!("Could not create a testing file"),
        };
        (dir, file)
    }

    #[test]
    #[should_panic(expected = "The id for a note should be higher than zero.")]
    fn adding_a_note_without_id_should_panic() {
        let id = 0;
        let (dir, mut file) = create_temp_dir_and_file();

        add_note(&mut file, String::from("This is the content"), id);
        dir.close();
    }

    #[test]
    #[should_panic(expected = "The note should be provided a valid note content.")]
    fn adding_a_note_without_content_should_panic() {
        let (dir, mut file) = create_temp_dir_and_file();
        add_note(&mut file, String::from(""), 1);
        dir.close();
    }
}
<|endoftext|>


<commit_before>// TODO: remove below
#![allow(dead_code)]

//let leftBlockDelim: String = "{%".to_string();
//let rightBlockDelim: String = "%}".to_string();
const LEFT_VARIABLE_DELIM: &'static str  = "{{";
const RIGHT_VARIABLE_DELIM: &'static str  = "}}";

// List of token types to emit to the parser.
// Different from the state enum despite some identical members
#[derive(PartialEq, Debug)]
pub enum TokenType {
  Text, // HTML text etc
  Space,
  //BlockStart,
  //BlockEnd,
  VariableStart, // {{
  VariableEnd, // }}
  Variable, // variable name, tera keywords
}

// List of different states the scanner can be in
#[derive(Debug)]
enum State {
  Text,
  VariableStart,
  VariableEnd,
  InsideBlock,
  Number,
  Variable,
}

#[derive(PartialEq, Debug)]
pub struct Token {
  kind: TokenType,
  value: String,
}

impl Token {
  pub fn new(kind: TokenType, value: &str) -> Token {
    Token {
      kind: kind,
      value: value.to_string()
    }
  }
}

#[derive(Debug)]
pub struct Scanner {
  name: String,
  input: String,
  chars: Vec<(usize, char)>,
  state: State,
  position: usize, // where we are in the chars vec
  start_position: usize, // where the current state started

  input_bytes_position: u32, // where we are in the input by bytes
}

impl Scanner {
  pub fn new(input: &str) -> Scanner {
    Scanner {
      name: "test".to_string(),
      input: input.to_string(),
      chars: input.char_indices().collect(),
      state: State::Text,
      position: 0,
      start_position: 0,
      input_bytes_position: 0,
    }
  }

  // We know we have {{ with self.position being on the first
  fn lex_left_variable_delimiter(&mut self) -> Token {
    self.position += 2;
    self.state = State::InsideBlock;

    Token::new(TokenType::VariableStart, "{{")
  }

  // TODO: see if we can simplify below
  fn lex_text(&mut self) -> Token {
    // Gets all chars until we reach {{ (only that for now)
    self.start_position = self.chars[self.position].0;
    let mut next_char_pos = self.chars[self.position].0;

    loop {
      if self.input[next_char_pos..].starts_with(LEFT_VARIABLE_DELIM) {
        self.state = State::VariableStart;
        break;
      }
      // TODO: add leftBlockDelim as the variable one

      // got to EOF
      if self.position == self.chars.len() - 1 {
        next_char_pos = self.input.len();
        break;
      }
      self.position += 1;
    }

    Token::new(
      TokenType::Text,
      &self.input[self.start_position..next_char_pos]
    )
  }
}

impl Iterator for Scanner {
  type Item = Token;

  fn next(&mut self) -> Option<Token> {
    // Empty template
    if self.input.len() == 0 {
      return None;
    }

    // Got to the end
    if self.position == self.chars.len() - 1 {
      return None;
    }

    match self.state {
      State::Text => Some(self.lex_text()),
      State::VariableStart => Some(self.lex_left_variable_delimiter()),
      _ => None,
    }
  }
}

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

  #[derive(Debug)]
  struct LexerTest {
    name: String,
    input: String,
    expected: Vec<Token>
  }

  impl LexerTest {
    pub fn new(name: &str, input: &str, expected: Vec<Token>) -> LexerTest {
      LexerTest {
        name: name.to_string(),
        input: input.to_string(),
        expected: expected
      }
    }
  }

  fn text_token(value: &str) -> Token {
    Token::new(TokenType::Text, value)
  }

  fn variable_token(value: &str) -> Token {
    Token::new(TokenType::Variable, value)
  }

  fn variable_start_token() -> Token {
    Token::new(TokenType::VariableStart, "{{")
  }

  fn variable_end_token() -> Token {
    Token::new(TokenType::VariableEnd, "}}")
  }

  fn space_token() -> Token {
    Token::new(TokenType::Space, " ")
  }

  fn check_if_correct(expected: Vec<Token>, obtained: Vec<Token>) -> bool {
    if expected.len() != obtained.len() {
      return false;
    }

    for i in 0..expected.len() {
      if expected[i].kind != obtained[i].kind {
        return false;
      }

      if expected[i].value != obtained[i].value {
        return false;
      }
    }
    return true;
  }

  #[test]
  fn test_lexer() {
    let tests: Vec<LexerTest> = vec![
      LexerTest::new("empty", "", vec![]),
      LexerTest::new("only text", "Hello 世界", vec![text_token("Hello 世界")]),
      LexerTest::new("only variable", "{{ greeting }}", vec![
        variable_start_token(),
        space_token(),
        variable_token("greeting"),
        space_token(),
        variable_end_token()
      ]),
      // LexerTest::new("variable and text", "{{ greeting }} 世界", vec![
      //   variable_start_token(),
      //   space_token(),
      //   variable_token("greeting"),
      //   space_token(),
      //   variable_end_token(),
      //   text_token(" 世界")
      // ]),
    ];

    for test in tests {
      println!("{:?}", test.name);
      let tokens: Vec<Token> = Scanner::new(&test.input).collect();
      if tokens.len() != test.expected.len() {
        println!("Test {} failed: different number of tokens.", test.name);
        assert!(false);
      }

      if check_if_correct(test.expected, tokens) {
        assert!(true);
      } else {
        println!("Test {} failed: different tokens", test.name);
        assert!(false);
      }
    }
  }
}
<commit_msg>Basic lexing for variable blocks<commit_after>// TODO: remove below
#![allow(dead_code)]

//let leftBlockDelim: String = "{%".to_string();
//let rightBlockDelim: String = "%}".to_string();
const LEFT_VARIABLE_DELIM: &'static str  = "{{";
const RIGHT_VARIABLE_DELIM: &'static str  = "}}";

// List of token types to emit to the parser.
// Different from the state enum despite some identical members
#[derive(PartialEq, Debug)]
pub enum TokenType {
  Text, // HTML text etc
  Space,
  //BlockStart,
  //BlockEnd,
  VariableStart, // {{
  VariableEnd, // }}
  Variable, // variable name, tera keywords
}

// List of different states the scanner can be in
#[derive(Debug)]
enum State {
  Text,
  VariableStart,
  VariableEnd,
  InsideBlock,
  Variable,
  Operator, // an operator in a block, such as * in {{ price * 100 }}
  Number, // a number in a block, such as 100 in {{ price * 100 }}
}

#[derive(PartialEq, Debug)]
pub struct Token {
  kind: TokenType,
  value: String,
}

impl Token {
  pub fn new(kind: TokenType, value: &str) -> Token {
    Token {
      kind: kind,
      value: value.to_string()
    }
  }
}

#[derive(Debug)]
pub struct Scanner {
  name: String,
  input: String,
  chars: Vec<(usize, char)>, // (bytes index, char)
  index: usize, // where we are in the chars vec
  state: State,
  start_position: usize, // where the current state started
}

impl Scanner {
  pub fn new(input: &str) -> Scanner {
    Scanner {
      name: "test".to_string(),
      input: input.to_string(),
      chars: input.char_indices().collect(),
      index: 0,
      state: State::Text,
      start_position: 0,
    }
  }

  // We know we have {{ with self.index being on the first
  fn lex_left_variable_delimiter(&mut self) -> Option<Token> {
    self.index += 2;
    self.state = State::InsideBlock;

    Some(Token::new(TokenType::VariableStart, "{{"))
  }

  // TODO: merge with the one above?
  fn lex_right_variable_delimiter(&mut self) -> Option<Token> {
    self.index += 2;
    self.state = State::Text;

    Some(Token::new(TokenType::VariableEnd, "}}"))
  }

  // TODO: see if we can simplify below
  fn lex_text(&mut self) -> Option<Token> {
    // Gets all chars until we reach {{ (only that for now)
    self.start_position = self.chars[self.index].0;
    let mut next_index = self.chars[self.index].0;

    loop {
      if self.input[next_index..].starts_with(LEFT_VARIABLE_DELIM) {
        self.state = State::VariableStart;

        // If we have a delim right at the beginning
        if next_index == 0 {
          return self.lex_left_variable_delimiter();
        }
        break;
      }
      // TODO: add leftBlockDelim as the variable one

      // got to EOF
      if self.index == self.chars.len() - 1 {
        next_index = self.input.len();
        break;
      }
      self.index += 1;
    }

    Some(Token::new(
      TokenType::Text,
      &self.input[self.start_position..next_index]
    ))
  }

  // We know we have a space, we need to figure out how many
  fn lex_space(&mut self) -> Option<Token> {
    self.start_position = self.chars[self.index].0;

    loop {
      if !self.chars[self.index].1.is_whitespace() {
        break;
      }

      self.index += 1;
    }

    Some(Token::new(
      TokenType::Space,
      &self.input[self.start_position..self.chars[self.index].0]
    ))
  }

  fn lex_variable(&mut self) -> Option<Token> {
    self.start_position = self.chars[self.index].0;

    loop {
      let current = self.chars[self.index].1;
      if current == '.' || current.is_whitespace() {
        break;
      }
      self.index += 1;
    }

    Some(Token::new(
      TokenType::Variable,
      &self.input[self.start_position..self.chars[self.index].0]
    ))
  }

  // Works for both {{ }} and {% %}
  fn lex_inside_block(&mut self) -> Option<Token> {
    match self.chars[self.index].1 {
      x if x.is_whitespace() => return self.lex_space(),
      x if x.is_alphabetic() || x == '_' => return self.lex_variable(),
      '}' => return self.lex_right_variable_delimiter(),
      _ => None,
    }

  }
}

impl Iterator for Scanner {
  type Item = Token;

  fn next(&mut self) -> Option<Token> {
    // Empty template
    // TODO: maybe put it in lex_text if we return an Option?
    if self.input.len() == 0 {
      return None;
    }

    // Got to the end
    if self.index >= self.chars.len() - 1 {
      return None;
    }

    match self.state {
      State::Text => self.lex_text(),
      State::VariableStart => self.lex_left_variable_delimiter(),
      State::InsideBlock => self.lex_inside_block(),
      _ => None,
    }
  }
}

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

  #[derive(Debug)]
  struct LexerTest {
    name: String,
    input: String,
    expected: Vec<Token>
  }

  impl LexerTest {
    pub fn new(name: &str, input: &str, expected: Vec<Token>) -> LexerTest {
      LexerTest {
        name: name.to_string(),
        input: input.to_string(),
        expected: expected
      }
    }
  }

  fn text_token(value: &str) -> Token {
    Token::new(TokenType::Text, value)
  }

  fn variable_token(value: &str) -> Token {
    Token::new(TokenType::Variable, value)
  }

  fn variable_start_token() -> Token {
    Token::new(TokenType::VariableStart, "{{")
  }

  fn variable_end_token() -> Token {
    Token::new(TokenType::VariableEnd, "}}")
  }

  fn space_token() -> Token {
    Token::new(TokenType::Space, " ")
  }

  fn check_if_correct(expected: &Vec<Token>, obtained: &Vec<Token>) -> bool {
    if expected.len() != obtained.len() {
      return false;
    }

    for i in 0..expected.len() {
      if expected[i].kind != obtained[i].kind {
        return false;
      }

      if expected[i].value != obtained[i].value {
        return false;
      }
    }
    return true;
  }

  #[test]
  fn test_lexer() {
    let tests: Vec<LexerTest> = vec![
      LexerTest::new("empty", "", vec![]),
      LexerTest::new("only text", "Hello 世界", vec![text_token("Hello 世界")]),
      LexerTest::new("only variable", "{{ greeting }}", vec![
        variable_start_token(),
        space_token(),
        variable_token("greeting"),
        space_token(),
        variable_end_token()
      ]),
      // LexerTest::new("variable and text", "{{ greeting }} 世界", vec![
      //   variable_start_token(),
      //   space_token(),
      //   variable_token("greeting"),
      //   space_token(),
      //   variable_end_token(),
      //   text_token(" 世界")
      // ]),
    ];

    for test in tests {
      let tokens: Vec<Token> = Scanner::new(&test.input).collect();
      if tokens.len() != test.expected.len() {
        println!("Test {} failed: different number of tokens.", test.name);
        println!("Expected: {:?}", test.expected);
        println!("Got: {:?}", tokens);
        assert!(false);
      }

      if check_if_correct(&test.expected, &tokens) {
        assert!(true);
      } else {
        println!("Test {} failed: different tokens", test.name);
        println!("Expected: {:?}", test.expected);
        println!("Got: {:?}", tokens);
        assert!(false);
      }
    }
  }
}
<|endoftext|>