<commit_before>use sass::value_part::ValuePart;
use sass::op::Op;
use value_tokenizer::ValueTokenizer;

use std::borrow::Cow::Borrowed;
use std::collections::HashMap;
extern crate collections;

#[derive(Debug)]
pub struct Evaluator<'a, T> {
    value_tokens: T,
    variables: Option<&'a HashMap<String, String>>,
    value_stack: Vec<ValuePart<'a>>,
    op_stack: Vec<Op>,
    paren_level: i32,
}

impl<'a> Evaluator<'a, ValueTokenizer<'a>> {
    pub fn new_from_string(original: &'a str, variables: &'a HashMap<String, String>) -> Evaluator<'a, ValueTokenizer<'a>>
    {
        Evaluator {
            value_tokens: ValueTokenizer::new(&original),
            variables: Some(&variables),
            value_stack: Vec::new(),
            op_stack: Vec::new(),
            paren_level: 0,
        }
    }
}

impl<'a> Evaluator<'a, collections::vec::IntoIter<ValuePart<'a>>> {
    pub fn new(value_tokens: Vec<ValuePart<'a>>) -> Evaluator<'a, collections::vec::IntoIter<ValuePart<'a>>>
    {
        Evaluator {
            value_tokens: value_tokens.into_iter(),
            variables: None,
            value_stack: Vec::new(),
            op_stack: Vec::new(),
            paren_level: 0,
        }
    }
}

impl<'a, T> Evaluator<'a, T>
where T: Iterator<Item = ValuePart<'a>>
{
    pub fn evaluate(&mut self) -> ValuePart<'a> {
        let mut last_was_an_operator = true;

        while let Some(part) = self.value_tokens.next() {
            match part {
                ValuePart::Variable(name) => {
                    match self.variables {
                        Some(vars) => {
                            match vars.get(&(*name).to_string()) {
                                Some(ref v) => self.value_stack.push(ValuePart::String(Borrowed(v))),
                                None => self.value_stack.push(ValuePart::String(name)),
                            }
                        },
                        None => self.value_stack.push(ValuePart::String(name)),
                    }
                    last_was_an_operator = false;
                },
                s @ ValuePart::String(..) => {
                    self.value_stack.push(s);
                    last_was_an_operator = false;
                },
                n @ ValuePart::Number(..) | n @ ValuePart::NumberUnits(..) => {
                    if last_was_an_operator {
                        self.value_stack.push(n);
                    } else {
                        while !self.op_stack.is_empty() && self.op_stack.last() != Some(&Op::LeftParen) {
                            self.math_machine();
                        }
                        let list_starter = self.value_stack.pop().expect("No expected list starter on the value stack!");
                        let list_parts = match list_starter {
                            ValuePart::List(mut v) => {
                                v.push(n);
                                v
                            },
                            other => vec![other, n],
                        };
                        self.value_stack.push(ValuePart::List(list_parts));
                    }
                    last_was_an_operator = false;
                },
                ValuePart::Operator(ref o) => {
                    if *o == Op::RightParen {
                        let mut last_operator = self.op_stack.last().unwrap_or(&Op::LeftParen).clone();
                        while last_operator != Op::LeftParen {
                            self.math_machine();
                            last_operator = self.op_stack.last().unwrap_or(&Op::LeftParen).clone();
                        }
                        self.op_stack.pop();
                        last_was_an_operator = false;
                        self.paren_level -= 1;
                    } else if *o == Op::LeftParen {
                        self.op_stack.push(*o);
                        last_was_an_operator = true;
                        self.paren_level += 1;
                    } else {
                        if let Some(&last_operator) = self.op_stack.last() {
                            if last_operator.same_or_greater_precedence(*o) {
                                self.math_machine();
                            }
                        }
                        self.op_stack.push(*o);
                        last_was_an_operator = true;
                    }
                },
                _ => unreachable!(),
            }
        }

        while !self.op_stack.is_empty() {
            self.math_machine();
        }

        if self.value_stack.len() > 1 {
            // TODO: figure out how to make borrowck like not cloning this, it's cool i swear
            ValuePart::List(self.value_stack.clone())
        } else {
            self.value_stack.pop().unwrap_or(ValuePart::Number(0.0))
        }
    }

    fn math_machine(&mut self) {
        let op = self.op_stack.pop().unwrap_or(Op::Plus);
        let second = self.value_stack.pop().unwrap_or(ValuePart::Number(0.0));
        let first  = self.value_stack.pop().unwrap_or(ValuePart::Number(0.0));
        self.value_stack.push(op.apply(first, second, self.paren_level));
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use sass::value_part::ValuePart;
    use sass::op::Op;
    use std::collections::HashMap;
    use std::borrow::Cow::Borrowed;

    #[test]
    fn it_subtitutes_variable_values() {
        let mut vars = HashMap::new();
        vars.insert("$bar".to_string(), "4".to_string());
        vars.insert("$quux".to_string(), "3px 10px".to_string());

        let answer = Evaluator::new_from_string("foo $bar 199.82 baz $quux", &vars).evaluate();

        assert_eq!(
            ValuePart::List(vec![
                ValuePart::String(Borrowed("foo")),
                ValuePart::List(vec![
                    ValuePart::String(Borrowed("4")),
                    ValuePart::Number(199.82)
                ]),
                ValuePart::String(Borrowed("baz")),
                ValuePart::String(Borrowed("3px 10px"))
            ]),
            answer
        );
    }

    #[test]
    fn it_adds() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(1.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Number(2.0),
        ]).evaluate();
        assert_eq!(ValuePart::Computed(3.0), answer);
    }

    #[test]
    fn it_divides_and_adds_with_the_right_precedence() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(4.0),
        ]).evaluate();
        assert_eq!(ValuePart::Computed(3.75), answer);
    }

    #[test]
    fn it_gets_the_right_precedence_with_parens() {
        let answer = Evaluator::new(vec![
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::RightParen),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(4.0),
        ]).evaluate();
        assert_eq!(ValuePart::Computed(1.5), answer);
    }

    #[test]
    fn it_does_string_concat_when_adding_to_list() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(2.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(3.0),
            ValuePart::Number(4.0),
            ValuePart::Operator(Op::RightParen),
        ]).evaluate();

        assert_eq!(ValuePart::List(vec![
            ValuePart::String(Borrowed("23")),
            ValuePart::Number(4.0)
        ]), answer);
    }

    #[test]
    fn it_does_string_concat_when_adding_to_list_in_a_list() {
        let answer = Evaluator::new(vec![
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(2.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(3.0),
            ValuePart::Number(4.0),
            ValuePart::Operator(Op::RightParen),
            ValuePart::Number(5.0),
            ValuePart::Operator(Op::RightParen),
        ]).evaluate();

        assert_eq!(ValuePart::List(vec![
            ValuePart::String(Borrowed("23")),
            ValuePart::Number(4.0),
            ValuePart::Number(5.0)
        ]), answer);
    }

    #[test]
    fn it_divides_because_parens_and_string_concats_because_list() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(1.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(5.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(10.0),
            ValuePart::Number(2.0),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::RightParen),
        ]).evaluate();

        assert_eq!(ValuePart::List(vec![
            ValuePart::String(Borrowed("10.5")),
            ValuePart::Number(2.0),
            ValuePart::Number(3.0)
        ]), answer);
    }

    #[test]
    fn it_does_not_divide_when_slash_is_separating() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(15.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(5.0),
        ]).evaluate();

        assert_eq!(ValuePart::List(vec![
            ValuePart::Number(15.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(5.0),
        ]), answer);
    }
}<commit_msg>Test case for 1/2 + 1/2<commit_after>use sass::value_part::ValuePart;
use sass::op::Op;
use value_tokenizer::ValueTokenizer;

use std::borrow::Cow::Borrowed;
use std::collections::HashMap;
extern crate collections;

#[derive(Debug)]
pub struct Evaluator<'a, T> {
    value_tokens: T,
    variables: Option<&'a HashMap<String, String>>,
    value_stack: Vec<ValuePart<'a>>,
    op_stack: Vec<Op>,
    paren_level: i32,
}

impl<'a> Evaluator<'a, ValueTokenizer<'a>> {
    pub fn new_from_string(original: &'a str, variables: &'a HashMap<String, String>) -> Evaluator<'a, ValueTokenizer<'a>>
    {
        Evaluator {
            value_tokens: ValueTokenizer::new(&original),
            variables: Some(&variables),
            value_stack: Vec::new(),
            op_stack: Vec::new(),
            paren_level: 0,
        }
    }
}

impl<'a> Evaluator<'a, collections::vec::IntoIter<ValuePart<'a>>> {
    pub fn new(value_tokens: Vec<ValuePart<'a>>) -> Evaluator<'a, collections::vec::IntoIter<ValuePart<'a>>>
    {
        Evaluator {
            value_tokens: value_tokens.into_iter(),
            variables: None,
            value_stack: Vec::new(),
            op_stack: Vec::new(),
            paren_level: 0,
        }
    }
}

impl<'a, T> Evaluator<'a, T>
where T: Iterator<Item = ValuePart<'a>>
{
    pub fn evaluate(&mut self) -> ValuePart<'a> {
        let mut last_was_an_operator = true;

        while let Some(part) = self.value_tokens.next() {
            match part {
                ValuePart::Variable(name) => {
                    match self.variables {
                        Some(vars) => {
                            match vars.get(&(*name).to_string()) {
                                Some(ref v) => self.value_stack.push(ValuePart::String(Borrowed(v))),
                                None => self.value_stack.push(ValuePart::String(name)),
                            }
                        },
                        None => self.value_stack.push(ValuePart::String(name)),
                    }
                    last_was_an_operator = false;
                },
                s @ ValuePart::String(..) => {
                    self.value_stack.push(s);
                    last_was_an_operator = false;
                },
                n @ ValuePart::Number(..) | n @ ValuePart::NumberUnits(..) => {
                    if last_was_an_operator {
                        self.value_stack.push(n);
                    } else {
                        while !self.op_stack.is_empty() && self.op_stack.last() != Some(&Op::LeftParen) {
                            self.math_machine();
                        }
                        let list_starter = self.value_stack.pop().expect("No expected list starter on the value stack!");
                        let list_parts = match list_starter {
                            ValuePart::List(mut v) => {
                                v.push(n);
                                v
                            },
                            other => vec![other, n],
                        };
                        self.value_stack.push(ValuePart::List(list_parts));
                    }
                    last_was_an_operator = false;
                },
                ValuePart::Operator(ref o) => {
                    if *o == Op::RightParen {
                        let mut last_operator = self.op_stack.last().unwrap_or(&Op::LeftParen).clone();
                        while last_operator != Op::LeftParen {
                            self.math_machine();
                            last_operator = self.op_stack.last().unwrap_or(&Op::LeftParen).clone();
                        }
                        self.op_stack.pop();
                        last_was_an_operator = false;
                        self.paren_level -= 1;
                    } else if *o == Op::LeftParen {
                        self.op_stack.push(*o);
                        last_was_an_operator = true;
                        self.paren_level += 1;
                    } else {
                        if let Some(&last_operator) = self.op_stack.last() {
                            if last_operator.same_or_greater_precedence(*o) {
                                self.math_machine();
                            }
                        }
                        self.op_stack.push(*o);
                        last_was_an_operator = true;
                    }
                },
                _ => unreachable!(),
            }
        }

        while !self.op_stack.is_empty() {
            self.math_machine();
        }

        if self.value_stack.len() > 1 {
            // TODO: figure out how to make borrowck like not cloning this, it's cool i swear
            ValuePart::List(self.value_stack.clone())
        } else {
            self.value_stack.pop().unwrap_or(ValuePart::Number(0.0))
        }
    }

    fn math_machine(&mut self) {
        let op = self.op_stack.pop().unwrap_or(Op::Plus);
        let second = self.value_stack.pop().unwrap_or(ValuePart::Number(0.0));
        let first  = self.value_stack.pop().unwrap_or(ValuePart::Number(0.0));
        self.value_stack.push(op.apply(first, second, self.paren_level));
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use sass::value_part::ValuePart;
    use sass::op::Op;
    use std::collections::HashMap;
    use std::borrow::Cow::Borrowed;

    #[test]
    fn it_subtitutes_variable_values() {
        let mut vars = HashMap::new();
        vars.insert("$bar".to_string(), "4".to_string());
        vars.insert("$quux".to_string(), "3px 10px".to_string());

        let answer = Evaluator::new_from_string("foo $bar 199.82 baz $quux", &vars).evaluate();

        assert_eq!(
            ValuePart::List(vec![
                ValuePart::String(Borrowed("foo")),
                ValuePart::List(vec![
                    ValuePart::String(Borrowed("4")),
                    ValuePart::Number(199.82)
                ]),
                ValuePart::String(Borrowed("baz")),
                ValuePart::String(Borrowed("3px 10px"))
            ]),
            answer
        );
    }

    #[test]
    fn it_adds() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(1.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Number(2.0),
        ]).evaluate();
        assert_eq!(ValuePart::Computed(3.0), answer);
    }

    #[test]
    fn it_divides_and_adds_with_the_right_precedence() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(4.0),
        ]).evaluate();
        assert_eq!(ValuePart::Computed(3.75), answer);
    }

    #[test]
    fn it_gets_the_right_precedence_with_parens() {
        let answer = Evaluator::new(vec![
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::RightParen),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(4.0),
        ]).evaluate();
        assert_eq!(ValuePart::Computed(1.5), answer);
    }

    #[test]
    fn it_does_string_concat_when_adding_to_list() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(2.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(3.0),
            ValuePart::Number(4.0),
            ValuePart::Operator(Op::RightParen),
        ]).evaluate();

        assert_eq!(ValuePart::List(vec![
            ValuePart::String(Borrowed("23")),
            ValuePart::Number(4.0)
        ]), answer);
    }

    #[test]
    fn it_does_string_concat_when_adding_to_list_in_a_list() {
        let answer = Evaluator::new(vec![
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(2.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(3.0),
            ValuePart::Number(4.0),
            ValuePart::Operator(Op::RightParen),
            ValuePart::Number(5.0),
            ValuePart::Operator(Op::RightParen),
        ]).evaluate();

        assert_eq!(ValuePart::List(vec![
            ValuePart::String(Borrowed("23")),
            ValuePart::Number(4.0),
            ValuePart::Number(5.0)
        ]), answer);
    }

    #[test]
    fn it_divides_because_parens_and_string_concats_because_list() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(1.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Operator(Op::LeftParen),
            ValuePart::Number(5.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(10.0),
            ValuePart::Number(2.0),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::RightParen),
        ]).evaluate();

        assert_eq!(ValuePart::List(vec![
            ValuePart::String(Borrowed("10.5")),
            ValuePart::Number(2.0),
            ValuePart::Number(3.0)
        ]), answer);
    }

    #[test]
    fn it_does_not_divide_when_slash_is_separating() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(15.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(5.0),
        ]).evaluate();

        assert_eq!(ValuePart::List(vec![
            ValuePart::Number(15.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(3.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(5.0),
        ]), answer);
    }

    #[test]
    fn it_does_divide_when_other_math_is_involved() {
        let answer = Evaluator::new(vec![
            ValuePart::Number(1.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(2.0),
            ValuePart::Operator(Op::Plus),
            ValuePart::Number(1.0),
            ValuePart::Operator(Op::Slash),
            ValuePart::Number(2.0),
        ]).evaluate();

        assert_eq!(ValuePart::Number(1.0), answer);
    }
}<|endoftext|>


<commit_before>use alloc::boxed::Box;
use core::fmt::{self, Debug, Display};

/// Exception thrown from an `extern "C++"` function.
#[derive(Debug)]
pub struct Exception {
    pub(crate) what: Box<str>,
}

impl Display for Exception {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.what)
    }
}

impl std::error::Error for Exception {}

impl Exception {
    pub fn what(&self) -> &str {
        &self.what
    }
}
<commit_msg>Clean up unneeded Debug derive macro import<commit_after>use alloc::boxed::Box;
use core::fmt::{self, Display};

/// Exception thrown from an `extern "C++"` function.
#[derive(Debug)]
pub struct Exception {
    pub(crate) what: Box<str>,
}

impl Display for Exception {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.what)
    }
}

impl std::error::Error for Exception {}

impl Exception {
    pub fn what(&self) -> &str {
        &self.what
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use num_derive::FromPrimitive;

use crate::api::ChromaSampling;
use crate::context::SB_SIZE;
use crate::mc::SUBPEL_FILTER_SIZE;
use crate::util::*;

#[cfg(test)]
use crate::tiling::*;

mod plane;
pub use plane::*;

const FRAME_MARGIN: usize = 16 + SUBPEL_FILTER_SIZE;

/// Override the frame type decision
///
/// Only certain frame types can be selected.
#[derive(Debug, PartialEq, Clone, Copy, FromPrimitive)]
#[repr(C)]
pub enum FrameTypeOverride {
  /// Do not force any decision.
  No,
  /// Force the frame to be a Keyframe.
  Key,
}

/// Optional per-frame encoder parameters
#[derive(Debug, Clone, Copy)]
pub struct FrameParameters {
  /// Force emitted frame to be of the type selected
  pub frame_type_override: FrameTypeOverride,
}

#[derive(Debug, Clone)]
pub struct Frame<T: Pixel> {
  pub planes: [Plane<T>; 3],
}

impl<T: Pixel> Frame<T> {
  pub fn new(
    width: usize, height: usize, chroma_sampling: ChromaSampling,
  ) -> Self {
    let luma_width = width.align_power_of_two(3);
    let luma_height = height.align_power_of_two(3);
    let luma_padding = SB_SIZE + FRAME_MARGIN;

    let (chroma_decimation_x, chroma_decimation_y) =
      chroma_sampling.get_decimation().unwrap_or((0, 0));
    let (chroma_width, chroma_height) =
      chroma_sampling.get_chroma_dimensions(luma_width, luma_height);
    let chroma_padding_x = luma_padding >> chroma_decimation_x;
    let chroma_padding_y = luma_padding >> chroma_decimation_y;

    Frame {
      planes: [
        Plane::new(luma_width, luma_height, 0, 0, luma_padding, luma_padding),
        Plane::new(
          chroma_width,
          chroma_height,
          chroma_decimation_x,
          chroma_decimation_y,
          chroma_padding_x,
          chroma_padding_y,
        ),
        Plane::new(
          chroma_width,
          chroma_height,
          chroma_decimation_x,
          chroma_decimation_y,
          chroma_padding_x,
          chroma_padding_y,
        ),
      ],
    }
  }

  pub(crate) fn pad(&mut self, w: usize, h: usize) {
    for p in self.planes.iter_mut() {
      p.pad(w, h);
    }
  }

  #[inline(always)]
  #[cfg(test)]
  pub(crate) fn as_tile(&self) -> Tile<'_, T> {
    let PlaneConfig { width, height, .. } = self.planes[0].cfg;
    Tile::new(self, TileRect { x: 0, y: 0, width, height })
  }

  #[inline(always)]
  #[cfg(test)]
  pub fn as_tile_mut(&mut self) -> TileMut<'_, T> {
    let PlaneConfig { width, height, .. } = self.planes[0].cfg;
    TileMut::new(self, TileRect { x: 0, y: 0, width, height })
  }

  /// Returns a `PixelIter` containing the data of this frame's planes in YUV format.
  /// Each point in the `PixelIter` is a triple consisting of a Y, U, and V component.
  /// The `PixelIter` is laid out as contiguous rows, e.g. to get a given 0-indexed row
  /// you could use `data.skip(width * row_idx).take(width)`.
  ///
  /// This data retains any padding, e.g. it uses the width and height specifed in
  /// the Y-plane's `cfg` struct, and not the display width and height specied in
  /// `FrameInvariants`.
  pub(crate) fn iter(&self) -> PixelIter<'_, T> {
    PixelIter::new(&self.planes)
  }
}

#[derive(Debug)]
pub(crate) struct PixelIter<'a, T: Pixel> {
  planes: &'a [Plane<T>; 3],
  y: usize,
  x: usize,
}

impl<'a, T: Pixel> PixelIter<'a, T> {
  pub fn new(planes: &'a [Plane<T>; 3]) -> Self {
    PixelIter { planes, y: 0, x: 0 }
  }

  fn width(&self) -> usize {
    self.planes[0].cfg.width
  }

  fn height(&self) -> usize {
    self.planes[0].cfg.height
  }
}

impl<'a, T: Pixel> Iterator for PixelIter<'a, T> {
  type Item = (T, T, T);

  fn next(&mut self) -> Option<<Self as Iterator>::Item> {
    if self.y == self.height() - 1 && self.x == self.width() - 1 {
      return None;
    }
    let pixel = (
      self.planes[0].p(self.x, self.y),
      self.planes[1].p(
        self.x >> self.planes[1].cfg.xdec,
        self.y >> self.planes[1].cfg.ydec,
      ),
      self.planes[2].p(
        self.x >> self.planes[2].cfg.xdec,
        self.y >> self.planes[2].cfg.ydec,
      ),
    );
    if self.x == self.width() - 1 {
      self.x = 0;
      self.y += 1;
    } else {
      self.x += 1;
    }
    Some(pixel)
  }
}
<commit_msg>Document Frame<commit_after>// Copyright (c) 2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use num_derive::FromPrimitive;

use crate::api::ChromaSampling;
use crate::context::SB_SIZE;
use crate::mc::SUBPEL_FILTER_SIZE;
use crate::util::*;

#[cfg(test)]
use crate::tiling::*;

mod plane;
pub use plane::*;

const FRAME_MARGIN: usize = 16 + SUBPEL_FILTER_SIZE;

/// Override the frame type decision
///
/// Only certain frame types can be selected.
#[derive(Debug, PartialEq, Clone, Copy, FromPrimitive)]
#[repr(C)]
pub enum FrameTypeOverride {
  /// Do not force any decision.
  No,
  /// Force the frame to be a Keyframe.
  Key,
}

/// Optional per-frame encoder parameters
#[derive(Debug, Clone, Copy)]
pub struct FrameParameters {
  /// Force emitted frame to be of the type selected
  pub frame_type_override: FrameTypeOverride,
}

/// One video frame.
#[derive(Debug, Clone)]
pub struct Frame<T: Pixel> {
  /// Planes constituting the frame.
  pub planes: [Plane<T>; 3],
}

impl<T: Pixel> Frame<T> {
  /// Creates a new frame with the given parameters.
  ///
  /// Allocates data for the planes.
  pub fn new(
    width: usize, height: usize, chroma_sampling: ChromaSampling,
  ) -> Self {
    let luma_width = width.align_power_of_two(3);
    let luma_height = height.align_power_of_two(3);
    let luma_padding = SB_SIZE + FRAME_MARGIN;

    let (chroma_decimation_x, chroma_decimation_y) =
      chroma_sampling.get_decimation().unwrap_or((0, 0));
    let (chroma_width, chroma_height) =
      chroma_sampling.get_chroma_dimensions(luma_width, luma_height);
    let chroma_padding_x = luma_padding >> chroma_decimation_x;
    let chroma_padding_y = luma_padding >> chroma_decimation_y;

    Frame {
      planes: [
        Plane::new(luma_width, luma_height, 0, 0, luma_padding, luma_padding),
        Plane::new(
          chroma_width,
          chroma_height,
          chroma_decimation_x,
          chroma_decimation_y,
          chroma_padding_x,
          chroma_padding_y,
        ),
        Plane::new(
          chroma_width,
          chroma_height,
          chroma_decimation_x,
          chroma_decimation_y,
          chroma_padding_x,
          chroma_padding_y,
        ),
      ],
    }
  }

  pub(crate) fn pad(&mut self, w: usize, h: usize) {
    for p in self.planes.iter_mut() {
      p.pad(w, h);
    }
  }

  #[inline(always)]
  #[cfg(test)]
  pub(crate) fn as_tile(&self) -> Tile<'_, T> {
    let PlaneConfig { width, height, .. } = self.planes[0].cfg;
    Tile::new(self, TileRect { x: 0, y: 0, width, height })
  }

  #[inline(always)]
  #[cfg(test)]
  pub fn as_tile_mut(&mut self) -> TileMut<'_, T> {
    let PlaneConfig { width, height, .. } = self.planes[0].cfg;
    TileMut::new(self, TileRect { x: 0, y: 0, width, height })
  }

  /// Returns a `PixelIter` containing the data of this frame's planes in YUV format.
  /// Each point in the `PixelIter` is a triple consisting of a Y, U, and V component.
  /// The `PixelIter` is laid out as contiguous rows, e.g. to get a given 0-indexed row
  /// you could use `data.skip(width * row_idx).take(width)`.
  ///
  /// This data retains any padding, e.g. it uses the width and height specifed in
  /// the Y-plane's `cfg` struct, and not the display width and height specied in
  /// `FrameInvariants`.
  pub(crate) fn iter(&self) -> PixelIter<'_, T> {
    PixelIter::new(&self.planes)
  }
}

#[derive(Debug)]
pub(crate) struct PixelIter<'a, T: Pixel> {
  planes: &'a [Plane<T>; 3],
  y: usize,
  x: usize,
}

impl<'a, T: Pixel> PixelIter<'a, T> {
  pub fn new(planes: &'a [Plane<T>; 3]) -> Self {
    PixelIter { planes, y: 0, x: 0 }
  }

  fn width(&self) -> usize {
    self.planes[0].cfg.width
  }

  fn height(&self) -> usize {
    self.planes[0].cfg.height
  }
}

impl<'a, T: Pixel> Iterator for PixelIter<'a, T> {
  type Item = (T, T, T);

  fn next(&mut self) -> Option<<Self as Iterator>::Item> {
    if self.y == self.height() - 1 && self.x == self.width() - 1 {
      return None;
    }
    let pixel = (
      self.planes[0].p(self.x, self.y),
      self.planes[1].p(
        self.x >> self.planes[1].cfg.xdec,
        self.y >> self.planes[1].cfg.ydec,
      ),
      self.planes[2].p(
        self.x >> self.planes[2].cfg.xdec,
        self.y >> self.planes[2].cfg.ydec,
      ),
    );
    if self.x == self.width() - 1 {
      self.x = 0;
      self.y += 1;
    } else {
      self.x += 1;
    }
    Some(pixel)
  }
}
<|endoftext|>


<commit_before>
#![crate_name = "geoip"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_upper_case_globals,
        unused_qualifications)]
#![feature(libc, path, std_misc, net)]

extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate "geoip-sys" as geoip_sys;

use libc::{c_char, c_int, c_ulong};
use std::ffi;
use std::fmt;
use std::net::IpAddr;

#[cfg(test)]
use std::str::FromStr;

enum Charset {
    UTF8 = 1
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

impl Copy for Options { }

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

impl Copy for DBType { }

pub struct GeoIp {
    db: geoip_sys::RawGeoIp
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct ASInfo {
    pub asn: u32,
    pub name: String,
    pub netmask: u32
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct CityInfo {
    pub country_code: Option<String>,
    pub country_code3: Option<String>,
    pub country_name: Option<String>,
    pub region: Option<String>,
    pub city: Option<String>,
    pub postal_code: Option<String>,
    pub latitude: f32,
    pub longitude: f32,
    pub dma_code: u32,
    pub area_code: u32,
    pub charset: u32,
    pub continent_code: Option<String>,
    pub netmask: u32
}

fn maybe_string(c_str: *const c_char) -> Option<String> {
    if c_str.is_null() {
        None
    } else {
        String::from_utf8(unsafe { ffi::c_str_to_bytes(&c_str) }.to_vec()).ok()
    }
}

impl CityInfo {
    unsafe fn from_geoiprecord(res: &geoip_sys::GeoIpRecord) -> CityInfo {
        CityInfo {
            country_code: maybe_string(res.country_code),
            country_code3: maybe_string(res.country_code3),
            country_name: maybe_string(res.country_name),
            region: maybe_string(res.region),
            city: maybe_string(res.city),
            postal_code: maybe_string(res.postal_code),
            latitude: res.latitude as f32,
            longitude: res.longitude as f32,
            dma_code: res.dma_code as u32,
            area_code: res.area_code as u32,
            charset: res.charset as u32,
            continent_code: maybe_string(res.continent_code),
            netmask: res.netmask as u32
        }
    }
}

impl fmt::Debug for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

enum CNetworkIp {
    V4(c_ulong),
    V6(geoip_sys::In6Addr)
}

impl CNetworkIp {
    fn new(ip: IpAddr) -> CNetworkIp {
        match ip {
            IpAddr::V4(addr) => {
                let b = addr.octets();
                CNetworkIp::V4(((b[0] as c_ulong) << 24) |
                               ((b[1] as c_ulong) << 16) |
                               ((b[2] as c_ulong) << 8)  |
                               ((b[3] as c_ulong)))
            },
            IpAddr::V6(addr) => {
                let b = addr.segments();
                CNetworkIp::V6([(b[0] >> 8) as u8, b[0] as u8,
                                (b[1] >> 8) as u8, b[1] as u8,
                                (b[2] >> 8) as u8, b[2] as u8,
                                (b[3] >> 8) as u8, b[3] as u8,
                                (b[4] >> 8) as u8, b[4] as u8,
                                (b[5] >> 8) as u8, b[5] as u8,
                                (b[6] >> 8) as u8, b[6] as u8,
                                (b[7] >> 8) as u8, b[7] as u8])
            }
        }
    }
}

impl GeoIp {
    pub fn open(path: &Path, options: Options) -> Result<GeoIp, String> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            geoip_sys::GeoIP_open(ffi::CString::from_slice(file.as_bytes()).as_ptr(),
                                  options as c_int)
        };
        if db.is_null() {
            return Err(format!("Can't open {}", file));
        }
        if unsafe { geoip_sys::GeoIP_set_charset(db, Charset::UTF8 as c_int)
        } != 0 {
            return Err("Can't set charset to UTF8".to_string());
        }
        Ok(GeoIp { db: db })
    }

    pub fn city_info_by_ip(&self, ip: IpAddr) -> Option<CityInfo> {
        let cres = match CNetworkIp::new(ip) {
            CNetworkIp::V4(ip) => unsafe {
                geoip_sys::GeoIP_record_by_ipnum(self.db, ip) },
            CNetworkIp::V6(ip) => unsafe {
                geoip_sys::GeoIP_record_by_ipnum_v6(self.db, ip) }
        };

        if cres.is_null() { return None; }

        unsafe {
            let city_info = CityInfo::from_geoiprecord(&*cres);
            geoip_sys::GeoIPRecord_delete(cres);
            std::mem::forget(cres);
            Some(city_info)
        }
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let mut gl = geoip_sys::GeoIpLookup::new();
        let cres = match CNetworkIp::new(ip) {
            CNetworkIp::V4(ip) => unsafe {
                geoip_sys::GeoIP_name_by_ipnum_gl(self.db, ip, &mut gl) },
            CNetworkIp::V6(ip) => unsafe {
                geoip_sys::GeoIP_name_by_ipnum_v6_gl(self.db, ip, &mut gl) }
        };

        if cres.is_null() {
            return None;
        }
        let description = match maybe_string(cres) {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(1, ' ');
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    asn[2..].parse::<u32>().unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let as_info = ASInfo {
            asn: asn,
            name: name.to_string(),
            netmask: gl.netmask as u32
        };
        Some(as_info)
    }
}

impl Drop for GeoIp {
    fn drop(&mut self) {
        unsafe {
            geoip_sys::GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIp::open(&Path::new("/opt/geoip/GeoIPASNum.dat"), Options::MemoryCache) {
        Err(err) => panic!(err),
        Ok(geoip) => geoip
    };
    let ip = FromStr::from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.contains("Telefun"));
    assert!(res.netmask == 22);
}

#[test]
fn geoip_test_city() {
    let geoip = match GeoIp::open(&Path::new("/opt/geoip/GeoLiteCity.dat"), Options::MemoryCache) {
        Err(err) => panic!(err),
        Ok(geoip) => geoip
    };
    let ip = FromStr::from_str("8.8.8.8").unwrap();
    let res = geoip.city_info_by_ip(ip).unwrap();
    assert!(res.city.unwrap() == "Mountain View");
}
<commit_msg>Path needs to be updated<commit_after>
#![crate_name = "geoip"]
#![crate_type = "rlib"]

#![warn(non_camel_case_types,
        non_upper_case_globals,
        unused_qualifications)]
#![feature(libc, std_misc, net)]

extern crate libc;
extern crate "rustc-serialize" as rustc_serialize;
extern crate "geoip-sys" as geoip_sys;

use libc::{c_char, c_int, c_ulong};
use std::ffi;
use std::fmt;
use std::net::IpAddr;

#[cfg(test)]
use std::str::FromStr;

enum Charset {
    UTF8 = 1
}

pub enum Options {
    Standard = 0,
    MemoryCache = 1,
    CheckCache = 2,
    IndexCache = 4,
    MmapCache = 8
}

impl Copy for Options { }

pub enum DBType {
    CountryEdition = 1,
    RegionEditionRev0 = 7,
    CityEditionRev0 = 6,
    ORGEdition = 5,
    ISPEdition = 4,
    CityEditionRev1 = 2,
    RegionEditionRev1 = 3,
    ProxyEdition = 8,
    ASNUMEdition = 9,
    NetSpeedEdition = 10,
    DomainEdition = 11,
    CountryEditionV6 = 12,
    LocationAEdition = 13,
    AccuracyRadiusEdition = 14,
    LargeCountryEdition = 17,
    LargeCountryEditionV6 = 18,
    ASNumEditionV6 = 21,
    ISPEditionV6 = 22,
    ORGEditionV6 = 23,
    DomainEditionV6 = 24,
    LoctionAEditionV6 = 25,
    RegistrarEdition = 26,
    RegistrarEditionV6 = 27,
    UserTypeEdition = 28,
    UserTypeEditionV6 = 29,
    CityEditionRev1V6 = 30,
    CityEditionRev0V6 = 31,
    NetSpeedEditionRev1 = 32,
    NetSpeedEditionRev1V6 = 33,
    CountryConfEdition = 34,
    CityConfEdition = 35,
    RegionConfEdition = 36,
    PostalConfEdition = 37,
    AccuracyRadiusEditionV6 = 38
}

impl Copy for DBType { }

pub struct GeoIp {
    db: geoip_sys::RawGeoIp
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct ASInfo {
    pub asn: u32,
    pub name: String,
    pub netmask: u32
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct CityInfo {
    pub country_code: Option<String>,
    pub country_code3: Option<String>,
    pub country_name: Option<String>,
    pub region: Option<String>,
    pub city: Option<String>,
    pub postal_code: Option<String>,
    pub latitude: f32,
    pub longitude: f32,
    pub dma_code: u32,
    pub area_code: u32,
    pub charset: u32,
    pub continent_code: Option<String>,
    pub netmask: u32
}

fn maybe_string(c_str: *const c_char) -> Option<String> {
    if c_str.is_null() {
        None
    } else {
        String::from_utf8(unsafe { ffi::c_str_to_bytes(&c_str) }.to_vec()).ok()
    }
}

impl CityInfo {
    unsafe fn from_geoiprecord(res: &geoip_sys::GeoIpRecord) -> CityInfo {
        CityInfo {
            country_code: maybe_string(res.country_code),
            country_code3: maybe_string(res.country_code3),
            country_name: maybe_string(res.country_name),
            region: maybe_string(res.region),
            city: maybe_string(res.city),
            postal_code: maybe_string(res.postal_code),
            latitude: res.latitude as f32,
            longitude: res.longitude as f32,
            dma_code: res.dma_code as u32,
            area_code: res.area_code as u32,
            charset: res.charset as u32,
            continent_code: maybe_string(res.continent_code),
            netmask: res.netmask as u32
        }
    }
}

impl fmt::Debug for ASInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}\t{}", self.asn, self.name)
    }
}

enum CNetworkIp {
    V4(c_ulong),
    V6(geoip_sys::In6Addr)
}

impl CNetworkIp {
    fn new(ip: IpAddr) -> CNetworkIp {
        match ip {
            IpAddr::V4(addr) => {
                let b = addr.octets();
                CNetworkIp::V4(((b[0] as c_ulong) << 24) |
                               ((b[1] as c_ulong) << 16) |
                               ((b[2] as c_ulong) << 8)  |
                               ((b[3] as c_ulong)))
            },
            IpAddr::V6(addr) => {
                let b = addr.segments();
                CNetworkIp::V6([(b[0] >> 8) as u8, b[0] as u8,
                                (b[1] >> 8) as u8, b[1] as u8,
                                (b[2] >> 8) as u8, b[2] as u8,
                                (b[3] >> 8) as u8, b[3] as u8,
                                (b[4] >> 8) as u8, b[4] as u8,
                                (b[5] >> 8) as u8, b[5] as u8,
                                (b[6] >> 8) as u8, b[6] as u8,
                                (b[7] >> 8) as u8, b[7] as u8])
            }
        }
    }
}

impl GeoIp {
    pub fn open(path: &Path, options: Options) -> Result<GeoIp, String> {
        let file = match path.as_str() {
            None => return Err(format!("Invalid path {}", path.display())),
            Some(file) => file
        };
        let db = unsafe {
            geoip_sys::GeoIP_open(ffi::CString::from_slice(file.as_bytes()).as_ptr(),
                                  options as c_int)
        };
        if db.is_null() {
            return Err(format!("Can't open {}", file));
        }
        if unsafe { geoip_sys::GeoIP_set_charset(db, Charset::UTF8 as c_int)
        } != 0 {
            return Err("Can't set charset to UTF8".to_string());
        }
        Ok(GeoIp { db: db })
    }

    pub fn city_info_by_ip(&self, ip: IpAddr) -> Option<CityInfo> {
        let cres = match CNetworkIp::new(ip) {
            CNetworkIp::V4(ip) => unsafe {
                geoip_sys::GeoIP_record_by_ipnum(self.db, ip) },
            CNetworkIp::V6(ip) => unsafe {
                geoip_sys::GeoIP_record_by_ipnum_v6(self.db, ip) }
        };

        if cres.is_null() { return None; }

        unsafe {
            let city_info = CityInfo::from_geoiprecord(&*cres);
            geoip_sys::GeoIPRecord_delete(cres);
            std::mem::forget(cres);
            Some(city_info)
        }
    }

    pub fn as_info_by_ip(&self, ip: IpAddr) -> Option<ASInfo> {
        let mut gl = geoip_sys::GeoIpLookup::new();
        let cres = match CNetworkIp::new(ip) {
            CNetworkIp::V4(ip) => unsafe {
                geoip_sys::GeoIP_name_by_ipnum_gl(self.db, ip, &mut gl) },
            CNetworkIp::V6(ip) => unsafe {
                geoip_sys::GeoIP_name_by_ipnum_v6_gl(self.db, ip, &mut gl) }
        };

        if cres.is_null() {
            return None;
        }
        let description = match maybe_string(cres) {
            None => return None,
            Some(description) => description
        };
        let mut di = description.splitn(1, ' ');
        let asn = match di.next() {
            None => return None,
            Some(asn) => {
                if ! asn.starts_with("AS") {
                    return None
                } else {
                    asn[2..].parse::<u32>().unwrap()
                }
            }
        };
        let name = di.next().unwrap_or("(none)");
        let as_info = ASInfo {
            asn: asn,
            name: name.to_string(),
            netmask: gl.netmask as u32
        };
        Some(as_info)
    }
}

impl Drop for GeoIp {
    fn drop(&mut self) {
        unsafe {
            geoip_sys::GeoIP_delete(self.db);
        }
    }
}

#[test]
fn geoip_test_basic() {
    let geoip = match GeoIp::open(&Path::new("/opt/geoip/GeoIPASNum.dat"), Options::MemoryCache) {
        Err(err) => panic!(err),
        Ok(geoip) => geoip
    };
    let ip = FromStr::from_str("91.203.184.192").unwrap();
    let res = geoip.as_info_by_ip(ip).unwrap();
    assert!(res.asn == 41064);
    assert!(res.name.contains("Telefun"));
    assert!(res.netmask == 22);
}

#[test]
fn geoip_test_city() {
    let geoip = match GeoIp::open(&Path::new("/opt/geoip/GeoLiteCity.dat"), Options::MemoryCache) {
        Err(err) => panic!(err),
        Ok(geoip) => geoip
    };
    let ip = FromStr::from_str("8.8.8.8").unwrap();
    let res = geoip.city_info_by_ip(ip).unwrap();
    assert!(res.city.unwrap() == "Mountain View");
}
<|endoftext|>


<commit_before>#![cfg(not(debug_assertions))]
/// Tests the available fork-choice algorithms
pub use beacon_chain::BeaconChain;
use bls::Signature;
use store::MemoryStore;
use store::Store;
// use env_logger::{Builder, Env};
use fork_choice::{BitwiseLMDGhost, ForkChoice, LongestChain, OptimizedLMDGhost, SlowLMDGhost};
use std::collections::HashMap;
use std::sync::Arc;
use std::{fs::File, io::prelude::*, path::PathBuf};
use types::test_utils::TestingBeaconStateBuilder;
use types::{
    BeaconBlock, BeaconBlockBody, Eth1Data, EthSpec, Hash256, Keypair, MainnetEthSpec, Slot,
};
use yaml_rust::yaml;

// Note: We Assume the block Id's are hex-encoded.

#[test]
fn test_optimized_lmd_ghost() {
    // set up logging
    // Builder::from_env(Env::default().default_filter_or("trace")).init();

    test_yaml_vectors::<OptimizedLMDGhost<MemoryStore, MainnetEthSpec>>(
        "tests/lmd_ghost_test_vectors.yaml",
        100,
    );
}

#[test]
fn test_bitwise_lmd_ghost() {
    // set up logging
    //Builder::from_env(Env::default().default_filter_or("trace")).init();

    test_yaml_vectors::<BitwiseLMDGhost<MemoryStore, MainnetEthSpec>>(
        "tests/bitwise_lmd_ghost_test_vectors.yaml",
        100,
    );
}

#[test]
fn test_slow_lmd_ghost() {
    test_yaml_vectors::<SlowLMDGhost<MemoryStore, MainnetEthSpec>>(
        "tests/lmd_ghost_test_vectors.yaml",
        100,
    );
}

#[test]
fn test_longest_chain() {
    test_yaml_vectors::<LongestChain<MemoryStore>>("tests/longest_chain_test_vectors.yaml", 100);
}

// run a generic test over given YAML test vectors
fn test_yaml_vectors<T: ForkChoice<MemoryStore>>(
    yaml_file_path: &str,
    emulated_validators: usize, // the number of validators used to give weights.
) {
    // load test cases from yaml
    let test_cases = load_test_cases_from_yaml(yaml_file_path);

    // default vars
    let spec = MainnetEthSpec::default_spec();
    let zero_hash = Hash256::zero();
    let eth1_data = Eth1Data {
        deposit_count: 0,
        deposit_root: zero_hash.clone(),
        block_hash: zero_hash.clone(),
    };
    let randao_reveal = Signature::empty_signature();
    let signature = Signature::empty_signature();
    let body = BeaconBlockBody {
        eth1_data,
        randao_reveal,
        graffiti: [0; 32],
        proposer_slashings: vec![],
        attester_slashings: vec![],
        attestations: vec![],
        deposits: vec![],
        voluntary_exits: vec![],
        transfers: vec![],
    };

    // process the tests
    for test_case in test_cases {
        // setup a fresh test
        let (mut fork_choice, store, state_root) = setup_inital_state::<T>(emulated_validators);

        // keep a hashmap of block_id's to block_hashes (random hashes to abstract block_id)
        //let mut block_id_map: HashMap<String, Hash256> = HashMap::new();
        // keep a list of hash to slot
        let mut block_slot: HashMap<Hash256, Slot> = HashMap::new();
        // assume the block tree is given to us in order.
        let mut genesis_hash = None;
        for block in test_case["blocks"].clone().into_vec().unwrap() {
            let block_id = block["id"].as_str().unwrap().to_string();
            let parent_id = block["parent"].as_str().unwrap().to_string();

            // default params for genesis
            let block_hash = id_to_hash(&block_id);
            let mut slot = spec.genesis_slot;
            let previous_block_root = id_to_hash(&parent_id);

            // set the slot and parent based off the YAML. Start with genesis;
            // if not the genesis, update slot
            if parent_id != block_id {
                // find parent slot
                slot = *(block_slot
                    .get(&previous_block_root)
                    .expect("Parent should have a slot number"))
                    + 1;
            } else {
                genesis_hash = Some(block_hash);
            }

            // update slot mapping
            block_slot.insert(block_hash, slot);

            // build the BeaconBlock
            let beacon_block = BeaconBlock {
                slot,
                previous_block_root,
                state_root: state_root.clone(),
                signature: signature.clone(),
                body: body.clone(),
            };

            // Store the block.
            store.put(&block_hash, &beacon_block).unwrap();

            // run add block for fork choice if not genesis
            if parent_id != block_id {
                fork_choice
                    .add_block(&beacon_block, &block_hash, &spec)
                    .unwrap();
            }
        }

        // add the weights (attestations)
        let mut current_validator = 0;
        for id_map in test_case["weights"].clone().into_vec().unwrap() {
            // get the block id and weights
            for (map_id, map_weight) in id_map.as_hash().unwrap().iter() {
                let id = map_id.as_str().unwrap();
                let block_root = id_to_hash(&id.to_string());
                let weight = map_weight.as_i64().unwrap();
                // we assume a validator has a value 1 and add an attestation for to achieve the
                // correct weight
                for _ in 0..weight {
                    assert!(
                        current_validator <= emulated_validators,
                        "Not enough validators to emulate weights"
                    );
                    fork_choice
                        .add_attestation(current_validator as u64, &block_root, &spec)
                        .unwrap();
                    current_validator += 1;
                }
            }
        }

        // everything is set up, run the fork choice, using genesis as the head
        let head = fork_choice
            .find_head(&genesis_hash.unwrap(), &spec)
            .unwrap();

        // compare the result to the expected test
        let success = test_case["heads"]
            .clone()
            .into_vec()
            .unwrap()
            .iter()
            .find(|heads| id_to_hash(&heads["id"].as_str().unwrap().to_string()) == head)
            .is_some();

        println!("Head found: {}", head);
        assert!(success, "Did not find one of the possible heads");
    }
}

// loads the test_cases from the supplied yaml file
fn load_test_cases_from_yaml(file_path: &str) -> Vec<yaml_rust::Yaml> {
    // load the yaml
    let mut file = {
        let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        file_path_buf.push(file_path);
        File::open(file_path_buf).unwrap()
    };
    let mut yaml_str = String::new();
    file.read_to_string(&mut yaml_str).unwrap();
    let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap();
    let doc = &docs[0];
    doc["test_cases"].as_vec().unwrap().clone()
}

fn setup_inital_state<T>(
    // fork_choice_algo: &ForkChoiceAlgorithm,
    num_validators: usize
) -> (T, Arc<MemoryStore>, Hash256)
where
    T: ForkChoice<MemoryStore>,
{
    let store = Arc::new(MemoryStore::open());

    let fork_choice = ForkChoice::new(store.clone());
    let spec = MainnetEthSpec::default_spec();

    let mut state_builder: TestingBeaconStateBuilder<MainnetEthSpec> =
        TestingBeaconStateBuilder::from_single_keypair(num_validators, &Keypair::random(), &spec);
    state_builder.build_caches(&spec).unwrap();
    let (state, _keypairs) = state_builder.build();

    let state_root = state.canonical_root();
    store.put(&state_root, &state).unwrap();

    // return initialised vars
    (fork_choice, store, state_root)
}

// convert a block_id into a Hash256 -- assume input is hex encoded;
fn id_to_hash(id: &String) -> Hash256 {
    let bytes = hex::decode(id).expect("Block ID should be hex");

    let len = std::cmp::min(bytes.len(), 32);
    let mut fixed_bytes = [0u8; 32];
    for (index, byte) in bytes.iter().take(32).enumerate() {
        fixed_bytes[32 - len + index] = *byte;
    }
    Hash256::from(fixed_bytes)
}
<commit_msg>Run rustfmt with updated cargo<commit_after>#![cfg(not(debug_assertions))]
/// Tests the available fork-choice algorithms
pub use beacon_chain::BeaconChain;
use bls::Signature;
use store::MemoryStore;
use store::Store;
// use env_logger::{Builder, Env};
use fork_choice::{BitwiseLMDGhost, ForkChoice, LongestChain, OptimizedLMDGhost, SlowLMDGhost};
use std::collections::HashMap;
use std::sync::Arc;
use std::{fs::File, io::prelude::*, path::PathBuf};
use types::test_utils::TestingBeaconStateBuilder;
use types::{
    BeaconBlock, BeaconBlockBody, Eth1Data, EthSpec, Hash256, Keypair, MainnetEthSpec, Slot,
};
use yaml_rust::yaml;

// Note: We Assume the block Id's are hex-encoded.

#[test]
fn test_optimized_lmd_ghost() {
    // set up logging
    // Builder::from_env(Env::default().default_filter_or("trace")).init();

    test_yaml_vectors::<OptimizedLMDGhost<MemoryStore, MainnetEthSpec>>(
        "tests/lmd_ghost_test_vectors.yaml",
        100,
    );
}

#[test]
fn test_bitwise_lmd_ghost() {
    // set up logging
    //Builder::from_env(Env::default().default_filter_or("trace")).init();

    test_yaml_vectors::<BitwiseLMDGhost<MemoryStore, MainnetEthSpec>>(
        "tests/bitwise_lmd_ghost_test_vectors.yaml",
        100,
    );
}

#[test]
fn test_slow_lmd_ghost() {
    test_yaml_vectors::<SlowLMDGhost<MemoryStore, MainnetEthSpec>>(
        "tests/lmd_ghost_test_vectors.yaml",
        100,
    );
}

#[test]
fn test_longest_chain() {
    test_yaml_vectors::<LongestChain<MemoryStore>>("tests/longest_chain_test_vectors.yaml", 100);
}

// run a generic test over given YAML test vectors
fn test_yaml_vectors<T: ForkChoice<MemoryStore>>(
    yaml_file_path: &str,
    emulated_validators: usize, // the number of validators used to give weights.
) {
    // load test cases from yaml
    let test_cases = load_test_cases_from_yaml(yaml_file_path);

    // default vars
    let spec = MainnetEthSpec::default_spec();
    let zero_hash = Hash256::zero();
    let eth1_data = Eth1Data {
        deposit_count: 0,
        deposit_root: zero_hash.clone(),
        block_hash: zero_hash.clone(),
    };
    let randao_reveal = Signature::empty_signature();
    let signature = Signature::empty_signature();
    let body = BeaconBlockBody {
        eth1_data,
        randao_reveal,
        graffiti: [0; 32],
        proposer_slashings: vec![],
        attester_slashings: vec![],
        attestations: vec![],
        deposits: vec![],
        voluntary_exits: vec![],
        transfers: vec![],
    };

    // process the tests
    for test_case in test_cases {
        // setup a fresh test
        let (mut fork_choice, store, state_root) = setup_inital_state::<T>(emulated_validators);

        // keep a hashmap of block_id's to block_hashes (random hashes to abstract block_id)
        //let mut block_id_map: HashMap<String, Hash256> = HashMap::new();
        // keep a list of hash to slot
        let mut block_slot: HashMap<Hash256, Slot> = HashMap::new();
        // assume the block tree is given to us in order.
        let mut genesis_hash = None;
        for block in test_case["blocks"].clone().into_vec().unwrap() {
            let block_id = block["id"].as_str().unwrap().to_string();
            let parent_id = block["parent"].as_str().unwrap().to_string();

            // default params for genesis
            let block_hash = id_to_hash(&block_id);
            let mut slot = spec.genesis_slot;
            let previous_block_root = id_to_hash(&parent_id);

            // set the slot and parent based off the YAML. Start with genesis;
            // if not the genesis, update slot
            if parent_id != block_id {
                // find parent slot
                slot = *(block_slot
                    .get(&previous_block_root)
                    .expect("Parent should have a slot number"))
                    + 1;
            } else {
                genesis_hash = Some(block_hash);
            }

            // update slot mapping
            block_slot.insert(block_hash, slot);

            // build the BeaconBlock
            let beacon_block = BeaconBlock {
                slot,
                previous_block_root,
                state_root: state_root.clone(),
                signature: signature.clone(),
                body: body.clone(),
            };

            // Store the block.
            store.put(&block_hash, &beacon_block).unwrap();

            // run add block for fork choice if not genesis
            if parent_id != block_id {
                fork_choice
                    .add_block(&beacon_block, &block_hash, &spec)
                    .unwrap();
            }
        }

        // add the weights (attestations)
        let mut current_validator = 0;
        for id_map in test_case["weights"].clone().into_vec().unwrap() {
            // get the block id and weights
            for (map_id, map_weight) in id_map.as_hash().unwrap().iter() {
                let id = map_id.as_str().unwrap();
                let block_root = id_to_hash(&id.to_string());
                let weight = map_weight.as_i64().unwrap();
                // we assume a validator has a value 1 and add an attestation for to achieve the
                // correct weight
                for _ in 0..weight {
                    assert!(
                        current_validator <= emulated_validators,
                        "Not enough validators to emulate weights"
                    );
                    fork_choice
                        .add_attestation(current_validator as u64, &block_root, &spec)
                        .unwrap();
                    current_validator += 1;
                }
            }
        }

        // everything is set up, run the fork choice, using genesis as the head
        let head = fork_choice
            .find_head(&genesis_hash.unwrap(), &spec)
            .unwrap();

        // compare the result to the expected test
        let success = test_case["heads"]
            .clone()
            .into_vec()
            .unwrap()
            .iter()
            .find(|heads| id_to_hash(&heads["id"].as_str().unwrap().to_string()) == head)
            .is_some();

        println!("Head found: {}", head);
        assert!(success, "Did not find one of the possible heads");
    }
}

// loads the test_cases from the supplied yaml file
fn load_test_cases_from_yaml(file_path: &str) -> Vec<yaml_rust::Yaml> {
    // load the yaml
    let mut file = {
        let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
        file_path_buf.push(file_path);
        File::open(file_path_buf).unwrap()
    };
    let mut yaml_str = String::new();
    file.read_to_string(&mut yaml_str).unwrap();
    let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap();
    let doc = &docs[0];
    doc["test_cases"].as_vec().unwrap().clone()
}

fn setup_inital_state<T>(
    // fork_choice_algo: &ForkChoiceAlgorithm,
    num_validators: usize,
) -> (T, Arc<MemoryStore>, Hash256)
where
    T: ForkChoice<MemoryStore>,
{
    let store = Arc::new(MemoryStore::open());

    let fork_choice = ForkChoice::new(store.clone());
    let spec = MainnetEthSpec::default_spec();

    let mut state_builder: TestingBeaconStateBuilder<MainnetEthSpec> =
        TestingBeaconStateBuilder::from_single_keypair(num_validators, &Keypair::random(), &spec);
    state_builder.build_caches(&spec).unwrap();
    let (state, _keypairs) = state_builder.build();

    let state_root = state.canonical_root();
    store.put(&state_root, &state).unwrap();

    // return initialised vars
    (fork_choice, store, state_root)
}

// convert a block_id into a Hash256 -- assume input is hex encoded;
fn id_to_hash(id: &String) -> Hash256 {
    let bytes = hex::decode(id).expect("Block ID should be hex");

    let len = std::cmp::min(bytes.len(), 32);
    let mut fixed_bytes = [0u8; 32];
    for (index, byte) in bytes.iter().take(32).enumerate() {
        fixed_bytes[32 - len + index] = *byte;
    }
    Hash256::from(fixed_bytes)
}
<|endoftext|>


<commit_before>//	MIT License
//
//  Copyright © 2017 Michael J Simms. All rights reserved.
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in all
//	copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//	SOFTWARE.

use std::collections::HashSet;
use std::collections::HashMap;

/// Each feature has a name and value.
pub struct Feature {
    name: String,
    value: u64,
}

impl Feature {
    pub fn new (name: &str, value: u64) -> Feature {
        Feature { name: name.to_string(), value: value }
    }

    pub fn set_name(&mut self, name: String) {
        self.name = name;
    }

    pub fn get_name(&self) -> String {
        self.name
    }

    pub fn set_value(&mut self, value: u64) {
        self.value = value;
    }

    pub fn get_value(&self) -> u64 {
        self.value
    }
}

pub type FeatureList = Vec<Feature>;
pub type Uint64Set = HashSet<u64>;
pub type FeatureNameToValuesMap<'a> = HashMap<&'a str, Uint64Set>;

/// This class represents a sample.
/// Each sample has a name and list of features.
pub struct Sample {
    name: String,
    features: FeatureList,
}

impl Sample {
    pub fn new (name: &str) -> Sample {
        Sample { name: name.to_string(), features: Sample::create_feature_list() }
    }

    fn create_feature_list() -> FeatureList {
        let mut v: FeatureList = vec![];
        v
    }

    pub fn add_features(&mut self, features: &mut FeatureList) {
        self.features.append(features);
    }

    pub fn add_feature(&mut self, feature: Feature) {
        self.features.push(feature);
    }

    pub fn features(&self) -> FeatureList {
        self.features
    }
}

pub type SampleList = Vec<Sample>;

/// Tree node, used internally.
struct Node {
    feature_name: String,
    left: Option<Box<Node>>,
    right: Option<Box<Node>>,
}

impl Node {
    pub fn new (feature_name: &str) -> Node {
        Node { feature_name: feature_name.to_string(), left: None, right: None }
    }

    fn get_feature_name(&self) -> String {
        self.feature_name
    }

	fn set_left_subtree(&mut self, subtree: NodeLink) {
		self.left = subtree;
	}

	fn set_right_subtree(&mut self, subtree: NodeLink) {
		self.right = subtree;
	}
}

type NodeLink = Option<Box<Node>>;
pub type NodeList = Vec<Node>;

/// Isolation Forest implementation.
pub struct Forest<'a> {
    featureValues: FeatureNameToValuesMap<'a>, // Lists each feature and maps it to all unique values in the training set
    trees: NodeList, // The decision trees that comprise the forest
    numTreesToCreate: u32, // The maximum number of trees to create
    subSamplingSize: u32, // The maximum depth of a tree
}

impl<'a> Forest<'a> {
    pub fn new (numTreesToCreate: u32, subSamplingSize: u32) -> Forest<'a> {
        Forest { numTreesToCreate: numTreesToCreate, subSamplingSize: subSamplingSize, trees: Forest::create_trees(), featureValues: Forest::create_feature_name_to_values_map() }
    }

    fn create_trees() -> NodeList {
        let mut v: NodeList = vec![];
        v
    }

    fn create_feature_name_to_values_map() -> FeatureNameToValuesMap<'a> {
        let mut m = HashMap::new();
        m
    }

    pub fn add_sample(&self, sample: Sample) {
		// Add each of this sample's features to the list of known features
		// with the corresponding set of unique values.
		let mut features = sample.features();
        for feature in &features {
            let mut found_feature = false;
        }
    }

    pub fn create(&self) {
    	for i in 0..self.numTreesToCreate {
            let tree = Forest::create_trees();
        }
    }

    fn score_tree(&self, sample: Sample, tree: Node) -> f64 {
        let mut depth = 0.0;
        let mut current_node = tree;
        let mut done = false;
        while !done {
            let mut found_feature = false;
            let feature_name = current_node.get_feature_name();
            let features = sample.features();
            for feature in features {

            }
        }
        depth
    }

    pub fn score(&self, sample: Sample) -> f64 {
        let mut score = 0.0;

        if self.trees.len() > 0 {
            for tree in self.trees {
                score += self.score_tree(sample, tree);
            }
            score /= self.trees.len() as f64;
        }
        score
    }
}
<commit_msg>Another backup commit.<commit_after>//	MIT License
//
//  Copyright © 2017 Michael J Simms. All rights reserved.
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in all
//	copies or substantial portions of the Software.
//
//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
//	SOFTWARE.

use std::collections::HashSet;
use std::collections::HashMap;

/// Each feature has a name and value.
pub struct Feature {
    name: String,
    value: u64,
}

impl Feature {
    pub fn new (name: &str, value: u64) -> Feature {
        Feature { name: name.to_string(), value: value }
    }

    pub fn set_name(&mut self, name: String) {
        self.name = name;
    }

    pub fn get_name(&self) -> String {
        self.name
    }

    pub fn set_value(&mut self, value: u64) {
        self.value = value;
    }

    pub fn get_value(&self) -> u64 {
        self.value
    }
}

pub type FeatureList = Vec<Feature>;
pub type Uint64Set = HashSet<u64>;
pub type FeatureNameToValuesMap<'a> = HashMap<&'a str, Uint64Set>;

/// This class represents a sample.
/// Each sample has a name and list of features.
pub struct Sample {
    name: String,
    features: FeatureList,
}

impl Sample {
    pub fn new (name: &str) -> Sample {
        Sample { name: name.to_string(), features: Sample::create_feature_list() }
    }

    fn create_feature_list() -> FeatureList {
        let mut v: FeatureList = vec![];
        v
    }

    pub fn add_features(&mut self, features: &mut FeatureList) {
        self.features.append(features);
    }

    pub fn add_feature(&mut self, feature: Feature) {
        self.features.push(feature);
    }

    pub fn features(&self) -> FeatureList {
        self.features
    }
}

pub type SampleList = Vec<Sample>;

/// Tree node, used internally.
struct Node {
    feature_name: String,
    left: Option<Box<Node>>,
    right: Option<Box<Node>>,
}

impl Node {
    pub fn new (feature_name: &str) -> Node {
        Node { feature_name: feature_name.to_string(), left: None, right: None }
    }

    fn get_feature_name(&self) -> String {
        self.feature_name
    }

	fn set_left_subtree(&mut self, subtree: NodeLink) {
		self.left = subtree;
	}

    fn get_left_subtree(&self) -> NodeLink {
        self.left
    }

	fn set_right_subtree(&mut self, subtree: NodeLink) {
		self.right = subtree;
	}

    fn get_right_subtree(&self) -> NodeLink {
        self.right
    }
}

type NodeLink = Option<Box<Node>>;
pub type NodeList = Vec<Node>;

/// Isolation Forest implementation.
pub struct Forest<'a> {
    featureValues: FeatureNameToValuesMap<'a>, // Lists each feature and maps it to all unique values in the training set
    trees: NodeList, // The decision trees that comprise the forest
    numTreesToCreate: u32, // The maximum number of trees to create
    subSamplingSize: u32, // The maximum depth of a tree
}

impl<'a> Forest<'a> {
    pub fn new (numTreesToCreate: u32, subSamplingSize: u32) -> Forest<'a> {
        Forest { numTreesToCreate: numTreesToCreate, subSamplingSize: subSamplingSize, trees: Forest::create_trees(), featureValues: Forest::create_feature_name_to_values_map() }
    }

    fn create_trees() -> NodeList {
        let mut v: NodeList = vec![];
        v
    }

    fn create_feature_name_to_values_map() -> FeatureNameToValuesMap<'a> {
        let mut m = HashMap::new();
        m
    }

    pub fn add_sample(&self, sample: Sample) {
		// Add each of this sample's features to the list of known features
		// with the corresponding set of unique values.
		let mut features = sample.features();
        for feature in &features {
            let mut found_feature = false;
        }
    }

    pub fn create(&self) {
    	for _i in 0..self.numTreesToCreate {
            let tree = Forest::create_trees();
        }
    }

    fn score_tree(&self, sample: Sample, tree: Node) -> f64 {
        let mut depth = 0.0;
        let mut current_node = tree;
        let mut done = false;
        while !done {
            let mut found_feature = false;
            let node_feature_name = current_node.get_feature_name();
            let features = sample.features();
            for feature in features {
                let feature_name = feature.get_name();
                if feature_name == node_feature_name {
					if feature.get_value() < current_node.split_value() {
						current_node = current_node.get_left_subtree();
                    } else {
						current_node = current_node.get_right_subtree();
                    }
                    found_feature = false;
                }
            }
        }
        depth
    }

    pub fn score(&self, sample: Sample) -> f64 {
        let mut score = 0.0;

        if self.trees.len() > 0 {
            for tree in self.trees {
                score += self.score_tree(sample, tree);
            }
            score /= self.trees.len() as f64;
        }
        score
    }
}
<|endoftext|>


<commit_before>use if_chain::if_chain;
use rustc::hir::{Expr, ExprKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use syntax_pos::Span;

use crate::consts::{constant, Constant};
use crate::utils::{in_macro_or_desugar, is_direct_expn_of, span_help_and_lint};

declare_clippy_lint! {
    /// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls.
    ///
    /// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
    /// panic!() or unreachable!()
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```rust,ignore
    /// assert!(false)
    /// // or
    /// assert!(true)
    /// // or
    /// const B: bool = false;
    /// assert!(B)
    /// ```
    pub ASSERTIONS_ON_CONSTANTS,
    style,
    "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`"
}

declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        let mut is_debug_assert = false;
        if let Some(assert_span) = is_direct_expn_of(e.span, "assert") {
            if in_macro_or_desugar(assert_span) {
                return;
            }
            if let Some(debug_assert_span) = is_direct_expn_of(assert_span, "debug_assert") {
                if in_macro_or_desugar(debug_assert_span) {
                    return;
                }
                is_debug_assert = true;
            }
            if let ExprKind::Unary(_, ref lit) = e.node {
                if let Some((bool_const, _)) = constant(cx, cx.tables, lit) {
                    if let Constant::Bool(is_true) bool_const {
                        if is_true {
                            span_help_and_lint(
                                cx,
                                ASSERTIONS_ON_CONSTANTS,
                                e.span,
                                "`assert!(true)` will be optimized out by the compiler",
                                "remove it"
                            );
                        } else if !is_debug_assert {
                            span_help_and_lint(
                                cx,
                                ASSERTIONS_ON_CONSTANTS,
                                e.span,
                                "`assert!(false)` should probably be replaced",
                                "use `panic!()` or `unreachable!()`"
                            );
                        }
                    }
                }
            }
        }
    }
}
<commit_msg>Fix assertions_on_constants lint<commit_after>use rustc::hir::{Expr, ExprKind};
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};

use crate::consts::{constant, Constant};
use crate::utils::{in_macro_or_desugar, is_direct_expn_of, is_expn_of, span_help_and_lint};

declare_clippy_lint! {
    /// **What it does:** Checks for `assert!(true)` and `assert!(false)` calls.
    ///
    /// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
    /// panic!() or unreachable!()
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```rust,ignore
    /// assert!(false)
    /// // or
    /// assert!(true)
    /// // or
    /// const B: bool = false;
    /// assert!(B)
    /// ```
    pub ASSERTIONS_ON_CONSTANTS,
    style,
    "`assert!(true)` / `assert!(false)` will be optimized out by the compiler, and should probably be replaced by a `panic!()` or `unreachable!()`"
}

declare_lint_pass!(AssertionsOnConstants => [ASSERTIONS_ON_CONSTANTS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        let lint_assert_cb = |is_debug_assert: bool| {
            if let ExprKind::Unary(_, ref lit) = e.node {
                if let Some((Constant::Bool(is_true), _)) = constant(cx, cx.tables, lit) {
                    if is_true {
                        span_help_and_lint(
                            cx,
                            ASSERTIONS_ON_CONSTANTS,
                            e.span,
                            "`assert!(true)` will be optimized out by the compiler",
                            "remove it",
                        );
                    } else if !is_debug_assert {
                        span_help_and_lint(
                            cx,
                            ASSERTIONS_ON_CONSTANTS,
                            e.span,
                            "`assert!(false)` should probably be replaced",
                            "use `panic!()` or `unreachable!()`",
                        );
                    }
                }
            }
        };
        if let Some(debug_assert_span) = is_expn_of(e.span, "debug_assert") {
            if in_macro_or_desugar(debug_assert_span) {
                return;
            }
            lint_assert_cb(true);
        } else if let Some(assert_span) = is_direct_expn_of(e.span, "assert") {
            if in_macro_or_desugar(assert_span) {
                return;
            }
            lint_assert_cb(false);
        }
    }
}
<|endoftext|>


<commit_before>use crate::consts::{constant, Constant};
use crate::rustc::hir::{Expr, ExprKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::LitKind;
use crate::utils::{is_direct_expn_of, span_help_and_lint};
use if_chain::if_chain;

/// **What it does:** Check to call assert!(true/false)
///
/// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
/// panic!() or unreachable!()
///
/// **Known problems:** None
///
/// **Example:**
/// ```rust
/// assert!(false)
/// // or
/// assert!(true)
/// // or
/// const B: bool = false;
/// assert!(B)
/// ```
declare_clippy_lint! {
    pub ASSERTIONS_ON_CONSTANTS,
    style,
    "assert!(true/false) will be optimized out by the compiler/should probably be replaced by a panic!() or unreachable!()"
}

pub struct AssertionsOnConstants;

impl LintPass for AssertionsOnConstants {
    fn get_lints(&self) -> LintArray {
        lint_array![ASSERTIONS_ON_CONSTANTS]
    }

    fn name(&self) -> &'static str {
        "AssertionsOnConstants"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if_chain! {
            if is_direct_expn_of(e.span, "assert").is_some();
            if let ExprKind::Unary(_, ref lit) = e.node;
            then {
                if let ExprKind::Lit(ref inner) = lit.node {
                    match inner.node {
                        LitKind::Bool(true) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(true) will be optimized out by the compiler",
                                "remove it");
                        },
                        LitKind::Bool(false) => {
                            span_help_and_lint(
                                cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(false) should probably be replaced",
                                "use panic!() or unreachable!()");
                        },
                        _ => (),
                    }
                } else if let Some(bool_const) = constant(cx, cx.tables, lit) {
                    match bool_const.0 {
                        Constant::Bool(true) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(const: true) will be optimized out by the compiler",
                                "remove it");
                        },
                        Constant::Bool(false) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(const: false) should probably be replaced",
                                "use panic!() or unreachable!()");
                        },
                        _ => (),
                    }
                }
            }
        }
    }
}
<commit_msg>Don't warn about const assertions when assert is in a macro itself<commit_after>use crate::consts::{constant, Constant};
use crate::rustc::hir::{Expr, ExprKind};
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::syntax::ast::LitKind;
use crate::utils::{in_macro, is_direct_expn_of, span_help_and_lint};
use if_chain::if_chain;

/// **What it does:** Check to call assert!(true/false)
///
/// **Why is this bad?** Will be optimized out by the compiler or should probably be replaced by a
/// panic!() or unreachable!()
///
/// **Known problems:** None
///
/// **Example:**
/// ```rust
/// assert!(false)
/// // or
/// assert!(true)
/// // or
/// const B: bool = false;
/// assert!(B)
/// ```
declare_clippy_lint! {
    pub ASSERTIONS_ON_CONSTANTS,
    style,
    "assert!(true/false) will be optimized out by the compiler/should probably be replaced by a panic!() or unreachable!()"
}

pub struct AssertionsOnConstants;

impl LintPass for AssertionsOnConstants {
    fn get_lints(&self) -> LintArray {
        lint_array![ASSERTIONS_ON_CONSTANTS]
    }

    fn name(&self) -> &'static str {
        "AssertionsOnConstants"
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssertionsOnConstants {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
        if_chain! {
            if let Some(assert_span) = is_direct_expn_of(e.span, "assert");
            if !in_macro(assert_span)
                || is_direct_expn_of(assert_span, "debug_assert").map_or(false, |span| !in_macro(span));
            if let ExprKind::Unary(_, ref lit) = e.node;
            then {
                if let ExprKind::Lit(ref inner) = lit.node {
                    match inner.node {
                        LitKind::Bool(true) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(true) will be optimized out by the compiler",
                                "remove it");
                        },
                        LitKind::Bool(false) => {
                            span_help_and_lint(
                                cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(false) should probably be replaced",
                                "use panic!() or unreachable!()");
                        },
                        _ => (),
                    }
                } else if let Some(bool_const) = constant(cx, cx.tables, lit) {
                    match bool_const.0 {
                        Constant::Bool(true) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(const: true) will be optimized out by the compiler",
                                "remove it");
                        },
                        Constant::Bool(false) => {
                            span_help_and_lint(cx, ASSERTIONS_ON_CONSTANTS, e.span,
                                "assert!(const: false) should probably be replaced",
                                "use panic!() or unreachable!()");
                        },
                        _ => (),
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use types::{DataTy, HasDataTy};
use common::constant::VECTOR_SIZE;

use std::marker;
use std::mem;
use std::raw::Slice;
use std::iter::Iterator;

pub trait Vector<'a> : HasDataTy {
  fn size(&self) -> usize;
  unsafe fn as_array<T>(&self) -> &'a [T];
  unsafe fn as_mut_array<T>(&mut self) -> &'a mut [T];
  fn iter<T>() -> Iterator<Item=T>;
}

pub trait VRowBlock<'b> {
  fn vector(&self, column_id: usize) -> &'b Vector<'b>;
  fn set_vector(&mut self, column_id: usize, &'b Vector<'b>);
}

pub struct BorrowVRowBlock<'b> {
  vectors: Vec<&'b Vector<'b>>
}

impl<'b> VRowBlock<'b> for BorrowVRowBlock<'b> {
  fn vector(&self, column_id: usize) -> &'b Vector<'b> {
    self.vectors[column_id]
  }

  fn set_vector(&mut self, column_id: usize, vector: &'b Vector<'b>) {
    self.vectors[column_id] = vector
  }
}

pub struct ArrayVector<T> {
  array: Vec<T>,
  data_ty: DataTy
}

impl<'a, V> Vector<'a> for ArrayVector<V> {
  fn size(&self) -> usize { self.array.len() }

  unsafe fn as_array<T>(&self) -> &'a [T] {
    let slice = Slice {data: self.array.as_ptr() as *const T, len: self.array.len()};
    mem::transmute(slice)
  }

  unsafe fn as_mut_array<T>(&mut self) -> &'a mut [T] {
    let slice = Slice {data: self.array.as_mut_ptr() as *mut T, len: self.array.len()};
    unsafe {
      mem::transmute(slice)
    }
  }
}

impl<T> HasDataTy for ArrayVector<T> {
  fn data_ty(&self) -> &DataTy {
    &self.data_ty
  }
}

pub struct PtrVector<'a> {
  ptr: *const u8,
  size: usize,
  data_type: DataTy,
  _marker: marker::PhantomData<&'a ()>
}

impl<'a> PtrVector<'a> {
  pub fn new(ptr: *const u8, size: usize, data_type: DataTy) -> PtrVector<'a> {
    PtrVector {
      ptr: ptr,
      size: size,
      data_type: data_type,
      _marker: marker::PhantomData
    }
  }

  pub fn as_array<T>(&self) -> &[T] {
    let slice = Slice {data: self.ptr as *const T, len: VECTOR_SIZE};
    unsafe {
      mem::transmute(slice)
    }
  }

  pub fn as_mut_array<T>(&self) -> &mut [T] {
    let slice = Slice {data: self.ptr as *mut T, len: VECTOR_SIZE};
    unsafe {
      mem::transmute(slice)
    }
  }
}

impl<'a> HasDataTy for PtrVector<'a> {
  fn data_ty(&self) -> &DataTy {
    &self.data_type
  }
}<commit_msg>Simplified as_array() and as_mut_array()<commit_after>use types::{DataTy, HasDataTy};
use common::constant::VECTOR_SIZE;

use std::marker;
use std::marker::Sized;
use std::mem;
use std::slice;
use std::slice::Iter;
use std::raw::Slice;
use std::iter::Iterator;

pub trait Vector<'a> : HasDataTy {
  fn size(&self) -> usize;
  fn as_array<T>(&self) -> &'a [T];
  fn as_mut_array<T>(&mut self) -> &'a mut [T];
  //fn iter<T: 'a>(&self) -> Box<Iterator<Item=T>>;
}

pub trait VRowBlock<'b> {
  fn vector(&self, column_id: usize) -> &'b Vector<'b>;
  fn set_vector(&mut self, column_id: usize, &'b Vector<'b>);
}

pub struct BorrowVRowBlock<'b> {
  vectors: Vec<&'b Vector<'b>>
}

impl<'b> VRowBlock<'b> for BorrowVRowBlock<'b> {
  fn vector(&self, column_id: usize) -> &'b Vector<'b> {
    self.vectors[column_id]
  }

  fn set_vector(&mut self, column_id: usize, vector: &'b Vector<'b>) {
    self.vectors[column_id] = vector
  }
}

pub struct ArrayVector<T: Sized> {
  array: Vec<T>,
  data_ty: DataTy
}

impl<'a, V> Vector<'a> for ArrayVector<V> {
  fn size(&self) -> usize { self.array.len() }

  #[inline]
  fn as_array<T>(&self) -> &'a [T] {
    unsafe {
      slice::from_raw_parts(self.array.as_ptr() as *const T, VECTOR_SIZE)
    }
  }

  #[inline]
  fn as_mut_array<T>(&mut self) -> &'a mut [T] {
    unsafe {
      slice::from_raw_parts_mut(self.array.as_mut_ptr() as *mut T, VECTOR_SIZE)
    }
  }

  // fn iter<T: 'a>(&self) -> Box<Iterator<Item=T>> {
  //   let slice = Slice {data: self.array.as_ptr() as *const T, len: self.array.len()};
  //   let x: &'a [T] = unsafe {
  //     mem::transmute(slice)
  //   };

  //   Box::new(ArrayVectorItor {iter: x.iter()})
  // }
}

// struct ArrayVectorItor<'a, T: 'a> {
//   iter: Iter<'a, T>
// }

// impl<'a, T: 'a> Iterator for ArrayVectorItor<'a, T> {
//   type Item = T;

//   fn next(&mut self) -> Option<T> {
//     self.iter.next()
//   }
// }

impl<T> HasDataTy for ArrayVector<T> {
  fn data_ty(&self) -> &DataTy {
    &self.data_ty
  }
}

pub struct PtrVector<'a> {
  ptr: *const u8,
  size: usize,
  data_type: DataTy,
  _marker: marker::PhantomData<&'a ()>
}

impl<'a> PtrVector<'a> {
  pub fn new(ptr: *const u8, size: usize, data_type: DataTy) -> PtrVector<'a> {
    PtrVector {
      ptr: ptr,
      size: size,
      data_type: data_type,
      _marker: marker::PhantomData
    }
  }

  pub fn as_array<T>(&self) -> &[T] {
    unsafe {
      slice::from_raw_parts(self.ptr as *const T, VECTOR_SIZE)
    }
  }

  pub fn as_mut_array<T>(&self) -> &mut [T] {
    unsafe {
      slice::from_raw_parts_mut(self.ptr as *mut T, VECTOR_SIZE)
    }
  }
}

impl<'a> HasDataTy for PtrVector<'a> {
  fn data_ty(&self) -> &DataTy {
    &self.data_type
  }
}<|endoftext|>