<commit_before>extern crate lp_modeler;

use lp_modeler::dsl::*;
use lp_modeler::dsl::LpExpression::*;

use lp_modeler::format::lp_format::LpFileFormat;

#[test]
fn expressions_creation() {
    let ref a = LpInteger::new("a").lower_bound(10.0).upper_bound(20.0);
    let ref b = LpInteger::new("b");

    assert_eq!(
        a + b,
        AddExpr(Box::new(ConsInt(a.clone())), Box::new(ConsInt(b.clone())))
    );
}

#[test]
fn distributivity() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    let test = a * (2 + b) * 3;
    let test2 = test.clone();
    assert_eq!((2 * (2 + a)).to_lp_file_format(), "2 a + 4");
    assert_eq!(
        ((2 + a) * (2 + b)).to_lp_file_format(),
        "2 a + 2 b + b a + 4"
    );
    assert_eq!(test.to_lp_file_format(), "6 a + 3 a b");
    assert_eq!((10 * test).to_lp_file_format(), "60 a + 30 a b");
    assert_eq!(
        ((c + 10) * test2).to_lp_file_format(),
        "6 c a + 3 c a b + 60 a + 30 a b"
    );

    let ref x = LpContinuous::new("x");
    let ref y = LpContinuous::new("y");
    let ref z = LpContinuous::new("z");

    let test3 = x * (y - z);
    assert_eq!((3 * (3 - a)).to_lp_file_format(), "-3 a + 9");
    assert_eq!(test3.to_lp_file_format(), "x y - x z");
    assert_eq!((4 * test3).to_lp_file_format(), "4 x y - 4 x z");
}

#[test]
fn associativity() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    assert_eq!((a + (b + 2)).to_lp_file_format(), "a + b + 2");
    assert_eq!(((a + b) + 2).to_lp_file_format(), "a + b + 2");

    assert_eq!((a + (b - 2)).to_lp_file_format(), "a + b - 2");
    assert_eq!(((a + b) - 2).to_lp_file_format(), "a + b - 2");

    assert_eq!((a - (b + 2)).to_lp_file_format(), "a - b - 2");
    assert_eq!(((a - b) + 2).to_lp_file_format(), "a - b + 2");

    assert_eq!((a - (b - 2)).to_lp_file_format(), "a - b + 2");
    assert_eq!(((a - b) - 2).to_lp_file_format(), "a - b - 2");

    assert_eq!((a - (b - 2) + c).to_lp_file_format(), "a - b + c + 2");
    assert_eq!(((a - b) - 2 + c).to_lp_file_format(), "a - b + c - 2");
}

#[test]
fn literal_first_with_accumulation() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    assert_eq!(
        (a + 1 + b + 2 + c + 3 + a + 4).to_lp_file_format(),
        "a + b + c + a + 10"
    );
    assert_eq!(
        (a - 1 + b - 2 - c + 3 + a - 4).to_lp_file_format(),
        "a + b - c + a - 4"
    );
    assert_eq!(
        (a + b + 1 - c - a - 3).to_lp_file_format(),
        "a + b - c - a - 2"
    );
    assert_eq!(
        (a + b + (c - 1) * 2 - a - 3).to_lp_file_format(),
        "a + b + 2 c - a - 5"
    );
    assert_eq!(
        (a + b + (1 - c) * 2 - a - 3).to_lp_file_format(),
        "a + b - 2 c - a - 1"
    );
    assert_eq!((2 * (a + 5)).to_lp_file_format(), "2 a + 10");
    assert_eq!(
        ((2 + b) * (a + 5)).to_lp_file_format(),
        "2 a + a b + 5 b + 10"
    );
    assert_eq!((2 + (a + b) + 3).to_lp_file_format(), "a + b + 5");
}

#[test]
fn trivial_rules() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");

    assert_eq!(((a + b) * 0).to_lp_file_format(), "0");
    assert_eq!((0 * (a + b)).to_lp_file_format(), "0");
    assert_eq!((0 * a * b * 3).to_lp_file_format(), "0");
    assert_eq!(((a + b) + 0).to_lp_file_format(), "a + b");
    assert_eq!((0 + (a + b) + 0).to_lp_file_format(), "a + b");
    assert_eq!((0 + (a + b)).to_lp_file_format(), "a + b");
    assert_eq!(((a + b) - 0).to_lp_file_format(), "a + b");
    assert_eq!((0 - (a + b)).to_lp_file_format(), "-a - b");
    assert_eq!((0 + (a + b)).to_lp_file_format(), "a + b");
}

#[test]
fn expressions_to_lp_file_format() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    // Expressions
    assert_eq!((a + 2 * b + c).to_lp_file_format(), "a + 2 b + c");
    assert_eq!((a + b * 2 + c).to_lp_file_format(), "a + 2 b + c");
    assert_eq!((a + b * 2 + 3 * 2 * c).to_lp_file_format(), "a + 2 b + 6 c");
    assert_eq!((a + 2).to_lp_file_format(), "a + 2");
    assert_eq!(
        (2 * a + 2 * b - 4 * c).to_lp_file_format(),
        "2 a + 2 b - 4 c"
    );
    assert_eq!((-2 * a).to_lp_file_format(), "-2 a");

    // Constraints
    assert_eq!((a + b).equal(10).to_lp_file_format(), "a + b = 10");
    assert_eq!((2 * a + b).ge(10).to_lp_file_format(), "2 a + b >= 10");
    assert_eq!(
        (2 * a + b + 20).ge(c).to_lp_file_format(),
        "2 a + b - c >= -20"
    );
    assert_eq!((-a).ge(10).to_lp_file_format(), "-a >= 10");
    assert_eq!(
        (2 * a - 20 + b).ge(-c).to_lp_file_format(),
        "2 a + b + c >= 20"
    );
    assert_eq!((a + b + 10).ge(0).to_lp_file_format(), "a + b >= -10");
    assert_eq!(
        (3 * (a + b + 10)).le(0).to_lp_file_format(),
        "3 a + 3 b <= -30"
    );
    assert_eq!(
        (3 * (a + b + 10)).le(a + b).to_lp_file_format(),
        "3 a + 3 b - a - b <= -30"
    );
}

#[test]
fn expression_with_lp_sum() {
    let ref a = LpBinary::new("a");
    let ref b = LpBinary::new("b");
    let ref c = LpBinary::new("c");
    let ref d = LpBinary::new("d");

    let ref expr1 = vec!(a,b,c);
    let ref expr2 = vec!(a,b,c,d);
    let ref expr3 = vec!(a);
    let ref empty: Vec<&LpBinary> = vec!();
    assert_eq!(
        lp_sum(expr1).equal(10.0).to_lp_file_format(),
        "a + b + c = 10"
    );
    assert_eq!(
        lp_sum(expr2).equal(10.0).to_lp_file_format(),
        "a + b + c + d = 10"
    );
    assert_eq!(
        lp_sum(expr3).le(5.5).to_lp_file_format(),
        "a <= 5.5"
    );
    assert!(
        std::panic::catch_unwind( || lp_sum(empty)).is_err(),
        "should panic if empty vec"
    );
}

#[test]
fn simplifications() {
    let a = &LpInteger::new("a");

    let expr1 = a - 2f32;
    let expr2 = 1f32 - a;

    let (c, _) = split_constant_and_expr(&simplify(&(&expr1 + &expr2)));
    assert_eq!(c, -1f32);

    let (c, _) = split_constant_and_expr(&simplify(&(&expr2 + &expr1)));
    assert_eq!(c, -1f32);
}<commit_msg>adding binary variables in associative test<commit_after>extern crate lp_modeler;

use lp_modeler::dsl::*;
use lp_modeler::dsl::LpExpression::*;

use lp_modeler::format::lp_format::LpFileFormat;

#[test]
fn expressions_creation() {
    let ref a = LpInteger::new("a").lower_bound(10.0).upper_bound(20.0);
    let ref b = LpInteger::new("b");

    assert_eq!(
        a + b,
        AddExpr(Box::new(ConsInt(a.clone())), Box::new(ConsInt(b.clone())))
    );
}

#[test]
fn distributivity() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    let test = a * (2 + b) * 3;
    let test2 = test.clone();
    assert_eq!((2 * (2 + a)).to_lp_file_format(), "2 a + 4");
    assert_eq!(
        ((2 + a) * (2 + b)).to_lp_file_format(),
        "2 a + 2 b + b a + 4"
    );
    assert_eq!(test.to_lp_file_format(), "6 a + 3 a b");
    assert_eq!((10 * test).to_lp_file_format(), "60 a + 30 a b");
    assert_eq!(
        ((c + 10) * test2).to_lp_file_format(),
        "6 c a + 3 c a b + 60 a + 30 a b"
    );

    let ref x = LpContinuous::new("x");
    let ref y = LpContinuous::new("y");
    let ref z = LpContinuous::new("z");

    let test3 = x * (y - z);
    assert_eq!((3 * (3 - a)).to_lp_file_format(), "-3 a + 9");
    assert_eq!(test3.to_lp_file_format(), "x y - x z");
    assert_eq!((4 * test3).to_lp_file_format(), "4 x y - 4 x z");
}

#[test]
fn associativity() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    assert_eq!((a + (b + 2)).to_lp_file_format(), "a + b + 2");
    assert_eq!(((a + b) + 2).to_lp_file_format(), "a + b + 2");

    assert_eq!((a + (b - 2)).to_lp_file_format(), "a + b - 2");
    assert_eq!(((a + b) - 2).to_lp_file_format(), "a + b - 2");

    assert_eq!((a - (b + 2)).to_lp_file_format(), "a - b - 2");
    assert_eq!(((a - b) + 2).to_lp_file_format(), "a - b + 2");

    assert_eq!((a - (b - 2)).to_lp_file_format(), "a - b + 2");
    assert_eq!(((a - b) - 2).to_lp_file_format(), "a - b - 2");

    assert_eq!((a - (b - 2) + c).to_lp_file_format(), "a - b + c + 2");
    assert_eq!(((a - b) - 2 + c).to_lp_file_format(), "a - b + c - 2");

    let ref x = LpBinary::new("x");
    let ref y = LpBinary::new("y");
    assert_eq!((x + (y + 1)).to_lp_file_format(), "x + y + 1");
    assert_eq!(((x + y) + 1).to_lp_file_format(), "x + y + 1");
}

#[test]
fn literal_first_with_accumulation() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    assert_eq!(
        (a + 1 + b + 2 + c + 3 + a + 4).to_lp_file_format(),
        "a + b + c + a + 10"
    );
    assert_eq!(
        (a - 1 + b - 2 - c + 3 + a - 4).to_lp_file_format(),
        "a + b - c + a - 4"
    );
    assert_eq!(
        (a + b + 1 - c - a - 3).to_lp_file_format(),
        "a + b - c - a - 2"
    );
    assert_eq!(
        (a + b + (c - 1) * 2 - a - 3).to_lp_file_format(),
        "a + b + 2 c - a - 5"
    );
    assert_eq!(
        (a + b + (1 - c) * 2 - a - 3).to_lp_file_format(),
        "a + b - 2 c - a - 1"
    );
    assert_eq!((2 * (a + 5)).to_lp_file_format(), "2 a + 10");
    assert_eq!(
        ((2 + b) * (a + 5)).to_lp_file_format(),
        "2 a + a b + 5 b + 10"
    );
    assert_eq!((2 + (a + b) + 3).to_lp_file_format(), "a + b + 5");
}

#[test]
fn trivial_rules() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");

    assert_eq!(((a + b) * 0).to_lp_file_format(), "0");
    assert_eq!((0 * (a + b)).to_lp_file_format(), "0");
    assert_eq!((0 * a * b * 3).to_lp_file_format(), "0");
    assert_eq!(((a + b) + 0).to_lp_file_format(), "a + b");
    assert_eq!((0 + (a + b) + 0).to_lp_file_format(), "a + b");
    assert_eq!((0 + (a + b)).to_lp_file_format(), "a + b");
    assert_eq!(((a + b) - 0).to_lp_file_format(), "a + b");
    assert_eq!((0 - (a + b)).to_lp_file_format(), "-a - b");
    assert_eq!((0 + (a + b)).to_lp_file_format(), "a + b");
}

#[test]
fn expressions_to_lp_file_format() {
    let ref a = LpInteger::new("a");
    let ref b = LpInteger::new("b");
    let ref c = LpInteger::new("c");

    // Expressions
    assert_eq!((a + 2 * b + c).to_lp_file_format(), "a + 2 b + c");
    assert_eq!((a + b * 2 + c).to_lp_file_format(), "a + 2 b + c");
    assert_eq!((a + b * 2 + 3 * 2 * c).to_lp_file_format(), "a + 2 b + 6 c");
    assert_eq!((a + 2).to_lp_file_format(), "a + 2");
    assert_eq!(
        (2 * a + 2 * b - 4 * c).to_lp_file_format(),
        "2 a + 2 b - 4 c"
    );
    assert_eq!((-2 * a).to_lp_file_format(), "-2 a");

    // Constraints
    assert_eq!((a + b).equal(10).to_lp_file_format(), "a + b = 10");
    assert_eq!((2 * a + b).ge(10).to_lp_file_format(), "2 a + b >= 10");
    assert_eq!(
        (2 * a + b + 20).ge(c).to_lp_file_format(),
        "2 a + b - c >= -20"
    );
    assert_eq!((-a).ge(10).to_lp_file_format(), "-a >= 10");
    assert_eq!(
        (2 * a - 20 + b).ge(-c).to_lp_file_format(),
        "2 a + b + c >= 20"
    );
    assert_eq!((a + b + 10).ge(0).to_lp_file_format(), "a + b >= -10");
    assert_eq!(
        (3 * (a + b + 10)).le(0).to_lp_file_format(),
        "3 a + 3 b <= -30"
    );
    assert_eq!(
        (3 * (a + b + 10)).le(a + b).to_lp_file_format(),
        "3 a + 3 b - a - b <= -30"
    );
}

#[test]
fn expression_with_lp_sum() {
    let ref a = LpBinary::new("a");
    let ref b = LpBinary::new("b");
    let ref c = LpBinary::new("c");
    let ref d = LpBinary::new("d");

    let ref expr1 = vec!(a,b,c);
    let ref expr2 = vec!(a,b,c,d);
    let ref expr3 = vec!(a);
    let ref empty: Vec<&LpBinary> = vec!();
    assert_eq!(
        lp_sum(expr1).equal(10.0).to_lp_file_format(),
        "a + b + c = 10"
    );
    assert_eq!(
        lp_sum(expr2).equal(10.0).to_lp_file_format(),
        "a + b + c + d = 10"
    );
    assert_eq!(
        lp_sum(expr3).le(5.5).to_lp_file_format(),
        "a <= 5.5"
    );
    assert!(
        std::panic::catch_unwind( || lp_sum(empty)).is_err(),
        "should panic if empty vec"
    );
}

#[test]
fn simplifications() {
    let a = &LpInteger::new("a");

    let expr1 = a - 2f32;
    let expr2 = 1f32 - a;

    let (c, _) = split_constant_and_expr(&simplify(&(&expr1 + &expr2)));
    assert_eq!(c, -1f32);

    let (c, _) = split_constant_and_expr(&simplify(&(&expr2 + &expr1)));
    assert_eq!(c, -1f32);
}<|endoftext|>


<commit_before>/// Character level parsers

use internal::{IResult,Needed};
use util::ErrorKind;

/// matches one of the provided characters
#[macro_export]
macro_rules! one_of (
  ($i:expr, $inp: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        #[inline(always)]
        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
          b.as_bytes()
        }

        let expected = $inp;
        let bytes = as_bytes(&expected);
        one_of_bytes!($i, bytes)
      }
    }
  );
);

#[doc(hidden)]
#[macro_export]
macro_rules! one_of_bytes (
  ($i:expr, $bytes: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        let mut found = false;

        for &i in $bytes {
          if i == $i[0] {
            found = true;
            break;
          }
        }

        if found {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          //$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::OneOf, $i))
          $crate::IResult::Error(error_position!($crate::ErrorKind::OneOf, $i))
        }
      }
    }
  );
);

/// matches anything but the provided characters
#[macro_export]
macro_rules! none_of (
  ($i:expr, $inp: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        #[inline(always)]
        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
          b.as_bytes()
        }

        let expected = $inp;
        let bytes = as_bytes(&expected);
        none_of_bytes!($i, bytes)
      }
    }
  );
);

#[doc(hidden)]
#[macro_export]
macro_rules! none_of_bytes (
  ($i:expr, $bytes: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        let mut found = false;

        for &i in $bytes {
          if i == $i[0] {
            found = true;
            break;
          }
        }

        if !found {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          $crate::IResult::Error(error_position!($crate::ErrorKind::NoneOf, $i))
        }
      }
    }
  );
);

/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
#[macro_export]
macro_rules! char (
  ($i:expr, $c: expr) => (
    {
      if $i.is_empty() {
        let res: $crate::IResult<&[u8], char> = $crate::IResult::Incomplete($crate::Needed::Size(1));
        res
      } else {
        if $i[0] == $c as u8 {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          $crate::IResult::Error(error_position!($crate::ErrorKind::Char, $i))
        }
      }
    }
  );
);

named!(pub newline<char>, char!('\n'));

pub fn crlf(input:&[u8]) -> IResult<&[u8], char> {
  if input.len() < 2 {
    IResult::Incomplete(Needed::Size(2))
  } else {
    if &input[0..2] == &b"\r\n"[..] {
      IResult::Done(&input[2..], '\n')
    } else {
      IResult::Error(error_position!(ErrorKind::CrLf, input))
    }
  }
}

named!(pub eol<char>, alt!(crlf | newline));
named!(pub tab<char>, char!('\t'));

pub fn anychar(input:&[u8]) -> IResult<&[u8], char> {
  if input.is_empty() {
    IResult::Incomplete(Needed::Size(1))
  } else {
    IResult::Done(&input[1..], input[0] as char)
  }
}

#[cfg(test)]
mod tests {
  use internal::IResult::*;
  use util::ErrorKind;

  #[test]
  fn one_of() {
    named!(f<char>, one_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Done(&b"bcd"[..], 'a'));

    let b = &b"cde"[..];
    assert_eq!(f(b), Error(error_position!(ErrorKind::OneOf, b)));
  }

  #[test]
  fn none_of() {
    named!(f<char>, none_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Error(error_position!(ErrorKind::NoneOf, a)));

    let b = &b"cde"[..];
    assert_eq!(f(b), Done(&b"de"[..], 'c'));
  }

  #[test]
  fn char() {
    named!(f<char>, char!('c'));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Error(error_position!(ErrorKind::Char, a)));

    let b = &b"cde"[..];
    assert_eq!(f(b), Done(&b"de"[..], 'c'));
  }
}
<commit_msg>Change eol to test for newline first<commit_after>/// Character level parsers

use internal::{IResult,Needed};
use util::ErrorKind;

/// matches one of the provided characters
#[macro_export]
macro_rules! one_of (
  ($i:expr, $inp: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        #[inline(always)]
        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
          b.as_bytes()
        }

        let expected = $inp;
        let bytes = as_bytes(&expected);
        one_of_bytes!($i, bytes)
      }
    }
  );
);

#[doc(hidden)]
#[macro_export]
macro_rules! one_of_bytes (
  ($i:expr, $bytes: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        let mut found = false;

        for &i in $bytes {
          if i == $i[0] {
            found = true;
            break;
          }
        }

        if found {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          //$crate::IResult::Error($crate::Err::Position($crate::ErrorKind::OneOf, $i))
          $crate::IResult::Error(error_position!($crate::ErrorKind::OneOf, $i))
        }
      }
    }
  );
);

/// matches anything but the provided characters
#[macro_export]
macro_rules! none_of (
  ($i:expr, $inp: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        #[inline(always)]
        fn as_bytes<T: $crate::AsBytes>(b: &T) -> &[u8] {
          b.as_bytes()
        }

        let expected = $inp;
        let bytes = as_bytes(&expected);
        none_of_bytes!($i, bytes)
      }
    }
  );
);

#[doc(hidden)]
#[macro_export]
macro_rules! none_of_bytes (
  ($i:expr, $bytes: expr) => (
    {
      if $i.is_empty() {
        $crate::IResult::Incomplete::<_, _>($crate::Needed::Size(1))
      } else {
        let mut found = false;

        for &i in $bytes {
          if i == $i[0] {
            found = true;
            break;
          }
        }

        if !found {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          $crate::IResult::Error(error_position!($crate::ErrorKind::NoneOf, $i))
        }
      }
    }
  );
);

/// matches one character: `char!(char) => &[u8] -> IResult<&[u8], char>
#[macro_export]
macro_rules! char (
  ($i:expr, $c: expr) => (
    {
      if $i.is_empty() {
        let res: $crate::IResult<&[u8], char> = $crate::IResult::Incomplete($crate::Needed::Size(1));
        res
      } else {
        if $i[0] == $c as u8 {
          $crate::IResult::Done(&$i[1..], $i[0] as char)
        } else {
          $crate::IResult::Error(error_position!($crate::ErrorKind::Char, $i))
        }
      }
    }
  );
);

named!(pub newline<char>, char!('\n'));

pub fn crlf(input:&[u8]) -> IResult<&[u8], char> {
  if input.len() < 2 {
    IResult::Incomplete(Needed::Size(2))
  } else {
    if &input[0..2] == &b"\r\n"[..] {
      IResult::Done(&input[2..], '\n')
    } else {
      IResult::Error(error_position!(ErrorKind::CrLf, input))
    }
  }
}

named!(pub eol<char>, alt!(newline | crlf));
named!(pub tab<char>, char!('\t'));

pub fn anychar(input:&[u8]) -> IResult<&[u8], char> {
  if input.is_empty() {
    IResult::Incomplete(Needed::Size(1))
  } else {
    IResult::Done(&input[1..], input[0] as char)
  }
}

#[cfg(test)]
mod tests {
  use internal::IResult::*;
  use util::ErrorKind;

  #[test]
  fn one_of() {
    named!(f<char>, one_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Done(&b"bcd"[..], 'a'));

    let b = &b"cde"[..];
    assert_eq!(f(b), Error(error_position!(ErrorKind::OneOf, b)));
  }

  #[test]
  fn none_of() {
    named!(f<char>, none_of!("ab"));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Error(error_position!(ErrorKind::NoneOf, a)));

    let b = &b"cde"[..];
    assert_eq!(f(b), Done(&b"de"[..], 'c'));
  }

  #[test]
  fn char() {
    named!(f<char>, char!('c'));

    let a = &b"abcd"[..];
    assert_eq!(f(a), Error(error_position!(ErrorKind::Char, a)));

    let b = &b"cde"[..];
    assert_eq!(f(b), Done(&b"de"[..], 'c'));
  }
}
<|endoftext|>


<commit_before>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum MTLPixelFormat {
    Invalid = 0,
    A8Unorm = 1,
    R8Unorm = 10,
    R8Unorm_sRGB = 11,
    R8Snorm = 12,
    R8Uint = 13,
    R8Sint = 14,
    R16Unorm = 20,
    R16Snorm = 22,
    R16Uint = 23,
    R16Sint = 24,
    R16Float = 25,
    RG8Unorm = 30,
    RG8Unorm_sRGB = 31,
    RG8Snorm = 32,
    RG8Uint = 33,
    RG8Sint = 34,
    B5G6R5Unorm = 40,
    A1BGR5Unorm = 41,
    ABGR4Unorm = 42,
    BGR5A1Unorm = 43,
    R32Uint = 53,
    R32Sint = 54,
    R32Float = 55,
    RG16Unorm = 60,
    RG16Snorm = 62,
    RG16Uint = 63,
    RG16Sint = 64,
    RG16Float = 65,
    RGBA8Unorm = 70,
    RGBA8Unorm_sRGB = 71,
    RGBA8Snorm = 72,
    RGBA8Uint = 73,
    RGBA8Sint = 74,
    BGRA8Unorm = 80,
    BGRA8Unorm_sRGB = 81,
    RGB10A2Unorm = 90,
    RGB10A2Uint = 91,
    RG11B10Float = 92,
    RGB9E5Float = 93,
    BGR10A2Unorm = 94,
    RG32Uint = 103,
    RG32Sint = 104,
    RG32Float = 105,
    RGBA16Unorm = 110,
    RGBA16Snorm = 112,
    RGBA16Uint = 113,
    RGBA16Sint = 114,
    RGBA16Float = 115,
    RGBA32Uint = 123,
    RGBA32Sint = 124,
    RGBA32Float = 125,
    BC1_RGBA = 130,
    BC1_RGBA_sRGB = 131,
    BC2_RGBA = 132,
    BC2_RGBA_sRGB = 133,
    BC3_RGBA = 134,
    BC3_RGBA_sRGB = 135,
    BC4_RUnorm = 140,
    BC4_RSnorm = 141,
    BC5_RGUnorm = 142,
    BC5_RGSnorm = 143,
    BC6H_RGBFloat = 150,
    BC6H_RGBUfloat = 151,
    BC7_RGBAUnorm = 152,
    BC7_RGBAUnorm_sRGB = 153,
    PVRTC_RGB_2BPP = 160,
    PVRTC_RGB_2BPP_sRGB = 161,
    PVRTC_RGB_4BPP = 162,
    PVRTC_RGB_4BPP_sRGB = 163,
    PVRTC_RGBA_2BPP = 164,
    PVRTC_RGBA_2BPP_sRGB = 165,
    PVRTC_RGBA_4BPP = 166,
    PVRTC_RGBA_4BPP_sRGB = 167,
    EAC_R11Unorm = 170,
    EAC_R11Snorm = 172,
    EAC_RG11Unorm = 174,
    EAC_RG11Snorm = 176,
    EAC_RGBA8 = 178,
    EAC_RGBA8_sRGB = 179,
    ETC2_RGB8 = 180,
    ETC2_RGB8_sRGB = 181,
    ETC2_RGB8A1 = 182,
    ETC2_RGB8A1_sRGB = 183,
    ASTC_4x4_sRGB = 186,
    ASTC_5x4_sRGB = 187,
    ASTC_5x5_sRGB = 188,
    ASTC_6x5_sRGB = 189,
    ASTC_6x6_sRGB = 190,
    ASTC_8x5_sRGB = 192,
    ASTC_8x6_sRGB = 193,
    ASTC_8x8_sRGB = 194,
    ASTC_10x5_sRGB = 195,
    ASTC_10x6_sRGB = 196,
    ASTC_10x8_sRGB = 197,
    ASTC_10x10_sRGB = 198,
    ASTC_12x10_sRGB = 199,
    ASTC_12x12_sRGB = 200,
    ASTC_4x4_LDR = 204,
    ASTC_5x4_LDR = 205,
    ASTC_5x5_LDR = 206,
    ASTC_6x5_LDR = 207,
    ASTC_6x6_LDR = 208,
    ASTC_8x5_LDR = 210,
    ASTC_8x6_LDR = 211,
    ASTC_8x8_LDR = 212,
    ASTC_10x5_LDR = 213,
    ASTC_10x6_LDR = 214,
    ASTC_10x8_LDR = 215,
    ASTC_10x10_LDR = 216,
    ASTC_12x10_LDR = 217,
    ASTC_12x12_LDR = 218,
    GBGR422 = 240,
    BGRG422 = 241,
    Depth16Unorm = 250,
    Depth32Float = 252,
    Stencil8 = 253,
    Depth24Unorm_Stencil8 = 255,
    Depth32Float_Stencil8 = 260,
    X32_Stencil8 = 261,
    X24_Stencil8 = 262,
    BGRA10_XR = 552,
    BGRA10_XR_SRGB = 553,
    BGR10_XR = 554,
    BGR10_XR_SRGB = 555,
}
<commit_msg>Add ASTC HDR Formats (#229)<commit_after>// Copyright 2016 GFX developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

#[repr(u64)]
#[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum MTLPixelFormat {
    Invalid = 0,
    A8Unorm = 1,
    R8Unorm = 10,
    R8Unorm_sRGB = 11,
    R8Snorm = 12,
    R8Uint = 13,
    R8Sint = 14,
    R16Unorm = 20,
    R16Snorm = 22,
    R16Uint = 23,
    R16Sint = 24,
    R16Float = 25,
    RG8Unorm = 30,
    RG8Unorm_sRGB = 31,
    RG8Snorm = 32,
    RG8Uint = 33,
    RG8Sint = 34,
    B5G6R5Unorm = 40,
    A1BGR5Unorm = 41,
    ABGR4Unorm = 42,
    BGR5A1Unorm = 43,
    R32Uint = 53,
    R32Sint = 54,
    R32Float = 55,
    RG16Unorm = 60,
    RG16Snorm = 62,
    RG16Uint = 63,
    RG16Sint = 64,
    RG16Float = 65,
    RGBA8Unorm = 70,
    RGBA8Unorm_sRGB = 71,
    RGBA8Snorm = 72,
    RGBA8Uint = 73,
    RGBA8Sint = 74,
    BGRA8Unorm = 80,
    BGRA8Unorm_sRGB = 81,
    RGB10A2Unorm = 90,
    RGB10A2Uint = 91,
    RG11B10Float = 92,
    RGB9E5Float = 93,
    BGR10A2Unorm = 94,
    RG32Uint = 103,
    RG32Sint = 104,
    RG32Float = 105,
    RGBA16Unorm = 110,
    RGBA16Snorm = 112,
    RGBA16Uint = 113,
    RGBA16Sint = 114,
    RGBA16Float = 115,
    RGBA32Uint = 123,
    RGBA32Sint = 124,
    RGBA32Float = 125,
    BC1_RGBA = 130,
    BC1_RGBA_sRGB = 131,
    BC2_RGBA = 132,
    BC2_RGBA_sRGB = 133,
    BC3_RGBA = 134,
    BC3_RGBA_sRGB = 135,
    BC4_RUnorm = 140,
    BC4_RSnorm = 141,
    BC5_RGUnorm = 142,
    BC5_RGSnorm = 143,
    BC6H_RGBFloat = 150,
    BC6H_RGBUfloat = 151,
    BC7_RGBAUnorm = 152,
    BC7_RGBAUnorm_sRGB = 153,
    PVRTC_RGB_2BPP = 160,
    PVRTC_RGB_2BPP_sRGB = 161,
    PVRTC_RGB_4BPP = 162,
    PVRTC_RGB_4BPP_sRGB = 163,
    PVRTC_RGBA_2BPP = 164,
    PVRTC_RGBA_2BPP_sRGB = 165,
    PVRTC_RGBA_4BPP = 166,
    PVRTC_RGBA_4BPP_sRGB = 167,
    EAC_R11Unorm = 170,
    EAC_R11Snorm = 172,
    EAC_RG11Unorm = 174,
    EAC_RG11Snorm = 176,
    EAC_RGBA8 = 178,
    EAC_RGBA8_sRGB = 179,
    ETC2_RGB8 = 180,
    ETC2_RGB8_sRGB = 181,
    ETC2_RGB8A1 = 182,
    ETC2_RGB8A1_sRGB = 183,
    ASTC_4x4_sRGB = 186,
    ASTC_5x4_sRGB = 187,
    ASTC_5x5_sRGB = 188,
    ASTC_6x5_sRGB = 189,
    ASTC_6x6_sRGB = 190,
    ASTC_8x5_sRGB = 192,
    ASTC_8x6_sRGB = 193,
    ASTC_8x8_sRGB = 194,
    ASTC_10x5_sRGB = 195,
    ASTC_10x6_sRGB = 196,
    ASTC_10x8_sRGB = 197,
    ASTC_10x10_sRGB = 198,
    ASTC_12x10_sRGB = 199,
    ASTC_12x12_sRGB = 200,
    ASTC_4x4_LDR = 204,
    ASTC_5x4_LDR = 205,
    ASTC_5x5_LDR = 206,
    ASTC_6x5_LDR = 207,
    ASTC_6x6_LDR = 208,
    ASTC_8x5_LDR = 210,
    ASTC_8x6_LDR = 211,
    ASTC_8x8_LDR = 212,
    ASTC_10x5_LDR = 213,
    ASTC_10x6_LDR = 214,
    ASTC_10x8_LDR = 215,
    ASTC_10x10_LDR = 216,
    ASTC_12x10_LDR = 217,
    ASTC_12x12_LDR = 218,
    ASTC_4x4_HDR = 222,
    ASTC_5x4_HDR = 223,
    ASTC_5x5_HDR = 224,
    ASTC_6x5_HDR = 225,
    ASTC_6x6_HDR = 226,
    ASTC_8x5_HDR = 228,
    ASTC_8x6_HDR = 229,
    ASTC_8x8_HDR = 230,
    ASTC_10x5_HDR = 231,
    ASTC_10x6_HDR = 232,
    ASTC_10x8_HDR = 233,
    ASTC_10x10_HDR = 234,
    ASTC_12x10_HDR = 235,
    ASTC_12x12_HDR = 236,
    GBGR422 = 240,
    BGRG422 = 241,
    Depth16Unorm = 250,
    Depth32Float = 252,
    Stencil8 = 253,
    Depth24Unorm_Stencil8 = 255,
    Depth32Float_Stencil8 = 260,
    X32_Stencil8 = 261,
    X24_Stencil8 = 262,
    BGRA10_XR = 552,
    BGRA10_XR_SRGB = 553,
    BGR10_XR = 554,
    BGR10_XR_SRGB = 555,
}
<|endoftext|>


<commit_before>use super::errors::{BlockOperationError, IndexedAttestationInvalid as Invalid};
use super::signature_sets::indexed_attestation_signature_set;
use crate::VerifySignatures;
use std::collections::HashSet;
use std::iter::FromIterator;
use types::*;

type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;

fn error(reason: Invalid) -> BlockOperationError<Invalid> {
    BlockOperationError::invalid(reason)
}

/// Verify an `IndexedAttestation`.
///
/// Spec v0.8.0
pub fn is_valid_indexed_attestation<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation<T>,
    verify_signatures: VerifySignatures,
    spec: &ChainSpec,
) -> Result<()> {
    let bit_0_indices = &indexed_attestation.custody_bit_0_indices;
    let bit_1_indices = &indexed_attestation.custody_bit_1_indices;

    // Verify no index has custody bit equal to 1 [to be removed in phase 1]
    verify!(bit_1_indices.is_empty(), Invalid::CustodyBitfieldHasSetBits);

    // Verify max number of indices
    let total_indices = bit_0_indices.len() + bit_1_indices.len();
    verify!(
        total_indices <= T::MaxValidatorsPerCommittee::to_usize(),
        Invalid::MaxIndicesExceed(T::MaxValidatorsPerCommittee::to_usize(), total_indices)
    );

    // Verify index sets are disjoint
    let custody_bit_intersection: HashSet<&u64> =
        &HashSet::from_iter(bit_0_indices.iter()) & &HashSet::from_iter(bit_1_indices.iter());
    verify!(
        custody_bit_intersection.is_empty(),
        Invalid::CustodyBitValidatorsIntersect
    );

    // Check that both vectors of indices are sorted
    let check_sorted = |list: &[u64]| -> Result<()> {
        list.windows(2).enumerate().try_for_each(|(i, pair)| {
            if pair[0] >= pair[1] {
                return Err(error(Invalid::BadValidatorIndicesOrdering(i)));
            } else {
                Ok(())
            }
        })?;
        Ok(())
    };
    check_sorted(&bit_0_indices)?;
    check_sorted(&bit_1_indices)?;

    dbg!(indexed_attestation_signature_set(
        state,
        &indexed_attestation.signature,
        &indexed_attestation,
        spec
    )?);
    dbg!(&bit_0_indices);
    dbg!(&bit_1_indices);

    if verify_signatures.is_true() {
        verify!(
            indexed_attestation_signature_set(
                state,
                &indexed_attestation.signature,
                &indexed_attestation,
                spec
            )?
            .is_valid(),
            Invalid::BadSignature
        );
    }

    Ok(())
}
<commit_msg>fix pauls shit (#528)<commit_after>use super::errors::{BlockOperationError, IndexedAttestationInvalid as Invalid};
use super::signature_sets::indexed_attestation_signature_set;
use crate::VerifySignatures;
use std::collections::HashSet;
use std::iter::FromIterator;
use types::*;

type Result<T> = std::result::Result<T, BlockOperationError<Invalid>>;

fn error(reason: Invalid) -> BlockOperationError<Invalid> {
    BlockOperationError::invalid(reason)
}

/// Verify an `IndexedAttestation`.
///
/// Spec v0.8.0
pub fn is_valid_indexed_attestation<T: EthSpec>(
    state: &BeaconState<T>,
    indexed_attestation: &IndexedAttestation<T>,
    verify_signatures: VerifySignatures,
    spec: &ChainSpec,
) -> Result<()> {
    let bit_0_indices = &indexed_attestation.custody_bit_0_indices;
    let bit_1_indices = &indexed_attestation.custody_bit_1_indices;

    // Verify no index has custody bit equal to 1 [to be removed in phase 1]
    verify!(bit_1_indices.is_empty(), Invalid::CustodyBitfieldHasSetBits);

    // Verify max number of indices
    let total_indices = bit_0_indices.len() + bit_1_indices.len();
    verify!(
        total_indices <= T::MaxValidatorsPerCommittee::to_usize(),
        Invalid::MaxIndicesExceed(T::MaxValidatorsPerCommittee::to_usize(), total_indices)
    );

    // Verify index sets are disjoint
    let custody_bit_intersection: HashSet<&u64> =
        &HashSet::from_iter(bit_0_indices.iter()) & &HashSet::from_iter(bit_1_indices.iter());
    verify!(
        custody_bit_intersection.is_empty(),
        Invalid::CustodyBitValidatorsIntersect
    );

    // Check that both vectors of indices are sorted
    let check_sorted = |list: &[u64]| -> Result<()> {
        list.windows(2).enumerate().try_for_each(|(i, pair)| {
            if pair[0] >= pair[1] {
                return Err(error(Invalid::BadValidatorIndicesOrdering(i)));
            } else {
                Ok(())
            }
        })?;
        Ok(())
    };
    check_sorted(&bit_0_indices)?;
    check_sorted(&bit_1_indices)?;

    if verify_signatures.is_true() {
        verify!(
            indexed_attestation_signature_set(
                state,
                &indexed_attestation.signature,
                &indexed_attestation,
                spec
            )?
            .is_valid(),
            Invalid::BadSignature
        );
    }

    Ok(())
}
<|endoftext|>


<commit_before>use std::path::Path;
use test;

use super::parse_solver;
use super::graph::Node;
use super::solver::SolverCx;

fn run_dir(b: &mut test::Bencher,
           name: &str,
           seq_threshold: usize,
           exp_weight: usize,
           exp_path: Vec<usize>) {
    let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
    let tsp_path = manifest_dir.join("data/tsp/").join(name);
    let graph = parse_solver(&tsp_path).unwrap();
    let mut solution = None;
    b.iter(|| {
        let mut solver = SolverCx::new(&graph, seq_threshold);
        solver.search_from(Node::new(0));
        solution = Some(solver.into_result());
    });
    let (path, weight) = solution.unwrap();
    let path: Vec<usize> = path.unwrap().iter().map(|n| n.index()).collect();
    assert_eq!(exp_weight, weight.to_usize(),
               "actual weight ({:?}) did not match expectation ({:?})", weight, exp_weight);
    assert_eq!(exp_path, path,
               "best path ({:?}) did not match expectation ({:?})", path, exp_path);
}

#[bench]
fn dj10(b: &mut test::Bencher) {
    // these numbers are tuned to "not take THAT long" in cargo bench,
    // basically, but still exercise the spawning stuff -- each run
    // should spawn 6! (720) tasks or so this way.
    run_dir(b, "dj10.tsp", 4, 2577, vec![0, 1, 3, 2, 4, 6, 8, 7, 5, 9, 0]);
}
<commit_msg>tsp: normalize the direction of the benchmarked path<commit_after>use std::path::Path;
use test;

use super::parse_solver;
use super::graph::Node;
use super::solver::SolverCx;

fn run_dir(b: &mut test::Bencher,
           name: &str,
           seq_threshold: usize,
           exp_weight: usize,
           exp_path: Vec<usize>) {
    let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR"));
    let tsp_path = manifest_dir.join("data/tsp/").join(name);
    let graph = parse_solver(&tsp_path).unwrap();
    let mut solution = None;
    b.iter(|| {
        let mut solver = SolverCx::new(&graph, seq_threshold);
        solver.search_from(Node::new(0));
        solution = Some(solver.into_result());
    });
    let (path, weight) = solution.unwrap();
    let mut path: Vec<usize> = path.unwrap().iter().map(|n| n.index()).collect();
    if path.iter().rev().lt(&path) {
        path.reverse(); // normalize the direction
    }
    assert_eq!(exp_weight, weight.to_usize(),
               "actual weight ({:?}) did not match expectation ({:?})", weight, exp_weight);
    assert_eq!(exp_path, path,
               "best path ({:?}) did not match expectation ({:?})", path, exp_path);
}

#[bench]
fn dj10(b: &mut test::Bencher) {
    // these numbers are tuned to "not take THAT long" in cargo bench,
    // basically, but still exercise the spawning stuff -- each run
    // should spawn 6! (720) tasks or so this way.
    run_dir(b, "dj10.tsp", 4, 2577, vec![0, 1, 3, 2, 4, 6, 8, 7, 5, 9, 0]);
}
<|endoftext|>


<commit_before>extern crate rlp;

use super::bytes;
use super::config;
use super::utils;
use super::blake2;
use super::active_state;
use super::aggregate_vote;
use super::crystallized_state;
use super::crosslink_record;
use super::partial_crosslink_record;
use super::recent_proposer_record;
use super::validator_record;
use super::block;

pub mod new_active_state;
pub mod crosslinks;
pub mod deposits;
pub mod epoch;
pub mod ffg;
pub mod proposers;
pub mod shuffling;
pub mod validators;
pub mod attestors;
<commit_msg>Implement compute_state_transition()<commit_after>extern crate rlp;

use super::bytes;
use super::config;
use super::utils;
use super::blake2;
use super::active_state;
use super::aggregate_vote;
use super::crystallized_state;
use super::crosslink_record;
use super::partial_crosslink_record;
use super::recent_proposer_record;
use super::validator_record;
use super::block;

pub mod new_active_state;
pub mod crosslinks;
pub mod deposits;
pub mod epoch;
pub mod ffg;
pub mod proposers;
pub mod shuffling;
pub mod validators;
pub mod attestors;

use super::block::Block;
use super::config::Config;
use super::crystallized_state::CrystallizedState;
use super::active_state::ActiveState;
use super::transition::epoch::initialize_new_epoch;
use super::transition::new_active_state::compute_new_active_state;

pub fn compute_state_transition (
    parent_cry_state: &CrystallizedState,
    parent_act_state: &ActiveState,
    parent_block: &Block,
    block: &Block,
    config: &Config)
    -> (CrystallizedState, ActiveState)
{
    let is_new_epoch =  parent_act_state.height %
        config.epoch_length == 0;

    let (cry_state, mut act_state) = match is_new_epoch {
        false => (parent_cry_state.clone(), parent_act_state.clone()),
        true => initialize_new_epoch(
            &parent_cry_state,
            &parent_act_state,
            &config)
    };

    act_state = compute_new_active_state(
        &cry_state,
        &act_state,
        &parent_block,
        &block,
        &config);

    (cry_state, act_state)
}
<|endoftext|>


<commit_before>// extern crate rand;
//
// trait ByteGenerator {
//     fn generate_byte() -> u8;
// }
//
// struct RandomByteGenerator;
//
// impl ByteGenerator for RandomByteGenerator {
//     /** Return a random 8 bit integer. */
//     fn generate_byte() -> u8 {
//         rand::random()
//     }
// }
//
// struct BitMaskOpcode<G> {
//     mask: u8,
//     generator: G
// }
//
// impl<G: ByteGenerator> BitMaskOpcode<G> {
//     fn new(mask: u8) -> Self {
//         BitMaskOpcode {
//             mask,
//             generator: RandomByteGenerator
//         }
//     }
//
//     fn set_byte_generator(&mut self, generator: G) {
//         self.generator = generator;
//     }
//
//     fn invoke(&self) -> u8 {
//         self.mask & self.generator::generate_byte()
//     }
// }
<commit_msg>Delete bitmaskopcode.rs<commit_after><|endoftext|>


<commit_before>
use du::{Entry,EntryType};

#[derive(PartialEq,Eq)]
pub enum DisplayType {
    Normal,
    HumanReadable,
    KiBytes,
}

pub struct Displayer {
    dt: DisplayType,
    num: usize,
}

impl Displayer {
    pub fn new(dt: DisplayType, num: usize) -> Displayer {
        Displayer { dt: dt, num: num }
    }

    pub fn display(&self, entry: &Entry) {
        self.show_usage_level(entry, 0, entry.size) ;
    }

    fn to_human(&self, size: u64) -> String {

        let size = size as f64;
        let k=1024.0;
        if size < k {
            format!("{:-5.1}", size)
        } else if size < k*k {
            format!("{:-5.1}K", size/k)
        } else if size < k*k*k {
            format!("{:-5.1}M", size/k/k)
        } else if size < k*k*k*k {
            format!("{:-5.1}G", size/k/k/k)
        } else if size < k*k*k*k*k {
            format!("{:-5.1}T", size/k/k/k/k)
        } else if size < k*k*k*k*k*k {
            format!("{:-5.1}P", size/k/k/k/k/k)
        } else {
            format!("{:-5.1}E", size/k/k/k/k/k/k)
        }
    }

    fn show_entry(&self, level: u32, entry: &Entry, allsize: u64) {
            //println!("{:?}", entry);
            for _ in 0..level {
                print!("   ");
            }

            let pct = if allsize == 0 { 0.0 } else { entry.size as f64 / allsize as f64 * 100.0 };

            print!("{:>5.1}% ", pct);

            match self.dt {
                DisplayType::Normal        => { print!("{:12}", entry.size); }
                DisplayType::KiBytes       => { print!("{:9}", entry.size/1024); }
                DisplayType::HumanReadable => { print!("{:6}", self.to_human(entry.size)); }
            }

            print!(" {}", entry.name.display());
            match entry.entrytype {
                EntryType::Directory => { print!("/"); },
                EntryType::OtherFs   => { print!(" [X]"); },
                EntryType::Other     => { print!(" [?]"); },
                _ => {}
            };
            println!();

    }

    fn show_usage_level(&self, entry: &Entry, level: u32, allsize: u64) {
            self.show_entry(level, &entry, allsize);
            if entry.entrytype == EntryType::Directory {
                    let mut n = self.num;
                    for ce in &entry.children {
                        self.show_usage_level(&ce, level+1, entry.size);
                        n = n-1;
                        if n == 0 { break; }
                    }
            }
    }
}

<commit_msg>fixed alignment of non-prefixed human readable sizes<commit_after>
use du::{Entry,EntryType};

#[derive(PartialEq,Eq)]
pub enum DisplayType {
    Normal,
    HumanReadable,
    KiBytes,
}

pub struct Displayer {
    dt: DisplayType,
    num: usize,
}

impl Displayer {
    pub fn new(dt: DisplayType, num: usize) -> Displayer {
        Displayer { dt: dt, num: num }
    }

    pub fn display(&self, entry: &Entry) {
        self.show_usage_level(entry, 0, entry.size) ;
    }

    fn to_human(&self, size: u64) -> String {

        let size = size as f64;
        let k=1024.0;
        if size < k {
            format!("{:-6}", size)
        } else if size < k*k {
            format!("{:-5.1}K", size/k)
        } else if size < k*k*k {
            format!("{:-5.1}M", size/k/k)
        } else if size < k*k*k*k {
            format!("{:-5.1}G", size/k/k/k)
        } else if size < k*k*k*k*k {
            format!("{:-5.1}T", size/k/k/k/k)
        } else if size < k*k*k*k*k*k {
            format!("{:-5.1}P", size/k/k/k/k/k)
        } else {
            format!("{:-5.1}E", size/k/k/k/k/k/k)
        }
    }

    fn show_entry(&self, level: u32, entry: &Entry, allsize: u64) {
            //println!("{:?}", entry);
            for _ in 0..level {
                print!("   ");
            }

            let pct = if allsize == 0 { 0.0 } else { entry.size as f64 / allsize as f64 * 100.0 };

            print!("{:>5.1}% ", pct);

            match self.dt {
                DisplayType::Normal        => { print!("{:12}", entry.size); }
                DisplayType::KiBytes       => { print!("{:9}", entry.size/1024); }
                DisplayType::HumanReadable => { print!("{:6}", self.to_human(entry.size)); }
            }

            print!(" {}", entry.name.display());
            match entry.entrytype {
                EntryType::Directory => { print!("/"); },
                EntryType::OtherFs   => { print!(" [X]"); },
                EntryType::Other     => { print!(" [?]"); },
                _ => {}
            };
            println!();

    }

    fn show_usage_level(&self, entry: &Entry, level: u32, allsize: u64) {
            self.show_entry(level, &entry, allsize);
            if entry.entrytype == EntryType::Directory {
                    let mut n = self.num;
                    for ce in &entry.children {
                        self.show_usage_level(&ce, level+1, entry.size);
                        n = n-1;
                        if n == 0 { break; }
                    }
            }
    }
}

<|endoftext|>


<commit_before>//! Checks for continue statements in loops that are redundant.
//!
//! For example, the lint would catch
//!
//! ```rust
//! let mut a = 1;
//! let x = true;
//!
//! while a < 5 {
//!     a = 6;
//!     if x {
//!         // ...
//!     } else {
//!         continue;
//!     }
//!     println!("Hello, world");
//! }
//! ```
//!
//! And suggest something like this:
//!
//! ```rust
//! let mut a = 1;
//! let x = true;
//!
//! while a < 5 {
//!     a = 6;
//!     if x {
//!         // ...
//!         println!("Hello, world");
//!     }
//! }
//! ```
//!
//! This lint is **warn** by default.
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use std::borrow::Cow;
use syntax::ast;
use syntax::source_map::{original_sp, DUMMY_SP};

use crate::utils::{in_macro_or_desugar, snippet, snippet_block, span_help_and_lint, trim_multiline};

declare_clippy_lint! {
    /// **What it does:** The lint checks for `if`-statements appearing in loops
    /// that contain a `continue` statement in either their main blocks or their
    /// `else`-blocks, when omitting the `else`-block possibly with some
    /// rearrangement of code can make the code easier to understand.
    ///
    /// **Why is this bad?** Having explicit `else` blocks for `if` statements
    /// containing `continue` in their THEN branch adds unnecessary branching and
    /// nesting to the code. Having an else block containing just `continue` can
    /// also be better written by grouping the statements following the whole `if`
    /// statement within the THEN block and omitting the else block completely.
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```rust
    /// while condition() {
    ///     update_condition();
    ///     if x {
    ///         // ...
    ///     } else {
    ///         continue;
    ///     }
    ///     println!("Hello, world");
    /// }
    /// ```
    ///
    /// Could be rewritten as
    ///
    /// ```rust
    /// while condition() {
    ///     update_condition();
    ///     if x {
    ///         // ...
    ///         println!("Hello, world");
    ///     }
    /// }
    /// ```
    ///
    /// As another example, the following code
    ///
    /// ```rust
    /// loop {
    ///     if waiting() {
    ///         continue;
    ///     } else {
    ///         // Do something useful
    ///     }
    /// }
    /// ```
    /// Could be rewritten as
    ///
    /// ```rust
    /// loop {
    ///     if waiting() {
    ///         continue;
    ///     }
    ///     // Do something useful
    /// }
    /// ```
    pub NEEDLESS_CONTINUE,
    pedantic,
    "`continue` statements that can be replaced by a rearrangement of code"
}

declare_lint_pass!(NeedlessContinue => [NEEDLESS_CONTINUE]);

impl EarlyLintPass for NeedlessContinue {
    fn check_expr(&mut self, ctx: &EarlyContext<'_>, expr: &ast::Expr) {
        if !in_macro_or_desugar(expr.span) {
            check_and_warn(ctx, expr);
        }
    }
}

/* This lint has to mainly deal with two cases of needless continue
 * statements. */
// Case 1 [Continue inside else block]:
//
//     loop {
//         // region A
//         if cond {
//             // region B
//         } else {
//             continue;
//         }
//         // region C
//     }
//
// This code can better be written as follows:
//
//     loop {
//         // region A
//         if cond {
//             // region B
//             // region C
//         }
//     }
//
// Case 2 [Continue inside then block]:
//
//     loop {
//       // region A
//       if cond {
//           continue;
//           // potentially more code here.
//       } else {
//           // region B
//       }
//       // region C
//     }
//
//
// This snippet can be refactored to:
//
//     loop {
//       // region A
//       if !cond {
//           // region B
//           // region C
//       }
//     }
//

/// Given an expression, returns true if either of the following is true
///
/// - The expression is a `continue` node.
/// - The expression node is a block with the first statement being a
/// `continue`.
fn needless_continue_in_else(else_expr: &ast::Expr, label: Option<&ast::Label>) -> bool {
    match else_expr.node {
        ast::ExprKind::Block(ref else_block, _) => is_first_block_stmt_continue(else_block, label),
        ast::ExprKind::Continue(l) => compare_labels(label, l.as_ref()),
        _ => false,
    }
}

fn is_first_block_stmt_continue(block: &ast::Block, label: Option<&ast::Label>) -> bool {
    block.stmts.get(0).map_or(false, |stmt| match stmt.node {
        ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => {
            if let ast::ExprKind::Continue(ref l) = e.node {
                compare_labels(label, l.as_ref())
            } else {
                false
            }
        },
        _ => false,
    })
}

/// If the `continue` has a label, check it matches the label of the loop.
fn compare_labels(loop_label: Option<&ast::Label>, continue_label: Option<&ast::Label>) -> bool {
    match (loop_label, continue_label) {
        // `loop { continue; }` or `'a loop { continue; }`
        (_, None) => true,
        // `loop { continue 'a; }`
        (None, _) => false,
        // `'a loop { continue 'a; }` or `'a loop { continue 'b; }`
        (Some(x), Some(y)) => x.ident == y.ident,
    }
}

/// If `expr` is a loop expression (while/while let/for/loop), calls `func` with
/// the AST object representing the loop block of `expr`.
fn with_loop_block<F>(expr: &ast::Expr, mut func: F)
where
    F: FnMut(&ast::Block, Option<&ast::Label>),
{
    if let ast::ExprKind::While(_, loop_block, label)
        | ast::ExprKind::ForLoop(_, _, loop_block, label)
        | ast::ExprKind::Loop(loop_block, label)
        = &expr.node
    {
        func(loop_block, label.as_ref());
    }
}

/// If `stmt` is an if expression node with an `else` branch, calls func with
/// the
/// following:
///
/// - The `if` expression itself,
/// - The `if` condition expression,
/// - The `then` block, and
/// - The `else` expression.
fn with_if_expr<F>(stmt: &ast::Stmt, mut func: F)
where
    F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr),
{
    match stmt.node {
        ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => {
            if let ast::ExprKind::If(ref cond, ref if_block, Some(ref else_expr)) = e.node {
                func(e, cond, if_block, else_expr);
            }
        },
        _ => {},
    }
}

/// A type to distinguish between the two distinct cases this lint handles.
#[derive(Copy, Clone, Debug)]
enum LintType {
    ContinueInsideElseBlock,
    ContinueInsideThenBlock,
}

/// Data we pass around for construction of help messages.
struct LintData<'a> {
    /// The `if` expression encountered in the above loop.
    if_expr: &'a ast::Expr,
    /// The condition expression for the above `if`.
    if_cond: &'a ast::Expr,
    /// The `then` block of the `if` statement.
    if_block: &'a ast::Block,
    /// The `else` block of the `if` statement.
    /// Note that we only work with `if` exprs that have an `else` branch.
    else_expr: &'a ast::Expr,
    /// The 0-based index of the `if` statement in the containing loop block.
    stmt_idx: usize,
    /// The statements of the loop block.
    block_stmts: &'a [ast::Stmt],
}

const MSG_REDUNDANT_ELSE_BLOCK: &str = "This else block is redundant.\n";

const MSG_ELSE_BLOCK_NOT_NEEDED: &str = "There is no need for an explicit `else` block for this `if` \
                                         expression\n";

const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "Consider dropping the else clause and merging the code that \
                                             follows (in the loop) with the if block, like so:\n";

const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the else clause, and moving out the code in the else \
                                   block, like so:\n";

fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) {
    // snip    is the whole *help* message that appears after the warning.
    // message is the warning message.
    // expr    is the expression which the lint warning message refers to.
    let (snip, message, expr) = match typ {
        LintType::ContinueInsideElseBlock => (
            suggestion_snippet_for_continue_inside_else(ctx, data, header),
            MSG_REDUNDANT_ELSE_BLOCK,
            data.else_expr,
        ),
        LintType::ContinueInsideThenBlock => (
            suggestion_snippet_for_continue_inside_if(ctx, data, header),
            MSG_ELSE_BLOCK_NOT_NEEDED,
            data.if_expr,
        ),
    };
    span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip);
}

fn suggestion_snippet_for_continue_inside_if<'a>(
    ctx: &EarlyContext<'_>,
    data: &'a LintData<'_>,
    header: &str,
) -> String {
    let cond_code = snippet(ctx, data.if_cond.span, "..");

    let if_code = format!("if {} {{\n    continue;\n}}\n", cond_code);
    /* ^^^^--- Four spaces of indentation. */
    // region B
    let else_code = snippet(ctx, data.else_expr.span, "..").into_owned();
    let else_code = erode_block(&else_code);
    let else_code = trim_multiline(Cow::from(else_code), false);

    let mut ret = String::from(header);
    ret.push_str(&if_code);
    ret.push_str(&else_code);
    ret.push_str("\n...");
    ret
}

fn suggestion_snippet_for_continue_inside_else<'a>(
    ctx: &EarlyContext<'_>,
    data: &'a LintData<'_>,
    header: &str,
) -> String {
    let cond_code = snippet(ctx, data.if_cond.span, "..");
    let mut if_code = format!("if {} {{\n", cond_code);

    // Region B
    let block_code = &snippet(ctx, data.if_block.span, "..").into_owned();
    let block_code = erode_block(block_code);
    let block_code = trim_multiline(Cow::from(block_code), false);

    if_code.push_str(&block_code);

    // Region C
    // These is the code in the loop block that follows the if/else construction
    // we are complaining about. We want to pull all of this code into the
    // `then` block of the `if` statement.
    let to_annex = data.block_stmts[data.stmt_idx + 1..]
        .iter()
        .map(|stmt| original_sp(stmt.span, DUMMY_SP))
        .map(|span| snippet_block(ctx, span, "..").into_owned())
        .collect::<Vec<_>>()
        .join("\n");

    let mut ret = String::from(header);

    ret.push_str(&if_code);
    ret.push_str("\n// Merged code follows...");
    ret.push_str(&to_annex);
    ret.push_str("\n}\n");
    ret
}

fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) {
    with_loop_block(expr, |loop_block, label| {
        for (i, stmt) in loop_block.stmts.iter().enumerate() {
            with_if_expr(stmt, |if_expr, cond, then_block, else_expr| {
                let data = &LintData {
                    stmt_idx: i,
                    if_expr,
                    if_cond: cond,
                    if_block: then_block,
                    else_expr,
                    block_stmts: &loop_block.stmts,
                };
                if needless_continue_in_else(else_expr, label) {
                    emit_warning(
                        ctx,
                        data,
                        DROP_ELSE_BLOCK_AND_MERGE_MSG,
                        LintType::ContinueInsideElseBlock,
                    );
                } else if is_first_block_stmt_continue(then_block, label) {
                    emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock);
                }
            });
        }
    });
}

/// Eats at `s` from the end till a closing brace `}` is encountered, and then
/// continues eating till a non-whitespace character is found.
/// e.g., the string
///
/// ```rust
/// {
///     let x = 5;
/// }
/// ```
///
/// is transformed to
///
/// ```ignore
///     {
///         let x = 5;
/// ```
///
/// NOTE: when there is no closing brace in `s`, `s` is _not_ preserved, i.e.,
/// an empty string will be returned in that case.
pub fn erode_from_back(s: &str) -> String {
    let mut ret = String::from(s);
    while ret.pop().map_or(false, |c| c != '}') {}
    while let Some(c) = ret.pop() {
        if !c.is_whitespace() {
            ret.push(c);
            break;
        }
    }
    ret
}

/// Eats at `s` from the front by first skipping all leading whitespace. Then,
/// any number of opening braces are eaten, followed by any number of newlines.
/// e.g.,  the string
///
/// ```ignore
///         {
///             something();
///             inside_a_block();
///         }
/// ```
///
/// is transformed to
///
/// ```ignore
///             something();
///             inside_a_block();
///         }
/// ```
pub fn erode_from_front(s: &str) -> String {
    s.chars()
        .skip_while(|c| c.is_whitespace())
        .skip_while(|c| *c == '{')
        .skip_while(|c| *c == '\n')
        .collect::<String>()
}

/// If `s` contains the code for a block, delimited by braces, this function
/// tries to get the contents of the block. If there is no closing brace
/// present,
/// an empty string is returned.
pub fn erode_block(s: &str) -> String {
    erode_from_back(&erode_from_front(s))
}
<commit_msg>Pacify rustfmt.<commit_after>//! Checks for continue statements in loops that are redundant.
//!
//! For example, the lint would catch
//!
//! ```rust
//! let mut a = 1;
//! let x = true;
//!
//! while a < 5 {
//!     a = 6;
//!     if x {
//!         // ...
//!     } else {
//!         continue;
//!     }
//!     println!("Hello, world");
//! }
//! ```
//!
//! And suggest something like this:
//!
//! ```rust
//! let mut a = 1;
//! let x = true;
//!
//! while a < 5 {
//!     a = 6;
//!     if x {
//!         // ...
//!         println!("Hello, world");
//!     }
//! }
//! ```
//!
//! This lint is **warn** by default.
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint};
use std::borrow::Cow;
use syntax::ast;
use syntax::source_map::{original_sp, DUMMY_SP};

use crate::utils::{in_macro_or_desugar, snippet, snippet_block, span_help_and_lint, trim_multiline};

declare_clippy_lint! {
    /// **What it does:** The lint checks for `if`-statements appearing in loops
    /// that contain a `continue` statement in either their main blocks or their
    /// `else`-blocks, when omitting the `else`-block possibly with some
    /// rearrangement of code can make the code easier to understand.
    ///
    /// **Why is this bad?** Having explicit `else` blocks for `if` statements
    /// containing `continue` in their THEN branch adds unnecessary branching and
    /// nesting to the code. Having an else block containing just `continue` can
    /// also be better written by grouping the statements following the whole `if`
    /// statement within the THEN block and omitting the else block completely.
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```rust
    /// while condition() {
    ///     update_condition();
    ///     if x {
    ///         // ...
    ///     } else {
    ///         continue;
    ///     }
    ///     println!("Hello, world");
    /// }
    /// ```
    ///
    /// Could be rewritten as
    ///
    /// ```rust
    /// while condition() {
    ///     update_condition();
    ///     if x {
    ///         // ...
    ///         println!("Hello, world");
    ///     }
    /// }
    /// ```
    ///
    /// As another example, the following code
    ///
    /// ```rust
    /// loop {
    ///     if waiting() {
    ///         continue;
    ///     } else {
    ///         // Do something useful
    ///     }
    /// }
    /// ```
    /// Could be rewritten as
    ///
    /// ```rust
    /// loop {
    ///     if waiting() {
    ///         continue;
    ///     }
    ///     // Do something useful
    /// }
    /// ```
    pub NEEDLESS_CONTINUE,
    pedantic,
    "`continue` statements that can be replaced by a rearrangement of code"
}

declare_lint_pass!(NeedlessContinue => [NEEDLESS_CONTINUE]);

impl EarlyLintPass for NeedlessContinue {
    fn check_expr(&mut self, ctx: &EarlyContext<'_>, expr: &ast::Expr) {
        if !in_macro_or_desugar(expr.span) {
            check_and_warn(ctx, expr);
        }
    }
}

/* This lint has to mainly deal with two cases of needless continue
 * statements. */
// Case 1 [Continue inside else block]:
//
//     loop {
//         // region A
//         if cond {
//             // region B
//         } else {
//             continue;
//         }
//         // region C
//     }
//
// This code can better be written as follows:
//
//     loop {
//         // region A
//         if cond {
//             // region B
//             // region C
//         }
//     }
//
// Case 2 [Continue inside then block]:
//
//     loop {
//       // region A
//       if cond {
//           continue;
//           // potentially more code here.
//       } else {
//           // region B
//       }
//       // region C
//     }
//
//
// This snippet can be refactored to:
//
//     loop {
//       // region A
//       if !cond {
//           // region B
//           // region C
//       }
//     }
//

/// Given an expression, returns true if either of the following is true
///
/// - The expression is a `continue` node.
/// - The expression node is a block with the first statement being a
/// `continue`.
fn needless_continue_in_else(else_expr: &ast::Expr, label: Option<&ast::Label>) -> bool {
    match else_expr.node {
        ast::ExprKind::Block(ref else_block, _) => is_first_block_stmt_continue(else_block, label),
        ast::ExprKind::Continue(l) => compare_labels(label, l.as_ref()),
        _ => false,
    }
}

fn is_first_block_stmt_continue(block: &ast::Block, label: Option<&ast::Label>) -> bool {
    block.stmts.get(0).map_or(false, |stmt| match stmt.node {
        ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => {
            if let ast::ExprKind::Continue(ref l) = e.node {
                compare_labels(label, l.as_ref())
            } else {
                false
            }
        },
        _ => false,
    })
}

/// If the `continue` has a label, check it matches the label of the loop.
fn compare_labels(loop_label: Option<&ast::Label>, continue_label: Option<&ast::Label>) -> bool {
    match (loop_label, continue_label) {
        // `loop { continue; }` or `'a loop { continue; }`
        (_, None) => true,
        // `loop { continue 'a; }`
        (None, _) => false,
        // `'a loop { continue 'a; }` or `'a loop { continue 'b; }`
        (Some(x), Some(y)) => x.ident == y.ident,
    }
}

/// If `expr` is a loop expression (while/while let/for/loop), calls `func` with
/// the AST object representing the loop block of `expr`.
fn with_loop_block<F>(expr: &ast::Expr, mut func: F)
where
    F: FnMut(&ast::Block, Option<&ast::Label>),
{
    if let ast::ExprKind::While(_, loop_block, label)
    | ast::ExprKind::ForLoop(_, _, loop_block, label)
    | ast::ExprKind::Loop(loop_block, label) = &expr.node
    {
        func(loop_block, label.as_ref());
    }
}

/// If `stmt` is an if expression node with an `else` branch, calls func with
/// the
/// following:
///
/// - The `if` expression itself,
/// - The `if` condition expression,
/// - The `then` block, and
/// - The `else` expression.
fn with_if_expr<F>(stmt: &ast::Stmt, mut func: F)
where
    F: FnMut(&ast::Expr, &ast::Expr, &ast::Block, &ast::Expr),
{
    match stmt.node {
        ast::StmtKind::Semi(ref e) | ast::StmtKind::Expr(ref e) => {
            if let ast::ExprKind::If(ref cond, ref if_block, Some(ref else_expr)) = e.node {
                func(e, cond, if_block, else_expr);
            }
        },
        _ => {},
    }
}

/// A type to distinguish between the two distinct cases this lint handles.
#[derive(Copy, Clone, Debug)]
enum LintType {
    ContinueInsideElseBlock,
    ContinueInsideThenBlock,
}

/// Data we pass around for construction of help messages.
struct LintData<'a> {
    /// The `if` expression encountered in the above loop.
    if_expr: &'a ast::Expr,
    /// The condition expression for the above `if`.
    if_cond: &'a ast::Expr,
    /// The `then` block of the `if` statement.
    if_block: &'a ast::Block,
    /// The `else` block of the `if` statement.
    /// Note that we only work with `if` exprs that have an `else` branch.
    else_expr: &'a ast::Expr,
    /// The 0-based index of the `if` statement in the containing loop block.
    stmt_idx: usize,
    /// The statements of the loop block.
    block_stmts: &'a [ast::Stmt],
}

const MSG_REDUNDANT_ELSE_BLOCK: &str = "This else block is redundant.\n";

const MSG_ELSE_BLOCK_NOT_NEEDED: &str = "There is no need for an explicit `else` block for this `if` \
                                         expression\n";

const DROP_ELSE_BLOCK_AND_MERGE_MSG: &str = "Consider dropping the else clause and merging the code that \
                                             follows (in the loop) with the if block, like so:\n";

const DROP_ELSE_BLOCK_MSG: &str = "Consider dropping the else clause, and moving out the code in the else \
                                   block, like so:\n";

fn emit_warning<'a>(ctx: &EarlyContext<'_>, data: &'a LintData<'_>, header: &str, typ: LintType) {
    // snip    is the whole *help* message that appears after the warning.
    // message is the warning message.
    // expr    is the expression which the lint warning message refers to.
    let (snip, message, expr) = match typ {
        LintType::ContinueInsideElseBlock => (
            suggestion_snippet_for_continue_inside_else(ctx, data, header),
            MSG_REDUNDANT_ELSE_BLOCK,
            data.else_expr,
        ),
        LintType::ContinueInsideThenBlock => (
            suggestion_snippet_for_continue_inside_if(ctx, data, header),
            MSG_ELSE_BLOCK_NOT_NEEDED,
            data.if_expr,
        ),
    };
    span_help_and_lint(ctx, NEEDLESS_CONTINUE, expr.span, message, &snip);
}

fn suggestion_snippet_for_continue_inside_if<'a>(
    ctx: &EarlyContext<'_>,
    data: &'a LintData<'_>,
    header: &str,
) -> String {
    let cond_code = snippet(ctx, data.if_cond.span, "..");

    let if_code = format!("if {} {{\n    continue;\n}}\n", cond_code);
    /* ^^^^--- Four spaces of indentation. */
    // region B
    let else_code = snippet(ctx, data.else_expr.span, "..").into_owned();
    let else_code = erode_block(&else_code);
    let else_code = trim_multiline(Cow::from(else_code), false);

    let mut ret = String::from(header);
    ret.push_str(&if_code);
    ret.push_str(&else_code);
    ret.push_str("\n...");
    ret
}

fn suggestion_snippet_for_continue_inside_else<'a>(
    ctx: &EarlyContext<'_>,
    data: &'a LintData<'_>,
    header: &str,
) -> String {
    let cond_code = snippet(ctx, data.if_cond.span, "..");
    let mut if_code = format!("if {} {{\n", cond_code);

    // Region B
    let block_code = &snippet(ctx, data.if_block.span, "..").into_owned();
    let block_code = erode_block(block_code);
    let block_code = trim_multiline(Cow::from(block_code), false);

    if_code.push_str(&block_code);

    // Region C
    // These is the code in the loop block that follows the if/else construction
    // we are complaining about. We want to pull all of this code into the
    // `then` block of the `if` statement.
    let to_annex = data.block_stmts[data.stmt_idx + 1..]
        .iter()
        .map(|stmt| original_sp(stmt.span, DUMMY_SP))
        .map(|span| snippet_block(ctx, span, "..").into_owned())
        .collect::<Vec<_>>()
        .join("\n");

    let mut ret = String::from(header);

    ret.push_str(&if_code);
    ret.push_str("\n// Merged code follows...");
    ret.push_str(&to_annex);
    ret.push_str("\n}\n");
    ret
}

fn check_and_warn<'a>(ctx: &EarlyContext<'_>, expr: &'a ast::Expr) {
    with_loop_block(expr, |loop_block, label| {
        for (i, stmt) in loop_block.stmts.iter().enumerate() {
            with_if_expr(stmt, |if_expr, cond, then_block, else_expr| {
                let data = &LintData {
                    stmt_idx: i,
                    if_expr,
                    if_cond: cond,
                    if_block: then_block,
                    else_expr,
                    block_stmts: &loop_block.stmts,
                };
                if needless_continue_in_else(else_expr, label) {
                    emit_warning(
                        ctx,
                        data,
                        DROP_ELSE_BLOCK_AND_MERGE_MSG,
                        LintType::ContinueInsideElseBlock,
                    );
                } else if is_first_block_stmt_continue(then_block, label) {
                    emit_warning(ctx, data, DROP_ELSE_BLOCK_MSG, LintType::ContinueInsideThenBlock);
                }
            });
        }
    });
}

/// Eats at `s` from the end till a closing brace `}` is encountered, and then
/// continues eating till a non-whitespace character is found.
/// e.g., the string
///
/// ```rust
/// {
///     let x = 5;
/// }
/// ```
///
/// is transformed to
///
/// ```ignore
///     {
///         let x = 5;
/// ```
///
/// NOTE: when there is no closing brace in `s`, `s` is _not_ preserved, i.e.,
/// an empty string will be returned in that case.
pub fn erode_from_back(s: &str) -> String {
    let mut ret = String::from(s);
    while ret.pop().map_or(false, |c| c != '}') {}
    while let Some(c) = ret.pop() {
        if !c.is_whitespace() {
            ret.push(c);
            break;
        }
    }
    ret
}

/// Eats at `s` from the front by first skipping all leading whitespace. Then,
/// any number of opening braces are eaten, followed by any number of newlines.
/// e.g.,  the string
///
/// ```ignore
///         {
///             something();
///             inside_a_block();
///         }
/// ```
///
/// is transformed to
///
/// ```ignore
///             something();
///             inside_a_block();
///         }
/// ```
pub fn erode_from_front(s: &str) -> String {
    s.chars()
        .skip_while(|c| c.is_whitespace())
        .skip_while(|c| *c == '{')
        .skip_while(|c| *c == '\n')
        .collect::<String>()
}

/// If `s` contains the code for a block, delimited by braces, this function
/// tries to get the contents of the block. If there is no closing brace
/// present,
/// an empty string is returned.
pub fn erode_block(s: &str) -> String {
    erode_from_back(&erode_from_front(s))
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use super::Position;
use super::symbols::SymbolTable;

pub type Functions = HashMap<String, Node<Function>>;

#[derive(PartialEq, Debug)]
pub struct Node<I> {
    pub pos: Position,
    pub node: I,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Type {
    Void,
    Bool,
    Int,
    Float,
    Str,
}

#[derive(PartialEq, Debug)]
pub enum Literal {
    Bool(bool),
    Int(i32),
    Float(f32),
    Str(String),
}

impl Literal {
    pub fn get_type(&self) -> Type {
        match *self {
            Literal::Bool(_) => Type::Bool,
            Literal::Int(_) => Type::Int,
            Literal::Float(_) => Type::Float,
            Literal::Str(_) => Type::Str,
        }
    }
}

#[derive(Debug)]
pub struct Variable {
    pub id: u32,
    pub type_: Type,
    pub name: String,
}

impl Variable {
    pub fn stub(name: String) -> Variable {
        Variable {
            id: 0,
            type_: Type::Void,
            name: name,
        }
    }

    pub fn eq_name_type(&self, other: &Variable) -> bool {
        self.type_ == other.type_ && self.name == other.name
    }
}

impl PartialEq for Variable {
    fn eq(&self, other: &Variable) -> bool {
        if self.id == 0 || other.id == 0 {
            false
        } else {
            self.id == other.id
        }
    }
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum UnaryOp {
    NOT,
    MINUS,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum BinaryOp {
    ADD,
    SUB,
    MUL,
    DIV,

    EQ,
    LT,
    LE,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Op {
    UnaryOp(UnaryOp),
    BinaryOp(BinaryOp),
}

#[derive(PartialEq, Debug)]
pub struct Program {
    pub functions: Functions,
}

#[derive(PartialEq, Debug)]
pub struct Function {
    pub name: String,
    pub filename: String,
    pub body: Node<Statement>,
    pub args: Vec<Rc<Variable>>,
    pub ret_type: Type,
    pub symbols: Rc<RefCell<SymbolTable>>,
}

#[derive(PartialEq, Debug)]
pub enum Statement {
    Expression {
        expr: Box<Node<Expression>>,
    },
    Declaration {
        var: Rc<Variable>,
    },
    Assignment {
        var: Rc<Variable>,
        expr: Box<Node<Expression>>,
    },
    If {
        cond: Box<Node<Expression>>,
        on_true: Box<Node<Statement>>,
        on_false: Option<Box<Node<Statement>>>,
    },
    While {
        cond: Box<Node<Expression>>,
        body: Box<Node<Statement>>,
    },
    Return {
        expr: Option<Box<Node<Expression>>>,
    },
    Compound {
        stmts: Vec<Node<Statement>>,
        symbols: Rc<RefCell<SymbolTable>>,
    },
}

impl Node<Statement> {
    /// Visit all statements with a given closure.
    ///
    /// The given closure is called for each statement with a reference to the
    /// given node. This reference inherits the lifetime of `self`. The return
    /// value indicates whether further statements should be visited or not.
    ///
    /// Use this method as alternative to the [Visitor].
    ///
    /// [Visitor]: <trait.Visitor.html>
    pub fn visit_stmt<'a>(&'a self, do_stmt: &mut FnMut(&'a Node<Statement>) -> bool) -> bool {
        do_stmt(self) || return false;
        match self.node {
            Statement::If { ref on_true, ref on_false, .. } => {
                on_true.visit_stmt(do_stmt) ||
                if let Some(ref stmt) = *on_false {
                    stmt.visit_stmt(do_stmt)
                } else {
                    true
                }
            }
            Statement::While { ref body, .. } => body.visit_stmt(do_stmt),
            Statement::Compound { ref stmts, .. } => {
                for stmt in stmts.iter() {
                    stmt.visit_stmt(do_stmt) || return false;
                }
                true
            }
            _ => true,
        }
    }

    /// Visit all expressions with a given closure.
    ///
    /// Same as [visit_stmt], but for expressions.
    ///
    /// [visit_stmt]: <struct.Node.html#method.visit_expr>
    pub fn visit_expr<'a>(&'a self, do_expr: &mut FnMut(&'a Node<Expression>) -> bool) -> bool {
        self.visit_stmt(&mut |stmt| {
            match stmt.node {
                Statement::Expression { ref expr } => do_expr(expr),
                Statement::Assignment { ref expr, .. } => do_expr(expr),
                Statement::If { ref cond, .. } => do_expr(cond),
                Statement::While { ref cond, .. } => do_expr(cond),
                Statement::Return { expr: Some(ref expr) } => do_expr(expr),
                _ => true,
            }
        })
    }
}

#[derive(PartialEq, Debug)]
pub enum Expression {
    Literal {
        lit: Literal,
    },
    Variable {
        var: Rc<Variable>,
    },
    Call {
        function: String,
        args: Vec<Node<Expression>>,
    },
    Unary {
        op: UnaryOp,
        expr: Box<Node<Expression>>,
    },
    Binary {
        op: BinaryOp,
        left: Box<Node<Expression>>,
        right: Box<Node<Expression>>,
    },
    Parenthesis {
        expr: Box<Node<Expression>>,
    },
}

impl Node<Expression> {
    /// Visit all expressions with a given closure.
    ///
    /// Same as [visit_stmt], but for expressions.
    ///
    /// [visit_stmt]: <struct.Node.html#method.visit_expr>
    pub fn visit_expr<'a>(&'a self, do_expr: &mut FnMut(&'a Node<Expression>) -> bool) -> bool {
        do_expr(self) || return false;
        match self.node {
            Expression::Call { ref args, .. } => {
                for arg in args.iter() {
                    arg.visit_expr(do_expr) || return false;
                }
                true
            }
            Expression::Unary { ref expr, .. } => expr.visit_expr(do_expr),
            Expression::Parenthesis { ref expr } => expr.visit_expr(do_expr),
            Expression::Binary { ref left, ref right, .. } => {
                left.visit_expr(do_expr) || return false;
                right.visit_expr(do_expr)
            }
            _ => true,
        }
    }
}

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

    #[test]
    fn literals() {
        assert_eq!(Type::Bool, Literal::Bool(false).get_type());
        assert_eq!(Type::Int, Literal::Int(0).get_type());
        assert_eq!(Type::Float, Literal::Float(0.0).get_type());
    }
}
<commit_msg>Front: Add visitor pattern for AST<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;

use super::Position;
use super::symbols::SymbolTable;

pub type Functions = HashMap<String, Node<Function>>;

#[derive(PartialEq, Debug)]
pub struct Node<I> {
    pub pos: Position,
    pub node: I,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Type {
    Void,
    Bool,
    Int,
    Float,
    Str,
}

#[derive(PartialEq, Debug)]
pub enum Literal {
    Bool(bool),
    Int(i32),
    Float(f32),
    Str(String),
}

impl Literal {
    pub fn get_type(&self) -> Type {
        match *self {
            Literal::Bool(_) => Type::Bool,
            Literal::Int(_) => Type::Int,
            Literal::Float(_) => Type::Float,
            Literal::Str(_) => Type::Str,
        }
    }
}

#[derive(Debug)]
pub struct Variable {
    pub id: u32,
    pub type_: Type,
    pub name: String,
}

impl Variable {
    pub fn stub(name: String) -> Variable {
        Variable {
            id: 0,
            type_: Type::Void,
            name: name,
        }
    }

    pub fn eq_name_type(&self, other: &Variable) -> bool {
        self.type_ == other.type_ && self.name == other.name
    }
}

impl PartialEq for Variable {
    fn eq(&self, other: &Variable) -> bool {
        if self.id == 0 || other.id == 0 {
            false
        } else {
            self.id == other.id
        }
    }
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum UnaryOp {
    NOT,
    MINUS,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum BinaryOp {
    ADD,
    SUB,
    MUL,
    DIV,

    EQ,
    LT,
    LE,
}

#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Op {
    UnaryOp(UnaryOp),
    BinaryOp(BinaryOp),
}

#[derive(PartialEq, Debug)]
pub struct Program {
    pub functions: Functions,
}

#[derive(PartialEq, Debug)]
pub struct Function {
    pub name: String,
    pub filename: String,
    pub body: Node<Statement>,
    pub args: Vec<Rc<Variable>>,
    pub ret_type: Type,
    pub symbols: Rc<RefCell<SymbolTable>>,
}

#[derive(PartialEq, Debug)]
pub enum Statement {
    Expression {
        expr: Box<Node<Expression>>,
    },
    Declaration {
        var: Rc<Variable>,
    },
    Assignment {
        var: Rc<Variable>,
        expr: Box<Node<Expression>>,
    },
    If {
        cond: Box<Node<Expression>>,
        on_true: Box<Node<Statement>>,
        on_false: Option<Box<Node<Statement>>>,
    },
    While {
        cond: Box<Node<Expression>>,
        body: Box<Node<Statement>>,
    },
    Return {
        expr: Option<Box<Node<Expression>>>,
    },
    Compound {
        stmts: Vec<Node<Statement>>,
        symbols: Rc<RefCell<SymbolTable>>,
    },
}

impl Node<Statement> {
    /// Visit all statements with a given closure.
    ///
    /// The given closure is called for each statement with a reference to the
    /// given node. This reference inherits the lifetime of `self`. The return
    /// value indicates whether further statements should be visited or not.
    ///
    /// Use this method as alternative to the [Visitor].
    ///
    /// [Visitor]: <trait.Visitor.html>
    pub fn visit_stmt<'a>(&'a self, do_stmt: &mut FnMut(&'a Node<Statement>) -> bool) -> bool {
        do_stmt(self) || return false;
        match self.node {
            Statement::If { ref on_true, ref on_false, .. } => {
                on_true.visit_stmt(do_stmt) ||
                if let Some(ref stmt) = *on_false {
                    stmt.visit_stmt(do_stmt)
                } else {
                    true
                }
            }
            Statement::While { ref body, .. } => body.visit_stmt(do_stmt),
            Statement::Compound { ref stmts, .. } => {
                for stmt in stmts.iter() {
                    stmt.visit_stmt(do_stmt) || return false;
                }
                true
            }
            _ => true,
        }
    }

    /// Visit all expressions with a given closure.
    ///
    /// Same as [visit_stmt], but for expressions.
    ///
    /// [visit_stmt]: <struct.Node.html#method.visit_expr>
    pub fn visit_expr<'a>(&'a self, do_expr: &mut FnMut(&'a Node<Expression>) -> bool) -> bool {
        self.visit_stmt(&mut |stmt| {
            match stmt.node {
                Statement::Expression { ref expr } => do_expr(expr),
                Statement::Assignment { ref expr, .. } => do_expr(expr),
                Statement::If { ref cond, .. } => do_expr(cond),
                Statement::While { ref cond, .. } => do_expr(cond),
                Statement::Return { expr: Some(ref expr) } => do_expr(expr),
                _ => true,
            }
        })
    }
}

#[derive(PartialEq, Debug)]
pub enum Expression {
    Literal {
        lit: Literal,
    },
    Variable {
        var: Rc<Variable>,
    },
    Call {
        function: String,
        args: Vec<Node<Expression>>,
    },
    Unary {
        op: UnaryOp,
        expr: Box<Node<Expression>>,
    },
    Binary {
        op: BinaryOp,
        left: Box<Node<Expression>>,
        right: Box<Node<Expression>>,
    },
    Parenthesis {
        expr: Box<Node<Expression>>,
    },
}

impl Node<Expression> {
    /// Visit all expressions with a given closure.
    ///
    /// Same as [visit_stmt], but for expressions.
    ///
    /// [visit_stmt]: <struct.Node.html#method.visit_expr>
    pub fn visit_expr<'a>(&'a self, do_expr: &mut FnMut(&'a Node<Expression>) -> bool) -> bool {
        do_expr(self) || return false;
        match self.node {
            Expression::Call { ref args, .. } => {
                for arg in args.iter() {
                    arg.visit_expr(do_expr) || return false;
                }
                true
            }
            Expression::Unary { ref expr, .. } => expr.visit_expr(do_expr),
            Expression::Parenthesis { ref expr } => expr.visit_expr(do_expr),
            Expression::Binary { ref left, ref right, .. } => {
                left.visit_expr(do_expr) || return false;
                right.visit_expr(do_expr)
            }
            _ => true,
        }
    }
}

/// Enables visiting specific nodes in the AST.
///
/// Source: <https://github.com/darwins-challenge/moonlander-ast-rust>
pub trait Visitor<'a> {
    /// Continue visiting nodes?
    fn cont(&self) -> bool {
        true
    }

    /// Handler for Statements
    fn visit_stmt(&mut self, &'a Node<Statement>) {}

    /// Handler for Expressions
    fn visit_expr(&mut self, &'a Node<Expression>) {}
}

/// Enables something to be visited by a [Visitor], intended for AST nodes.
///
/// [Visitor]: <trait.Visitor.html>
pub trait Visitable<'a> {
    fn visit(&'a self, visitor: &mut Visitor<'a>);
}

impl<'a> Visitable<'a> for Node<Function> {
    fn visit(&'a self, visitor: &mut Visitor<'a>) {
        self.node.body.visit(visitor);
    }
}

impl<'a> Visitable<'a> for Node<Statement> {
    fn visit(&'a self, visitor: &mut Visitor<'a>) {
        if !visitor.cont() {
            return;
        }

        visitor.visit_stmt(self);

        match self.node {
            Statement::Expression { ref expr } => expr.visit(visitor),
            Statement::Assignment { ref expr, .. } => expr.visit(visitor),
            Statement::If { ref cond, ref on_true, ref on_false } => {
                cond.visit(visitor);
                on_true.visit(visitor);
                if let Some(ref stmt) = *on_false {
                    stmt.visit(visitor);
                }
            }
            Statement::While { ref cond, ref body } => {
                cond.visit(visitor);
                body.visit(visitor);
            }
            Statement::Return { expr: Some(ref expr) } => expr.visit(visitor),
            Statement::Compound { ref stmts, .. } => {
                for stmt in stmts {
                    stmt.visit(visitor);
                }
            }
            _ => (),
        }
    }
}

impl<'a> Visitable<'a> for Node<Expression> {
    fn visit(&'a self, visitor: &mut Visitor<'a>) {
        if !visitor.cont() {
            return;
        }

        visitor.visit_expr(self);

        match self.node {
            Expression::Call { ref args, .. } => {
                for arg in args {
                    arg.visit(visitor);
                }
            }
            Expression::Unary { ref expr, .. } => expr.visit(visitor),
            Expression::Binary { ref left, ref right, .. } => {
                left.visit(visitor);
                right.visit(visitor);
            }
            Expression::Parenthesis { ref expr } => expr.visit(visitor),
            _ => (),
        }
    }
}

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

    #[test]
    fn literals() {
        assert_eq!(Type::Bool, Literal::Bool(false).get_type());
        assert_eq!(Type::Int, Literal::Int(0).get_type());
        assert_eq!(Type::Float, Literal::Float(0.0).get_type());
    }
}
<|endoftext|>