<commit_before>#![feature(io)]

extern crate anymap;

use std::old_io::net::ip::IpAddr;
use anymap::AnyMap;

#[derive(Debug)]
enum HostAddress {
    DomainName(String),
    Ip(IpAddr),
}

#[derive(Debug)]
struct Port(u32);

#[derive(Debug)]
struct ConnectionLimit(u32);

fn main() {
    println!("24 days of Rust - anymap (day 9)");
    let mut config = AnyMap::new();
    config.insert(HostAddress::DomainName("siciarz.net".to_string()));
    config.insert(Port(666));
    config.insert(ConnectionLimit(32));
    println!("{:?}", config.get::<HostAddress>());
    println!("{:?}", config.get::<Port>());
    assert!(config.get::<String>().is_none());
    assert!(config.get::<u32>().is_none());
    config.insert(HostAddress::Ip(IpAddr::Ipv4Addr(127, 0, 0, 1)));
    println!("{:?}", config.get::<HostAddress>());
    if config.contains::<Option<f32>>() {
        println!("There's no optional float in the configuration...");
    }
    let dummy: Option<f32> = None;
    config.insert(dummy);
    if config.contains::<Option<f32>>() {
        println!("There's an optional 32-bit float in the configuration...");
    }
    if !config.contains::<Option<f64>>() {
        println!("...but not an optional 64-bit float.");
    }
}
<commit_msg>Use new std::net module in day 9.<commit_after>#![feature(net)]

extern crate anymap;

use std::net::IpAddr;
use anymap::AnyMap;

#[derive(Debug)]
enum HostAddress {
    DomainName(String),
    Ip(IpAddr),
}

#[derive(Debug)]
struct Port(u32);

#[derive(Debug)]
struct ConnectionLimit(u32);

fn main() {
    println!("24 days of Rust - anymap (day 9)");
    let mut config = AnyMap::new();
    config.insert(HostAddress::DomainName("siciarz.net".to_string()));
    config.insert(Port(666));
    config.insert(ConnectionLimit(32));
    println!("{:?}", config.get::<HostAddress>());
    println!("{:?}", config.get::<Port>());
    assert!(config.get::<String>().is_none());
    assert!(config.get::<u32>().is_none());
    config.insert(HostAddress::Ip(IpAddr::new_v4(127, 0, 0, 1)));
    println!("{:?}", config.get::<HostAddress>());
    if config.contains::<Option<f32>>() {
        println!("There's no optional float in the configuration...");
    }
    let dummy: Option<f32> = None;
    config.insert(dummy);
    if config.contains::<Option<f32>>() {
        println!("There's an optional 32-bit float in the configuration...");
    }
    if !config.contains::<Option<f64>>() {
        println!("...but not an optional 64-bit float.");
    }
}
<|endoftext|>


<commit_before>use parser::{parse};

#[derive(Clone, Debug, PartialEq)]
pub enum UnOp {
  Not,
  Neg,
}

#[derive(Clone, Debug, PartialEq)]
pub enum BinOp {
  Plus,
  Minus,
  Times,
  Div,
  Eq,
  Ne,
  Leq,
  Geq,
  Lt,
  Gt,
  And,
  Or,
  Mod,
  Seq,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Expr {
  Int(isize),
  Bool(bool),
  Var(String),
  BinOp(BinOp, Box<Expr>, Box<Expr>),
  UnOp(UnOp, Box<Expr>),
  Ternary(Box<Expr>, Box<Expr>, Box<Expr>),
  Let(Box<Expr>, Box<Expr>, Box<Expr>),
  Func(Option<Box<Expr>>, Box<Expr>, Vec<Expr>),
  FnCall(Box<Expr>, Vec<Expr>),
}

fn is_int(e: &Expr) -> bool {
  match *e {
    Expr::Int(_) => true,
    _ => false,
  }
}

fn is_bool(e: &Expr) -> bool {
  match *e {
    Expr::Bool(_) => true,
    _ => false,
  }
}

fn is_func(e: &Expr) -> bool {
  match *e {
    Expr::Func(_, _, _) => true,
    _ => false,
  }
}

fn is_value(e: &Expr) -> bool {
  match *e {
    Expr::Int(_) | Expr::Bool(_) | Expr::Var(_) | Expr::Func(_, _, _) => true,
    _ => false,
  }
}

fn to_int(e: &Expr) -> isize {
  match *e {
    Expr::Int(n) => n,
    _ => {
      debug!("cant turn into int: {:?}", e);
      panic!()
    }
  }
}

fn to_bool(e: &Expr) -> bool {
  match *e {
    Expr::Bool(b) => b,
    _ => {
      debug!("cant turn into bool: {:?}", e);
      panic!()
    }
  }
}

fn subst(e: Expr, x: Expr, v: Expr) -> Expr {
  let sub = |e1: Expr| subst(e1.clone(), x.clone(), v.clone());

  match (e.clone(), x.clone()) {
    (Expr::Var(ref s1), Expr::Var(ref s2)) if s1 == s2 => v.clone(),
    (Expr::FnCall(v1, xs), _) => {
      let xs2 = xs.iter().map(|xn| sub(xn.clone())).collect();

      if *v1 == x {
        Expr::FnCall(Box::new(v.clone()), xs2)
      } else {
        Expr::FnCall(v1, xs2)
      }
    },
    (Expr::Var(_), _) => e,
    (Expr::Int(_), _) => e,
    (Expr::Bool(_), _) => e,
    (Expr::BinOp(op, e1, e2), _) => {
      Expr::BinOp(
        op,
        Box::new(sub(*e1)),
        Box::new(sub(*e2))
      )
    },
    (Expr::UnOp(op, e1), _) => Expr::UnOp(op, Box::new(sub(*e1))),
    (Expr::Ternary(e1, e2, e3), _) => {
      Expr::Ternary(
        Box::new(sub(*e1)),
        Box::new(sub(*e2)),
        Box::new(sub(*e3))
      )
    },
    (Expr::Let(e1, e2, e3), _) => {
      let e3s = if *e1 == x {
        *e3
      } else {
        sub(*e3)
      };

      Expr::Let(
        Box::new(*e1),
        Box::new(sub(*e2)),
        Box::new(e3s)
      )
    },
    (Expr::Func(name, e1, xs), _) => {
      let xs2 = xs.iter().map(|xn| sub(xn.clone())).collect();
      Expr::Func(name, Box::new(sub(*e1)), xs2)
    },
  }
}

pub fn step(e: Expr) -> Expr {
  debug!("step(e) : {:?}", e);
  match e {
    // TODO 'use Expr::*;
    //
    /**
     * Values are ineligible for step
     */
    Expr::Int(_) | Expr::Bool(_) | Expr::Func(_, _, _) | Expr::Var(_) => {
      debug!("stepping on a value {:?}", e);
      panic!("stepping on a value");
    }
    /**
     * Base cases
     */
    Expr::UnOp(UnOp::Not, ref e1) if is_bool(e1) => {
      Expr::Bool(!to_bool(&*e1))
    },
    Expr::UnOp(UnOp::Neg, ref e1) if is_int(e1) => {
      Expr::Int(-1 * to_int(&*e1))
    },
    Expr::BinOp(BinOp::And, ref e1, ref e2) if is_bool(e1) && is_bool(e2) => {
      Expr::Bool(to_bool(&*e1) && to_bool(&*e2))
    },
    Expr::BinOp(BinOp::Or, ref e1, ref e2) if is_bool(e1) && is_bool(e2) => {
      Expr::Bool(to_bool(&*e1) || to_bool(&*e2))
    },
    Expr::BinOp(BinOp::Eq, ref e1, ref e2) if is_value(e1) && is_value(e2) => {
      Expr::Bool(*e1 == *e2)
    },
    Expr::BinOp(BinOp::Ne, ref e1, ref e2) if is_value(e1) && is_value(e2) => {
      Expr::Bool(*e1 != *e2)
    },
    Expr::BinOp(BinOp::Mod, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      let n1 = to_int(&*e1);
      let n2 = to_int(&*e2);

      // rust % gives the remainder, not modulus
      let result = ((n1 % n2) + n2) % n2;

      Expr::Int(result)
    },
    Expr::BinOp(BinOp::Lt, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Bool(to_int(&*e1) < to_int(&*e2))
    },
    Expr::BinOp(BinOp::Gt, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Bool(to_int(&*e1) > to_int(&*e2))
    },
    Expr::BinOp(BinOp::Leq, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Bool(to_int(&*e1) <= to_int(&*e2))
    },
    Expr::BinOp(BinOp::Geq, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Bool(to_int(&*e1) >= to_int(&*e2))
    },
    Expr::BinOp(BinOp::Plus, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Int(to_int(&*e1) + to_int(&*e2))
    },
    Expr::BinOp(BinOp::Minus, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Int(to_int(&*e1) - to_int(&*e2))
    },
    Expr::BinOp(BinOp::Times, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Int(to_int(&*e1) * to_int(&*e2))
    },
    Expr::BinOp(BinOp::Div, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Int(to_int(&*e1) / to_int(&*e2))
    },
    Expr::BinOp(BinOp::Seq, ref e1, ref e2) if is_value(e1) => {
      *e2.clone()
    },
    Expr::Ternary(ref e1, ref e2, ref e3) if is_value(e1) => {
      match to_bool(&*e1) {
        true => *e2.clone(),
        false => *e3.clone(),
      }
    },
    Expr::Let(ref x, ref e1, ref e2) if is_value(e1) => {
      subst(*e2.clone(), *x.clone(), *e1.clone())
    },
    Expr::FnCall(ref v1, ref es) if is_func(v1) => {
      match **v1 {
        Expr::Func(ref name, ref e1, ref xs) => {
          // sub the params
          let exp = xs.iter().zip(es.iter())
            .fold(*e1.clone(), |exp, (xn, en)| subst(exp, xn.clone(), en.clone()));

          // sub the fn body for named functions
          match *name {
            None => exp,
            Some(ref s) => subst(exp, *s.clone(), *v1.clone())
          }
        },
        _ => {
          debug!("expected a Func, got {:?}", v1);
          panic!()
        },
      }
    },
    /**
     * Search Cases
     */
    Expr::BinOp(ref op, ref v1, ref e2) if is_value(v1) => {
      Expr::BinOp(op.clone(), Box::new(*v1.clone()), Box::new(step(*e2.clone())))
    },
    Expr::BinOp(op, e1, e2) => {
      Expr::BinOp(op, Box::new(step(*e1)), e2)
    },
    Expr::UnOp(op, e1) => {
      Expr::UnOp(op, Box::new(step(*e1)))
    },
    Expr::Ternary(e1, e2, e3) => {
      Expr::Ternary(Box::new(step(*e1)), e2, e3)
    },
    Expr::Let(ref e1, ref e2, ref e3) if is_value(e1) => {
      Expr::Let(Box::new(*e1.clone()), Box::new(step(*e2.clone())), Box::new(*e3.clone()))
    },
    Expr::Let(e1, e2, e3) => {
      Expr::Let(Box::new(step(*e1)), e2, e3)
    },
    Expr::FnCall(e1, mut xs) => {
      let mut found_first = true;

      for x in xs.iter_mut() {
        if is_value(x) && found_first == true {
          found_first = false;
          *x = step(x.clone());
        }
      }

      Expr::FnCall(e1, xs)
    }
  }
}

pub fn boxx(input: &str) -> Expr {
  let mut exp = parse(input);

  loop {
    if is_value(&exp) {
      return exp
    } else {
      exp = step(exp);
    }
  }
}
<commit_msg>remove some deref craziness<commit_after>use parser::{parse};

#[derive(Clone, Debug, PartialEq)]
pub enum UnOp {
  Not,
  Neg,
}

#[derive(Clone, Debug, PartialEq)]
pub enum BinOp {
  Plus,
  Minus,
  Times,
  Div,
  Eq,
  Ne,
  Leq,
  Geq,
  Lt,
  Gt,
  And,
  Or,
  Mod,
  Seq,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Expr {
  Int(isize),
  Bool(bool),
  Var(String),
  BinOp(BinOp, Box<Expr>, Box<Expr>),
  UnOp(UnOp, Box<Expr>),
  Ternary(Box<Expr>, Box<Expr>, Box<Expr>),
  Let(Box<Expr>, Box<Expr>, Box<Expr>),
  Func(Option<Box<Expr>>, Box<Expr>, Vec<Expr>),
  FnCall(Box<Expr>, Vec<Expr>),
}

fn is_int(e: &Expr) -> bool {
  match *e {
    Expr::Int(_) => true,
    _ => false,
  }
}

fn is_bool(e: &Expr) -> bool {
  match *e {
    Expr::Bool(_) => true,
    _ => false,
  }
}

fn is_func(e: &Expr) -> bool {
  match *e {
    Expr::Func(_, _, _) => true,
    _ => false,
  }
}

fn is_value(e: &Expr) -> bool {
  match *e {
    Expr::Int(_) | Expr::Bool(_) | Expr::Var(_) | Expr::Func(_, _, _) => true,
    _ => false,
  }
}

fn to_int(e: &Expr) -> isize {
  match *e {
    Expr::Int(n) => n,
    _ => {
      debug!("cant turn into int: {:?}", e);
      panic!()
    }
  }
}

fn to_bool(e: &Expr) -> bool {
  match *e {
    Expr::Bool(b) => b,
    _ => {
      debug!("cant turn into bool: {:?}", e);
      panic!()
    }
  }
}

fn subst(e: Expr, x: Expr, v: Expr) -> Expr {
  let sub = |e1: Expr| subst(e1.clone(), x.clone(), v.clone());

  match (e.clone(), x.clone()) {
    (Expr::Var(ref s1), Expr::Var(ref s2)) if s1 == s2 => v.clone(),
    (Expr::FnCall(v1, xs), _) => {
      let xs2 = xs.iter().map(|xn| sub(xn.clone())).collect();

      if *v1 == x {
        Expr::FnCall(Box::new(v.clone()), xs2)
      } else {
        Expr::FnCall(v1, xs2)
      }
    },
    (Expr::Var(_), _) => e,
    (Expr::Int(_), _) => e,
    (Expr::Bool(_), _) => e,
    (Expr::BinOp(op, e1, e2), _) => {
      Expr::BinOp(
        op,
        Box::new(sub(*e1)),
        Box::new(sub(*e2))
      )
    },
    (Expr::UnOp(op, e1), _) => Expr::UnOp(op, Box::new(sub(*e1))),
    (Expr::Ternary(e1, e2, e3), _) => {
      Expr::Ternary(
        Box::new(sub(*e1)),
        Box::new(sub(*e2)),
        Box::new(sub(*e3))
      )
    },
    (Expr::Let(e1, e2, e3), _) => {
      let e3s = if *e1 == x {
        *e3
      } else {
        sub(*e3)
      };

      Expr::Let(
        Box::new(*e1),
        Box::new(sub(*e2)),
        Box::new(e3s)
      )
    },
    (Expr::Func(name, e1, xs), _) => {
      let xs2 = xs.iter().map(|xn| sub(xn.clone())).collect();
      Expr::Func(name, Box::new(sub(*e1)), xs2)
    },
  }
}

pub fn step(e: Expr) -> Expr {
  debug!("step(e) : {:?}", e);
  match e {
    // TODO 'use Expr::*;
    /**
     * Values are ineligible for step
     */
    Expr::Int(_) | Expr::Bool(_) | Expr::Func(_, _, _) | Expr::Var(_) => {
      debug!("stepping on a value {:?}", e);
      panic!("stepping on a value");
    }
    /**
     * Base cases
     */
    Expr::UnOp(UnOp::Not, ref e1) if is_bool(e1) => {
      Expr::Bool(!to_bool(e1))
    },
    Expr::UnOp(UnOp::Neg, ref e1) if is_int(e1) => {
      Expr::Int(-1 * to_int(e1))
    },
    Expr::BinOp(BinOp::And, ref e1, ref e2) if is_bool(e1) && is_bool(e2) => {
      Expr::Bool(to_bool(e1) && to_bool(e2))
    },
    Expr::BinOp(BinOp::Or, ref e1, ref e2) if is_bool(e1) && is_bool(e2) => {
      Expr::Bool(to_bool(e1) || to_bool(e2))
    },
    Expr::BinOp(BinOp::Eq, ref e1, ref e2) if is_value(e1) && is_value(e2) => {
      Expr::Bool(*e1 == *e2)
    },
    Expr::BinOp(BinOp::Ne, ref e1, ref e2) if is_value(e1) && is_value(e2) => {
      Expr::Bool(*e1 != *e2)
    },
    Expr::BinOp(BinOp::Mod, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      let n1 = to_int(e1);
      let n2 = to_int(e2);

      // rust % gives the remainder, not modulus
      let result = ((n1 % n2) + n2) % n2;

      Expr::Int(result)
    },
    Expr::BinOp(BinOp::Lt, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Bool(to_int(e1) < to_int(e2))
    },
    Expr::BinOp(BinOp::Gt, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Bool(to_int(e1) > to_int(e2))
    },
    Expr::BinOp(BinOp::Leq, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Bool(to_int(e1) <= to_int(e2))
    },
    Expr::BinOp(BinOp::Geq, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Bool(to_int(e1) >= to_int(e2))
    },
    Expr::BinOp(BinOp::Plus, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Int(to_int(e1) + to_int(e2))
    },
    Expr::BinOp(BinOp::Minus, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Int(to_int(e1) - to_int(e2))
    },
    Expr::BinOp(BinOp::Times, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Int(to_int(e1) * to_int(e2))
    },
    Expr::BinOp(BinOp::Div, ref e1, ref e2) if is_int(e1) && is_int(e2) => {
      Expr::Int(to_int(e1) / to_int(e2))
    },
    Expr::BinOp(BinOp::Seq, ref e1, ref e2) if is_value(e1) => {
      *e2.clone()
    },
    Expr::Ternary(ref e1, ref e2, ref e3) if is_value(e1) => {
      match to_bool(e1) {
        true => *e2.clone(),
        false => *e3.clone(),
      }
    },
    Expr::Let(ref x, ref e1, ref e2) if is_value(e1) => {
      subst(*e2.clone(), *x.clone(), *e1.clone())
    },
    Expr::FnCall(ref v1, ref es) if is_func(v1) => {
      match **v1 {
        Expr::Func(ref name, ref e1, ref xs) => {
          // sub the params
          let exp = xs.iter().zip(es.iter())
            .fold(*e1.clone(), |exp, (xn, en)| subst(exp, xn.clone(), en.clone()));

          // sub the fn body for named functions
          match *name {
            None => exp,
            Some(ref s) => subst(exp, *s.clone(), *v1.clone())
          }
        },
        _ => {
          debug!("expected a Func, got {:?}", v1);
          panic!()
        },
      }
    },
    /**
     * Search Cases
     */
    Expr::BinOp(ref op, ref v1, ref e2) if is_value(v1) => {
      Expr::BinOp(op.clone(), Box::new(*v1.clone()), Box::new(step(*e2.clone())))
    },
    Expr::BinOp(op, e1, e2) => {
      Expr::BinOp(op, Box::new(step(*e1)), e2)
    },
    Expr::UnOp(op, e1) => {
      Expr::UnOp(op, Box::new(step(*e1)))
    },
    Expr::Ternary(e1, e2, e3) => {
      Expr::Ternary(Box::new(step(*e1)), e2, e3)
    },
    Expr::Let(ref e1, ref e2, ref e3) if is_value(e1) => {
      Expr::Let(Box::new(*e1.clone()), Box::new(step(*e2.clone())), Box::new(*e3.clone()))
    },
    Expr::Let(e1, e2, e3) => {
      Expr::Let(Box::new(step(*e1)), e2, e3)
    },
    Expr::FnCall(e1, mut xs) => {
      let mut found_first = true;

      for x in xs.iter_mut() {
        if is_value(x) && found_first == true {
          found_first = false;
          *x = step(x.clone());
        }
      }

      Expr::FnCall(e1, xs)
    }
  }
}

pub fn boxx(input: &str) -> Expr {
  let mut exp = parse(input);

  loop {
    if is_value(&exp) {
      return exp
    } else {
      exp = step(exp);
    }
  }
}
<|endoftext|>


<commit_before><commit_msg>Test statements pretty printing<commit_after><|endoftext|>


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

use crate::platform::{self, FileExt};
use bytes::Buf;
use futures_core::Stream;
use futures_util::stream;
use http::header::{HeaderMap, HeaderValue};
use std::error::Error as StdError;
use std::io;
use std::ops::Range;
use std::sync::Arc;
use std::time::{self, SystemTime};

use crate::Entity;

// This stream breaks apart the file into chunks of at most CHUNK_SIZE. This size is
// a tradeoff between memory usage and thread handoffs.
static CHUNK_SIZE: u64 = 65_536;

/// A HTTP entity created from a `std::fs::File` which reads the file chunk-by-chunk within
/// a `tokio::task::block_in_place` closure.
///
/// Expects to be used from a tokio threadpool.
#[derive(Clone)]
pub struct ChunkedReadFile<
    D: 'static + Send + Buf + From<Vec<u8>> + From<&'static [u8]>,
    E: 'static + Send + Into<Box<dyn StdError + Send + Sync>> + From<Box<dyn StdError + Send + Sync>>,
> {
    inner: Arc<ChunkedReadFileInner>,
    phantom: std::marker::PhantomData<(D, E)>,
}

struct ChunkedReadFileInner {
    len: u64,
    inode: u64,
    mtime: SystemTime,
    f: std::fs::File,
    headers: HeaderMap,
}

impl<D, E> ChunkedReadFile<D, E>
where
    D: 'static + Send + Sync + Buf + From<Vec<u8>> + From<&'static [u8]>,
    E: 'static
        + Send
        + Sync
        + Into<Box<dyn StdError + Send + Sync>>
        + From<Box<dyn StdError + Send + Sync>>,
{
    /// Creates a new ChunkedReadFile.
    ///
    /// `read(2)` calls will be wrapped in `tokio::task::block_in_place` calls so that they don't
    /// block the tokio reactor thread on local disk I/O. Note that `File::open` and this
    /// constructor (specifically, its call to `fstat(2)`) may also block, so they typically
    /// should be wrapped in `tokio::task::block_in_place` as well.
    pub fn new(file: std::fs::File, headers: HeaderMap) -> Result<Self, io::Error> {
        let m = file.metadata()?;
        ChunkedReadFile::new_with_metadata(file, &m, headers)
    }

    /// Creates a new ChunkedReadFile, with presupplied metadata.
    ///
    /// This is an optimization for the case where the caller has already called `fstat(2)`.
    /// Note that on Windows, this still may perform a blocking file operation, so it should
    /// still be wrapped in `tokio::task::block_in_place`.
    pub fn new_with_metadata(
        file: ::std::fs::File,
        metadata: &::std::fs::Metadata,
        headers: HeaderMap,
    ) -> Result<Self, io::Error> {
        // `file` might represent a directory. If so, it's better to realize that now (while
        // we can still send a proper HTTP error) rather than during `get_range` (when all we can
        // do is drop the HTTP connection).
        if !metadata.is_file() {
            return Err(io::Error::new(io::ErrorKind::Other, "expected a file"));
        }

        let info = platform::file_info(&file)?;

        Ok(ChunkedReadFile {
            inner: Arc::new(ChunkedReadFileInner {
                len: info.len,
                inode: info.inode,
                mtime: info.mtime,
                headers,
                f: file,
            }),
            phantom: std::marker::PhantomData,
        })
    }
}

impl<D, E> Entity for ChunkedReadFile<D, E>
where
    D: 'static + Send + Sync + Buf + From<Vec<u8>> + From<&'static [u8]>,
    E: 'static
        + Send
        + Sync
        + Into<Box<dyn StdError + Send + Sync>>
        + From<Box<dyn StdError + Send + Sync>>,
{
    type Data = D;
    type Error = E;

    fn len(&self) -> u64 {
        self.inner.len
    }

    fn get_range(
        &self,
        range: Range<u64>,
    ) -> Box<dyn Stream<Item = Result<Self::Data, Self::Error>> + Send + Sync> {
        let stream = stream::unfold(
            (range, Arc::clone(&self.inner)),
            move |(left, inner)| async {
                if left.start == left.end {
                    return None;
                }
                let chunk_size = std::cmp::min(CHUNK_SIZE, left.end - left.start) as usize;
                Some(tokio::task::block_in_place(move || {
                    // Read directly into an uninitialized buffer. By a strict reading of the
                    // Vec::set_len docs, this is unsound (the buffer must be initialized first),
                    // but tokio::io::BufReader does something similar (at least these two calls in
                    // a row), so I'll assume for now it doesn't cause problems in practice.
                    // It looks like there's work to avoid this problem here:
                    // https://github.com/rust-lang/rust/issues/42788
                    let mut chunk = Vec::with_capacity(chunk_size);
                    unsafe { chunk.set_len(chunk_size) };
                    let bytes_read = match inner.f.read_at(&mut chunk, left.start) {
                        Err(e) => {
                            return (
                                Err(Box::<dyn StdError + Send + Sync + 'static>::from(e).into()),
                                (left, inner),
                            )
                        }
                        Ok(b) => b,
                    };
                    chunk.truncate(bytes_read);
                    (
                        Ok(chunk.into()),
                        (left.start + bytes_read as u64..left.end, inner),
                    )
                }))
            },
        );
        let _: &dyn Stream<Item = Result<Self::Data, Self::Error>> = &stream;
        Box::new(stream)
    }

    fn add_headers(&self, h: &mut HeaderMap) {
        h.extend(
            self.inner
                .headers
                .iter()
                .map(|(k, v)| (k.clone(), v.clone())),
        );
    }

    fn etag(&self) -> Option<HeaderValue> {
        // This etag format is similar to Apache's. The etag should change if the file is modified
        // or replaced. The length is probably redundant but doesn't harm anything.
        let dur = self
            .inner
            .mtime
            .duration_since(time::UNIX_EPOCH)
            .expect("modification time must be after epoch");

        // Rust doesn't seem to understand these lengths are used in the macro invocation.
        #[allow(dead_code)]
        static HEX_U64_LEN: usize = 16;
        #[allow(dead_code)]
        static HEX_U32_LEN: usize = 16;
        Some(unsafe_fmt_ascii_val!(
            HEX_U64_LEN * 3 + HEX_U64_LEN + 5,
            "\"{:x}:{:x}:{:x}:{:x}\"",
            self.inner.inode,
            self.inner.len,
            dur.as_secs(),
            dur.subsec_nanos()
        ))
    }

    fn last_modified(&self) -> Option<SystemTime> {
        Some(self.inner.mtime)
    }
}

#[cfg(test)]
mod tests {
    use super::ChunkedReadFile;
    use super::Entity;
    use bytes::Bytes;
    use futures_core::Stream;
    use http::header::HeaderMap;
    use std::fs::File;
    use std::io::Write;

    type BoxedError = Box<dyn std::error::Error + Sync + Send>;
    type CRF = ChunkedReadFile<Bytes, BoxedError>;

    async fn to_bytes(s: Box<dyn Stream<Item = Result<Bytes, BoxedError>> + Send>) -> Bytes {
        hyper::body::to_bytes(hyper::Body::from(s)).await.unwrap()
    }

    #[tokio::test(flavor = "multi_thread")]
    async fn basic() {
        tokio::spawn(async move {
            let tmp = tempfile::tempdir().unwrap();
            let p = tmp.path().join("f");
            let mut f = File::create(&p).unwrap();
            f.write_all(b"asdf").unwrap();

            let crf = CRF::new(File::open(&p).unwrap(), HeaderMap::new()).unwrap();
            assert_eq!(4, crf.len());
            let etag1 = crf.etag();

            // Test returning part/all of the stream.
            assert_eq!(&to_bytes(crf.get_range(0..4)).await.as_ref(), b"asdf");
            assert_eq!(&to_bytes(crf.get_range(1..3)).await.as_ref(), b"sd");

            // A ChunkedReadFile constructed from a modified file should have a different etag.
            f.write_all(b"jkl;").unwrap();
            let crf = CRF::new(File::open(&p).unwrap(), HeaderMap::new()).unwrap();
            assert_eq!(8, crf.len());
            let etag2 = crf.etag();
            assert_ne!(etag1, etag2);
        })
        .await
        .unwrap();
    }
}
<commit_msg>remove mistaken #[dead_code] annotation<commit_after>// Copyright (c) 2020 The http-serve developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE.txt or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT.txt or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::platform::{self, FileExt};
use bytes::Buf;
use futures_core::Stream;
use futures_util::stream;
use http::header::{HeaderMap, HeaderValue};
use std::error::Error as StdError;
use std::io;
use std::ops::Range;
use std::sync::Arc;
use std::time::{self, SystemTime};

use crate::Entity;

// This stream breaks apart the file into chunks of at most CHUNK_SIZE. This size is
// a tradeoff between memory usage and thread handoffs.
static CHUNK_SIZE: u64 = 65_536;

/// A HTTP entity created from a `std::fs::File` which reads the file chunk-by-chunk within
/// a `tokio::task::block_in_place` closure.
///
/// Expects to be used from a tokio threadpool.
#[derive(Clone)]
pub struct ChunkedReadFile<
    D: 'static + Send + Buf + From<Vec<u8>> + From<&'static [u8]>,
    E: 'static + Send + Into<Box<dyn StdError + Send + Sync>> + From<Box<dyn StdError + Send + Sync>>,
> {
    inner: Arc<ChunkedReadFileInner>,
    phantom: std::marker::PhantomData<(D, E)>,
}

struct ChunkedReadFileInner {
    len: u64,
    inode: u64,
    mtime: SystemTime,
    f: std::fs::File,
    headers: HeaderMap,
}

impl<D, E> ChunkedReadFile<D, E>
where
    D: 'static + Send + Sync + Buf + From<Vec<u8>> + From<&'static [u8]>,
    E: 'static
        + Send
        + Sync
        + Into<Box<dyn StdError + Send + Sync>>
        + From<Box<dyn StdError + Send + Sync>>,
{
    /// Creates a new ChunkedReadFile.
    ///
    /// `read(2)` calls will be wrapped in `tokio::task::block_in_place` calls so that they don't
    /// block the tokio reactor thread on local disk I/O. Note that `File::open` and this
    /// constructor (specifically, its call to `fstat(2)`) may also block, so they typically
    /// should be wrapped in `tokio::task::block_in_place` as well.
    pub fn new(file: std::fs::File, headers: HeaderMap) -> Result<Self, io::Error> {
        let m = file.metadata()?;
        ChunkedReadFile::new_with_metadata(file, &m, headers)
    }

    /// Creates a new ChunkedReadFile, with presupplied metadata.
    ///
    /// This is an optimization for the case where the caller has already called `fstat(2)`.
    /// Note that on Windows, this still may perform a blocking file operation, so it should
    /// still be wrapped in `tokio::task::block_in_place`.
    pub fn new_with_metadata(
        file: ::std::fs::File,
        metadata: &::std::fs::Metadata,
        headers: HeaderMap,
    ) -> Result<Self, io::Error> {
        // `file` might represent a directory. If so, it's better to realize that now (while
        // we can still send a proper HTTP error) rather than during `get_range` (when all we can
        // do is drop the HTTP connection).
        if !metadata.is_file() {
            return Err(io::Error::new(io::ErrorKind::Other, "expected a file"));
        }

        let info = platform::file_info(&file)?;

        Ok(ChunkedReadFile {
            inner: Arc::new(ChunkedReadFileInner {
                len: info.len,
                inode: info.inode,
                mtime: info.mtime,
                headers,
                f: file,
            }),
            phantom: std::marker::PhantomData,
        })
    }
}

impl<D, E> Entity for ChunkedReadFile<D, E>
where
    D: 'static + Send + Sync + Buf + From<Vec<u8>> + From<&'static [u8]>,
    E: 'static
        + Send
        + Sync
        + Into<Box<dyn StdError + Send + Sync>>
        + From<Box<dyn StdError + Send + Sync>>,
{
    type Data = D;
    type Error = E;

    fn len(&self) -> u64 {
        self.inner.len
    }

    fn get_range(
        &self,
        range: Range<u64>,
    ) -> Box<dyn Stream<Item = Result<Self::Data, Self::Error>> + Send + Sync> {
        let stream = stream::unfold(
            (range, Arc::clone(&self.inner)),
            move |(left, inner)| async {
                if left.start == left.end {
                    return None;
                }
                let chunk_size = std::cmp::min(CHUNK_SIZE, left.end - left.start) as usize;
                Some(tokio::task::block_in_place(move || {
                    // Read directly into an uninitialized buffer. By a strict reading of the
                    // Vec::set_len docs, this is unsound (the buffer must be initialized first),
                    // but tokio::io::BufReader does something similar (at least these two calls in
                    // a row), so I'll assume for now it doesn't cause problems in practice.
                    // It looks like there's work to avoid this problem here:
                    // https://github.com/rust-lang/rust/issues/42788
                    let mut chunk = Vec::with_capacity(chunk_size);
                    unsafe { chunk.set_len(chunk_size) };
                    let bytes_read = match inner.f.read_at(&mut chunk, left.start) {
                        Err(e) => {
                            return (
                                Err(Box::<dyn StdError + Send + Sync + 'static>::from(e).into()),
                                (left, inner),
                            )
                        }
                        Ok(b) => b,
                    };
                    chunk.truncate(bytes_read);
                    (
                        Ok(chunk.into()),
                        (left.start + bytes_read as u64..left.end, inner),
                    )
                }))
            },
        );
        let _: &dyn Stream<Item = Result<Self::Data, Self::Error>> = &stream;
        Box::new(stream)
    }

    fn add_headers(&self, h: &mut HeaderMap) {
        h.extend(
            self.inner
                .headers
                .iter()
                .map(|(k, v)| (k.clone(), v.clone())),
        );
    }

    fn etag(&self) -> Option<HeaderValue> {
        // This etag format is similar to Apache's. The etag should change if the file is modified
        // or replaced. The length is probably redundant but doesn't harm anything.
        let dur = self
            .inner
            .mtime
            .duration_since(time::UNIX_EPOCH)
            .expect("modification time must be after epoch");

        static HEX_U64_LEN: usize = 16;
        static HEX_U32_LEN: usize = 8;
        Some(unsafe_fmt_ascii_val!(
            HEX_U64_LEN * 3 + HEX_U32_LEN + 5,
            "\"{:x}:{:x}:{:x}:{:x}\"",
            self.inner.inode,
            self.inner.len,
            dur.as_secs(),
            dur.subsec_nanos()
        ))
    }

    fn last_modified(&self) -> Option<SystemTime> {
        Some(self.inner.mtime)
    }
}

#[cfg(test)]
mod tests {
    use super::ChunkedReadFile;
    use super::Entity;
    use bytes::Bytes;
    use futures_core::Stream;
    use http::header::HeaderMap;
    use std::fs::File;
    use std::io::Write;

    type BoxedError = Box<dyn std::error::Error + Sync + Send>;
    type CRF = ChunkedReadFile<Bytes, BoxedError>;

    async fn to_bytes(s: Box<dyn Stream<Item = Result<Bytes, BoxedError>> + Send>) -> Bytes {
        hyper::body::to_bytes(hyper::Body::from(s)).await.unwrap()
    }

    #[tokio::test(flavor = "multi_thread")]
    async fn basic() {
        tokio::spawn(async move {
            let tmp = tempfile::tempdir().unwrap();
            let p = tmp.path().join("f");
            let mut f = File::create(&p).unwrap();
            f.write_all(b"asdf").unwrap();

            let crf = CRF::new(File::open(&p).unwrap(), HeaderMap::new()).unwrap();
            assert_eq!(4, crf.len());
            let etag1 = crf.etag();

            // Test returning part/all of the stream.
            assert_eq!(&to_bytes(crf.get_range(0..4)).await.as_ref(), b"asdf");
            assert_eq!(&to_bytes(crf.get_range(1..3)).await.as_ref(), b"sd");

            // A ChunkedReadFile constructed from a modified file should have a different etag.
            f.write_all(b"jkl;").unwrap();
            let crf = CRF::new(File::open(&p).unwrap(), HeaderMap::new()).unwrap();
            assert_eq!(8, crf.len());
            let etag2 = crf.etag();
            assert_ne!(etag1, etag2);
        })
        .await
        .unwrap();
    }
}
<|endoftext|>


<commit_before>//! Procedural macro implementing `#[derive(EnumMap)]`
//!
//! This is supposed to used with `enum-map` crate, which provides the
//! actual usage documentation.

#![recursion_limit = "128"]

extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
extern crate syn;

use std::iter;

use syn::{Data, DataEnum, DeriveInput, Fields, Ident, Variant};

fn generate_enum_code(name: Ident, data_enum: DataEnum) -> proc_macro2::TokenStream {
    let enum_count = data_enum.variants.len();
    let mut has_discriminants = false;

    for &Variant {
        ref fields,
        ref discriminant,
        ..
    } in &data_enum.variants
    {
        match *fields {
            Fields::Unit => (),
            _ => return quote!(compile_error!{"#[derive(EnumMap)] requires C style style enum"}),
        }

        if discriminant.is_some() {
            has_discriminants = true;
        }
    }

    let variants_names_a = data_enum.variants.iter().map(|variant| &variant.ident);
    let variants_names_b = data_enum.variants.iter().map(|variant| &variant.ident);
    let repeat_name_a = iter::repeat(&name);
    let repeat_name_b = repeat_name_a.clone();
    let counter = 0..enum_count;

    let to_usize = if enum_count == 0 || has_discriminants {
        let variants_names = data_enum.variants.iter().map(|variant| &variant.ident);
        let repeat_name = repeat_name_a.clone();
        let counter = counter.clone();

        quote! {
            match self {
                #(
                    #repeat_name::#variants_names => #counter,
                )*
            }
        }
    } else {
        quote! { self as usize }
    };

    quote! {
        impl<V> ::enum_map::Internal<V> for #name {
            type Array = [V; #enum_count];

            #[inline]
            fn slice(array: &Self::Array) -> &[V] {
                array
            }

            #[inline]
            fn slice_mut(array: &mut Self::Array) -> &mut [V] {
                array
            }

            #[inline]
            fn from_usize(value: usize) -> Self {
                match value {
                    #(
                        #counter => #repeat_name_a::#variants_names_a,
                    )*
                    _ => unreachable!()
                }
            }

            #[inline]
            fn to_usize(self) -> usize {
                #to_usize
            }

            #[inline]
            fn from_function<F: FnMut(Self) -> V>(mut _f: F) -> Self::Array {
                [#(
                    _f(#repeat_name_b::#variants_names_b),
                )*]
            }
        }
    }
}

#[proc_macro_derive(EnumMap)]
pub fn derive_enum_map(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();

    let result = match input.data {
        Data::Enum(data_enum) => generate_enum_code(input.ident, data_enum),
        _ => quote!(compile_error!{"#[derive(EnumMap)] is only defined for enums"}),
    };

    result.into()
}
<commit_msg>Mark Enum trait as automatically derived in documentation<commit_after>//! Procedural macro implementing `#[derive(EnumMap)]`
//!
//! This is supposed to used with `enum-map` crate, which provides the
//! actual usage documentation.

#![recursion_limit = "128"]

extern crate proc_macro;
extern crate proc_macro2;
#[macro_use]
extern crate quote;
extern crate syn;

use std::iter;

use syn::{Data, DataEnum, DeriveInput, Fields, Ident, Variant};

fn generate_enum_code(name: Ident, data_enum: DataEnum) -> proc_macro2::TokenStream {
    let enum_count = data_enum.variants.len();
    let mut has_discriminants = false;

    for &Variant {
        ref fields,
        ref discriminant,
        ..
    } in &data_enum.variants
    {
        match *fields {
            Fields::Unit => (),
            _ => return quote!(compile_error!{"#[derive(EnumMap)] requires C style style enum"}),
        }

        if discriminant.is_some() {
            has_discriminants = true;
        }
    }

    let variants_names_a = data_enum.variants.iter().map(|variant| &variant.ident);
    let variants_names_b = data_enum.variants.iter().map(|variant| &variant.ident);
    let repeat_name_a = iter::repeat(&name);
    let repeat_name_b = repeat_name_a.clone();
    let counter = 0..enum_count;

    let to_usize = if enum_count == 0 || has_discriminants {
        let variants_names = data_enum.variants.iter().map(|variant| &variant.ident);
        let repeat_name = repeat_name_a.clone();
        let counter = counter.clone();

        quote! {
            match self {
                #(
                    #repeat_name::#variants_names => #counter,
                )*
            }
        }
    } else {
        quote! { self as usize }
    };

    quote! {
        #[automatically_derived]
        impl<V> ::enum_map::Internal<V> for #name {
            type Array = [V; #enum_count];

            #[inline]
            fn slice(array: &Self::Array) -> &[V] {
                array
            }

            #[inline]
            fn slice_mut(array: &mut Self::Array) -> &mut [V] {
                array
            }

            #[inline]
            fn from_usize(value: usize) -> Self {
                match value {
                    #(
                        #counter => #repeat_name_a::#variants_names_a,
                    )*
                    _ => unreachable!()
                }
            }

            #[inline]
            fn to_usize(self) -> usize {
                #to_usize
            }

            #[inline]
            fn from_function<F: FnMut(Self) -> V>(mut _f: F) -> Self::Array {
                [#(
                    _f(#repeat_name_b::#variants_names_b),
                )*]
            }
        }
    }
}

#[proc_macro_derive(EnumMap)]
pub fn derive_enum_map(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();

    let result = match input.data {
        Data::Enum(data_enum) => generate_enum_code(input.ident, data_enum),
        _ => quote!(compile_error!{"#[derive(EnumMap)] is only defined for enums"}),
    };

    result.into()
}
<|endoftext|>


<commit_before>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. Chung

// 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.

//! Rc4Md5 cipher definition

use crypto::openssl::{OpenSSLCrypto, OpenSSLDigest};
use crypto::cipher::{Cipher, CipherType, CipherResult};
use crypto::digest::{Digest, DigestType};
use crypto::CryptoMode;

/// Rc4Md5 Cipher
pub struct Rc4Md5Cipher {
    crypto: OpenSSLCrypto,
}

impl Rc4Md5Cipher {
    pub fn new(key: &[u8], iv: &[u8], mode: CryptoMode) -> Rc4Md5Cipher {
        let mut md5_digest = OpenSSLDigest::new(DigestType::Md5);
        md5_digest.update(key);
        md5_digest.update(iv);
        let key = md5_digest.digest();

        Rc4Md5Cipher {
            crypto: OpenSSLCrypto::new(CipherType::Rc4, &key[..], b"", mode)
        }
    }
}

impl Cipher for Rc4Md5Cipher {
    fn update(&mut self, data: &[u8], out: &mut Vec<u8>) -> CipherResult<()> {
        self.crypto.update(data, out)
    }

    fn finalize(&mut self, out: &mut Vec<u8>) -> CipherResult<()> {
        self.crypto.finalize(out)
    }
}

unsafe impl Send for Rc4Md5Cipher {}
<commit_msg>add test for rc4 md5<commit_after>// The MIT License (MIT)

// Copyright (c) 2014 Y. T. Chung

// 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.

//! Rc4Md5 cipher definition

use crypto::openssl::{OpenSSLCrypto, OpenSSLDigest};
use crypto::cipher::{Cipher, CipherType, CipherResult};
use crypto::digest::{Digest, DigestType};
use crypto::CryptoMode;

/// Rc4Md5 Cipher
pub struct Rc4Md5Cipher {
    crypto: OpenSSLCrypto,
}

impl Rc4Md5Cipher {
    pub fn new(key: &[u8], iv: &[u8], mode: CryptoMode) -> Rc4Md5Cipher {
        let mut md5_digest = OpenSSLDigest::new(DigestType::Md5);
        md5_digest.update(key);
        md5_digest.update(iv);
        let key = md5_digest.digest();

        Rc4Md5Cipher {
            crypto: OpenSSLCrypto::new(CipherType::Rc4, &key[..], b"", mode)
        }
    }
}

impl Cipher for Rc4Md5Cipher {
    fn update(&mut self, data: &[u8], out: &mut Vec<u8>) -> CipherResult<()> {
        self.crypto.update(data, out)
    }

    fn finalize(&mut self, out: &mut Vec<u8>) -> CipherResult<()> {
        self.crypto.finalize(out)
    }
}

unsafe impl Send for Rc4Md5Cipher {}

#[cfg(test)]
mod test {
    use super::*;
    use crypto::cipher::{Cipher, CipherType};
    use crypto::CryptoMode;

    #[test]
    fn test_rc4_md5_cipher() {
        let msg = b"abcd1234";
        let key = b"key";

        let t = CipherType::Rc4Md5;
        let iv = t.gen_init_vec();

        let mut enc = Rc4Md5Cipher::new(key, &iv[..], CryptoMode::Encrypt);
        let mut encrypted_msg = Vec::new();
        enc.update(msg, &mut encrypted_msg)
           .and_then(|_| enc.finalize(&mut encrypted_msg))
           .unwrap();

        let mut dec = Rc4Md5Cipher::new(key, &iv[..], CryptoMode::Decrypt);
        let mut decrypted_msg = Vec::new();
        dec.update(&encrypted_msg[..], &mut decrypted_msg)
           .and_then(|_| dec.finalize(&mut decrypted_msg))
           .unwrap();

        assert_eq!(msg, &decrypted_msg[..]);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::net::IpAddr;
use std::path::{PathBuf, Path, Component};

use id_map::{IdMap, mapping_validator};
use ipnetwork::IpNetwork;
use quire::validate::{Sequence, Mapping, Scalar, Numeric};
use quire::validate::{Structure};
use range::Range;

#[derive(Deserialize)]
pub struct BridgedNetwork {
    pub bridge: String,
    #[serde(with="::serde_str")]
    pub network: IpNetwork,
    pub default_gateway: Option<IpAddr>,
}

#[derive(Deserialize)]
pub struct SandboxConfig {
    pub config_file: Option<PathBuf>,
    pub image_dir: PathBuf,
    pub image_dir_levels: u32,
    pub used_images_list: Option<PathBuf>,
    pub log_file: Option<PathBuf>,
    pub log_level: Option<String>,
    pub readonly_paths: BTreeMap<PathBuf, PathBuf>,
    pub writable_paths: BTreeMap<PathBuf, PathBuf>,
    pub allow_users: Vec<Range>,
    pub default_user: Option<u32>,
    pub allow_groups: Vec<Range>,
    pub default_group: Option<u32>,
    pub allow_tcp_ports: Vec<Range>,
    pub additional_hosts: BTreeMap<String, String>,
    pub uid_map: Vec<IdMap>,
    pub gid_map: Vec<IdMap>,
    pub auto_clean: bool,
    pub resolv_conf: PathBuf,
    pub hosts_file: PathBuf,
    pub bridged_network: Option<BridgedNetwork>,
}

impl SandboxConfig {
    pub fn check_path<P: AsRef<Path>>(&self, path: P) -> bool {
        let mut num = 0;
        for component in path.as_ref().components() {
            match component {
                Component::Normal(x) if x.to_str().is_some() => num += 1,
                _ => return false,
            }
        }
        return num == self.image_dir_levels;
    }
    pub fn validator<'x>() -> Structure<'x> {
        Structure::new()
        .member("config_file", Scalar::new().optional())
        .member("image_dir", Scalar::new().optional()
            .default("/var/lib/lithos/containers"))
        .member("image_dir_levels",
            Numeric::new().min(1).max(16).default(1))
        .member("used_images_list", Scalar::new().optional())
        .member("log_file", Scalar::new().optional())
        .member("log_level", Scalar::new().optional())
        .member("readonly_paths", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("writable_paths", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("allow_users", Sequence::new(Scalar::new()))
        .member("allow_groups", Sequence::new(Scalar::new()))
        .member("allow_tcp_ports", Sequence::new(Scalar::new()))
        .member("uid_map", mapping_validator())
        .member("gid_map", mapping_validator())
        .member("additional_hosts", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("auto_clean", Scalar::new().default("true").optional())
        .member("hosts_file", Scalar::new().default("/etc/hosts"))
        .member("resolv_conf", Scalar::new().default("/etc/resolv.conf"))
        .member("bridged_network", Structure::new()
            .member("bridge", Scalar::new())
            .member("network", Scalar::new())
            .member("default_gateway", Scalar::new())
            .optional())
    }
}
<commit_msg>Add `default-user` and `default-group` to config validator<commit_after>use std::collections::BTreeMap;
use std::net::IpAddr;
use std::path::{PathBuf, Path, Component};

use id_map::{IdMap, mapping_validator};
use ipnetwork::IpNetwork;
use quire::validate::{Sequence, Mapping, Scalar, Numeric};
use quire::validate::{Structure};
use range::Range;

#[derive(Deserialize)]
pub struct BridgedNetwork {
    pub bridge: String,
    #[serde(with="::serde_str")]
    pub network: IpNetwork,
    pub default_gateway: Option<IpAddr>,
}

#[derive(Deserialize)]
pub struct SandboxConfig {
    pub config_file: Option<PathBuf>,
    pub image_dir: PathBuf,
    pub image_dir_levels: u32,
    pub used_images_list: Option<PathBuf>,
    pub log_file: Option<PathBuf>,
    pub log_level: Option<String>,
    pub readonly_paths: BTreeMap<PathBuf, PathBuf>,
    pub writable_paths: BTreeMap<PathBuf, PathBuf>,
    pub allow_users: Vec<Range>,
    pub default_user: Option<u32>,
    pub allow_groups: Vec<Range>,
    pub default_group: Option<u32>,
    pub allow_tcp_ports: Vec<Range>,
    pub additional_hosts: BTreeMap<String, String>,
    pub uid_map: Vec<IdMap>,
    pub gid_map: Vec<IdMap>,
    pub auto_clean: bool,
    pub resolv_conf: PathBuf,
    pub hosts_file: PathBuf,
    pub bridged_network: Option<BridgedNetwork>,
}

impl SandboxConfig {
    pub fn check_path<P: AsRef<Path>>(&self, path: P) -> bool {
        let mut num = 0;
        for component in path.as_ref().components() {
            match component {
                Component::Normal(x) if x.to_str().is_some() => num += 1,
                _ => return false,
            }
        }
        return num == self.image_dir_levels;
    }
    pub fn validator<'x>() -> Structure<'x> {
        Structure::new()
        .member("config_file", Scalar::new().optional())
        .member("image_dir", Scalar::new().optional()
            .default("/var/lib/lithos/containers"))
        .member("image_dir_levels",
            Numeric::new().min(1).max(16).default(1))
        .member("used_images_list", Scalar::new().optional())
        .member("log_file", Scalar::new().optional())
        .member("log_level", Scalar::new().optional())
        .member("readonly_paths", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("writable_paths", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("allow_users", Sequence::new(Scalar::new()))
        .member("default_user", Scalar::new().optional())
        .member("allow_groups", Sequence::new(Scalar::new()))
        .member("default_group", Scalar::new().default(0))
        .member("allow_tcp_ports", Sequence::new(Scalar::new()))
        .member("uid_map", mapping_validator())
        .member("gid_map", mapping_validator())
        .member("additional_hosts", Mapping::new(
            Scalar::new(),
            Scalar::new()))
        .member("auto_clean", Scalar::new().default("true").optional())
        .member("hosts_file", Scalar::new().default("/etc/hosts"))
        .member("resolv_conf", Scalar::new().default("/etc/resolv.conf"))
        .member("bridged_network", Structure::new()
            .member("bridge", Scalar::new())
            .member("network", Scalar::new())
            .member("default_gateway", Scalar::new())
            .optional())
    }
}
<|endoftext|>


<commit_before>use util::{ZOPFLI_WINDOW_MASK, ZOPFLI_MIN_MATCH};

const HASH_SHIFT: i32 = 5;
const HASH_MASK: i32 = 32767;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Which {
    Hash1,
    Hash2,
}

pub struct HashThing {
    head: Vec<i32>,  /* Hash value to index of its most recent occurrence. */
    prev: Vec<u16>,  /* Index to index of prev. occurrence of same hash. */
    hashval: Vec<i32>,  /* Index to hash value at this index. */
    val: i32,  /* Current hash value. */
}

impl HashThing {
    fn new(window_size: usize) -> HashThing {
        HashThing {
            head: vec![-1; 65536],
            prev: (0..window_size as u16).collect(),
            hashval: vec![-1; window_size],
            val: 0,
        }
    }

    fn reset(&mut self, window_size: usize) {
        self.val = 0;
        self.head = vec![-1; 65536];
        self.prev = (0..window_size as u16).collect();
        self.hashval = vec![-1; window_size];
    }

    fn update(&mut self, hpos: usize) {
        self.hashval[hpos] = self.val;

        let index = self.val as usize;
        let head_index = self.head[index];
        self.prev[hpos] = if head_index != -1 && self.hashval[head_index as usize] == self.val {
            head_index as u16
        } else {
            hpos as u16
        };
        self.head[index] = hpos as i32;
    }
}

pub struct ZopfliHash {
    hash1: HashThing,
    hash2: HashThing,
    pub same: Vec<u16>,  /* Amount of repetitions of same byte after this .*/
}

impl ZopfliHash {
    pub fn new(window_size: usize) -> ZopfliHash {
        ZopfliHash {
            hash1: HashThing::new(window_size),
            hash2: HashThing::new(window_size),
            same: vec![0; window_size],
        }
    }

    pub fn reset(&mut self, window_size: usize) {
        self.hash1.reset(window_size);
        self.hash2.reset(window_size);
        self.same = vec![0; window_size];
    }

    pub fn warmup(&mut self, arr: &[u8], pos: usize, end: usize) {
        let c = arr[pos];
        self.update_val(c);

        if pos + 1 < end {
            let c = arr[pos + 1];
            self.update_val(c);
        }
    }

    /// Update the sliding hash value with the given byte. All calls to this function
    /// must be made on consecutive input characters. Since the hash value exists out
    /// of multiple input bytes, a few warmups with this function are needed initially.
    fn update_val(&mut self, c: u8) {
        self.hash1.val = ((self.hash1.val << HASH_SHIFT) ^ c as i32) & HASH_MASK;
    }

    pub fn update(&mut self, array: &[u8], pos: usize) {
        let hash_value = array.get(pos + ZOPFLI_MIN_MATCH - 1).cloned().unwrap_or(0);
        self.update_val(hash_value);

        let hpos = pos & ZOPFLI_WINDOW_MASK;

        self.hash1.update(hpos);

        // Update "same".
        let mut amount = 0;
        let same_index = pos.wrapping_sub(1) & ZOPFLI_WINDOW_MASK;
        let same = self.same[same_index];
        if same > 1 {
            amount = same as i32 - 1;
        }

        let amount_u16 = amount as u16;
        self.same[hpos] = amount_u16;

        self.hash2.val = ((amount_u16.wrapping_sub(ZOPFLI_MIN_MATCH as u16) & 255) ^ self.hash1.val as u16) as i32;

        self.hash2.update(hpos);
    }

    pub fn head_at(&self, index: usize, which: Which) -> i32 {
        match which {
            Which::Hash1 => self.hash1.head[index],
            Which::Hash2 => self.hash2.head[index],
        }
    }

    pub fn prev_at(&self, index: usize, which: Which) -> u16 {
        match which {
            Which::Hash1 => self.hash1.prev[index],
            Which::Hash2 => self.hash2.prev[index],
        }
    }

    pub fn hash_val_at(&self, index: usize, which: Which) -> i32 {
        match which {
            Which::Hash1 => self.hash1.hashval[index],
            Which::Hash2 => self.hash2.hashval[index],
        }
    }

    pub fn val(&self, which: Which) -> i32 {
        match which {
            Which::Hash1 => self.hash1.val,
            Which::Hash2 => self.hash2.val,
        }
    }
}
<commit_msg>Remove unnecessary type casts<commit_after>use util::{ZOPFLI_WINDOW_MASK, ZOPFLI_MIN_MATCH};

const HASH_SHIFT: i32 = 5;
const HASH_MASK: i32 = 32767;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Which {
    Hash1,
    Hash2,
}

pub struct HashThing {
    head: Vec<i32>,  /* Hash value to index of its most recent occurrence. */
    prev: Vec<u16>,  /* Index to index of prev. occurrence of same hash. */
    hashval: Vec<i32>,  /* Index to hash value at this index. */
    val: i32,  /* Current hash value. */
}

impl HashThing {
    fn new(window_size: usize) -> HashThing {
        HashThing {
            head: vec![-1; 65536],
            prev: (0..window_size as u16).collect(),
            hashval: vec![-1; window_size],
            val: 0,
        }
    }

    fn reset(&mut self, window_size: usize) {
        self.val = 0;
        self.head = vec![-1; 65536];
        self.prev = (0..window_size as u16).collect();
        self.hashval = vec![-1; window_size];
    }

    fn update(&mut self, hpos: usize) {
        self.hashval[hpos] = self.val;

        let index = self.val as usize;
        let head_index = self.head[index];
        self.prev[hpos] = if head_index != -1 && self.hashval[head_index as usize] == self.val {
            head_index as u16
        } else {
            hpos as u16
        };
        self.head[index] = hpos as i32;
    }
}

pub struct ZopfliHash {
    hash1: HashThing,
    hash2: HashThing,
    pub same: Vec<u16>,  /* Amount of repetitions of same byte after this .*/
}

impl ZopfliHash {
    pub fn new(window_size: usize) -> ZopfliHash {
        ZopfliHash {
            hash1: HashThing::new(window_size),
            hash2: HashThing::new(window_size),
            same: vec![0; window_size],
        }
    }

    pub fn reset(&mut self, window_size: usize) {
        self.hash1.reset(window_size);
        self.hash2.reset(window_size);
        self.same = vec![0; window_size];
    }

    pub fn warmup(&mut self, arr: &[u8], pos: usize, end: usize) {
        let c = arr[pos];
        self.update_val(c);

        if pos + 1 < end {
            let c = arr[pos + 1];
            self.update_val(c);
        }
    }

    /// Update the sliding hash value with the given byte. All calls to this function
    /// must be made on consecutive input characters. Since the hash value exists out
    /// of multiple input bytes, a few warmups with this function are needed initially.
    fn update_val(&mut self, c: u8) {
        self.hash1.val = ((self.hash1.val << HASH_SHIFT) ^ c as i32) & HASH_MASK;
    }

    pub fn update(&mut self, array: &[u8], pos: usize) {
        let hash_value = array.get(pos + ZOPFLI_MIN_MATCH - 1).cloned().unwrap_or(0);
        self.update_val(hash_value);

        let hpos = pos & ZOPFLI_WINDOW_MASK;

        self.hash1.update(hpos);

        // Update "same".
        let mut amount = 0;
        let same_index = pos.wrapping_sub(1) & ZOPFLI_WINDOW_MASK;
        let same = self.same[same_index];
        if same > 1 {
            amount = same - 1;
        }

        self.same[hpos] = amount;

        self.hash2.val = ((amount.wrapping_sub(ZOPFLI_MIN_MATCH as u16) & 255) ^ self.hash1.val as u16) as i32;

        self.hash2.update(hpos);
    }

    pub fn head_at(&self, index: usize, which: Which) -> i32 {
        match which {
            Which::Hash1 => self.hash1.head[index],
            Which::Hash2 => self.hash2.head[index],
        }
    }

    pub fn prev_at(&self, index: usize, which: Which) -> u16 {
        match which {
            Which::Hash1 => self.hash1.prev[index],
            Which::Hash2 => self.hash2.prev[index],
        }
    }

    pub fn hash_val_at(&self, index: usize, which: Which) -> i32 {
        match which {
            Which::Hash1 => self.hash1.hashval[index],
            Which::Hash2 => self.hash2.hashval[index],
        }
    }

    pub fn val(&self, which: Which) -> i32 {
        match which {
            Which::Hash1 => self.hash1.val,
            Which::Hash2 => self.hash2.val,
        }
    }
}
<|endoftext|>


<commit_before>use url::{Url};

use std::io::{Reader, IoResult};
use std::fmt::{Show, Formatter, FormatError};
use std::io::net::ip::SocketAddr;
use anymap::AnyMap;

use server_backend::method::Method;
use server_backend::header;
use server_backend::header::Headers;
use server_backend::server::Request as RawRequest;
use server_backend::mime::{Mime, Application, Json};
use server_backend::uri;

pub trait Request: Reader + Show + Send {
    fn remote_addr(&self) -> &SocketAddr;
    fn headers(&self) -> &Headers;
    fn method(&self) -> &Method;
    fn ext(&self) -> &AnyMap;
    fn ext_mut(&mut self) -> &mut AnyMap;
    fn url(&self) -> &Url;

    fn is_json_body(&self) -> bool {
        let content_type = self.headers().get::<header::common::ContentType>();
        if content_type.is_some() {
            println!("ContentType: {}", content_type.unwrap().0);
            match content_type.unwrap().0 {
                Mime(Application, Json, _) => true,
                _ => false
            }
        } else {
            false
        }
    }
}

#[deriving(Send)]
pub struct ServerRequest {
    pub url: Url,
    pub ext: AnyMap,
    raw: RawRequest
}

impl Request for ServerRequest {

    fn url(&self) -> &Url {
        return &self.url;
    }

    fn remote_addr(&self) -> &SocketAddr {
        return &self.raw.remote_addr;
    }

    fn headers(&self) -> &Headers {
        return &self.raw.headers;
    }

    fn method(&self) -> &Method {
        return &self.raw.method;
    }

    fn ext(&self) -> &AnyMap {
        &self.ext
    }

    fn ext_mut(&mut self) -> &mut AnyMap {
        &mut self.ext
    }
}

impl ServerRequest {
    pub fn new(url: Url, req: RawRequest) -> ServerRequest {
        ServerRequest {
            url: url,
            raw: req,
            ext: AnyMap::new(),
        }
    }

    pub fn wrap(req: RawRequest) -> Result<ServerRequest, String> {

        let url = match req.uri {
            uri::AbsolutePath(ref path) => {
                match req.headers.get::<header::common::Host>() {
                    Some(host) => format!("http://{}{}", host.0, path),
                    None => return Err("No HOST header specified in request".to_string())
                }
            },
            uri::AbsoluteUri(ref uri) => format!("{}", uri),
            _ => return Err("Unsupported request URI".to_string())
        };

        println!("Url is {}", url);

        let parsed_url = match Url::parse(url.as_slice()) {
            Ok(url) => url,
            Err(parse_error) => return Err(format!("{}", parse_error))
        };

        Ok(ServerRequest::new(parsed_url, req))

    }
}

impl Reader for ServerRequest {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.raw.read(buf)
    }
}

impl Show for ServerRequest {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
        try!(writeln!(f, "ServerRequest ->"));
        try!(writeln!(f, "  url: {}", self.url));
        try!(writeln!(f, "  method: {}", self.method()));
        try!(writeln!(f, "  path: {}", self.url.path()));
        try!(writeln!(f, "  query: {}", self.url.query));
        try!(writeln!(f, "  remote_addr: {}", self.remote_addr()));
        Ok(())
    }
}<commit_msg>refactor: remove obsolete debug printing<commit_after>use url::{Url};

use std::io::{Reader, IoResult};
use std::fmt::{Show, Formatter, FormatError};
use std::io::net::ip::SocketAddr;
use anymap::AnyMap;

use server_backend::method::Method;
use server_backend::header;
use server_backend::header::Headers;
use server_backend::server::Request as RawRequest;
use server_backend::mime::{Mime, Application, Json};
use server_backend::uri;

pub trait Request: Reader + Show + Send {
    fn remote_addr(&self) -> &SocketAddr;
    fn headers(&self) -> &Headers;
    fn method(&self) -> &Method;
    fn ext(&self) -> &AnyMap;
    fn ext_mut(&mut self) -> &mut AnyMap;
    fn url(&self) -> &Url;

    fn is_json_body(&self) -> bool {
        let content_type = self.headers().get::<header::common::ContentType>();
        if content_type.is_some() {
            match content_type.unwrap().0 {
                Mime(Application, Json, _) => true,
                _ => false
            }
        } else {
            false
        }
    }
}

#[deriving(Send)]
pub struct ServerRequest {
    pub url: Url,
    pub ext: AnyMap,
    raw: RawRequest
}

impl Request for ServerRequest {

    fn url(&self) -> &Url {
        return &self.url;
    }

    fn remote_addr(&self) -> &SocketAddr {
        return &self.raw.remote_addr;
    }

    fn headers(&self) -> &Headers {
        return &self.raw.headers;
    }

    fn method(&self) -> &Method {
        return &self.raw.method;
    }

    fn ext(&self) -> &AnyMap {
        &self.ext
    }

    fn ext_mut(&mut self) -> &mut AnyMap {
        &mut self.ext
    }
}

impl ServerRequest {
    pub fn new(url: Url, req: RawRequest) -> ServerRequest {
        ServerRequest {
            url: url,
            raw: req,
            ext: AnyMap::new(),
        }
    }

    pub fn wrap(req: RawRequest) -> Result<ServerRequest, String> {

        let url = match req.uri {
            uri::AbsolutePath(ref path) => {
                match req.headers.get::<header::common::Host>() {
                    Some(host) => format!("http://{}{}", host.0, path),
                    None => return Err("No HOST header specified in request".to_string())
                }
            },
            uri::AbsoluteUri(ref uri) => format!("{}", uri),
            _ => return Err("Unsupported request URI".to_string())
        };

        let parsed_url = match Url::parse(url.as_slice()) {
            Ok(url) => url,
            Err(parse_error) => return Err(format!("{}", parse_error))
        };

        Ok(ServerRequest::new(parsed_url, req))

    }
}

impl Reader for ServerRequest {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.raw.read(buf)
    }
}

impl Show for ServerRequest {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FormatError> {
        try!(writeln!(f, "ServerRequest ->"));
        try!(writeln!(f, "  url: {}", self.url));
        try!(writeln!(f, "  method: {}", self.method()));
        try!(writeln!(f, "  path: {}", self.url.path()));
        try!(writeln!(f, "  query: {}", self.url.query));
        try!(writeln!(f, "  remote_addr: {}", self.remote_addr()));
        Ok(())
    }
}<|endoftext|>


<commit_before>use std::fs::File;
use std::path::Path;
use std::str::FromStr;

use rust_decimal::Decimal;

#[derive(Serialize, Deserialize)]
struct FuzzInput {
    left: String,
    right: String,
    operator: Op,
    result: String,
}

impl FuzzInput {
    fn new(a: &String, b: &String, op: Op) -> FuzzInput {
        // Use the decimal crate that wraps the C library to calculate
        // the result. This has higher precision so we then round it naively.
        FuzzInput {
            left: a.to_string(),
            right: b.to_string(),
            operator: op,
            result: FuzzInput::calculate(a, b, op),
        }
    }

    fn calculate(a: &String, b: &String, op: Op) -> String {
        use decimal::d128;

        let a = d128::from_str(a).unwrap();
        let b = d128::from_str(b).unwrap();
        let result = match op {
            Op::Add => a + b,
            Op::Sub => a - b,
            Op::Mul => a * b,
            Op::Div => a / b,
        }.to_string();
        if result.len() > 30 {
            // Absolute max of 29 + decimal point
            let (r1, _r2) = result.split_at(30);
            let r1 = r1.to_string();
            // TODO: Round
            r1
        } else {
            result
        }
    }
}

#[derive(Clone, Copy, Serialize, Deserialize)]
enum Op {
    Add,
    Sub,
    Mul,
    Div,
}

fn to_str<E: ::std::fmt::Display>(e: E) -> String {
    format!("{}", e)
}

pub fn generate(sample_size: u32, output: &Path) -> Result<(), String> {
    let pairs = generate_pairs(sample_size as usize);
    let input = pairs.iter()
                    .flat_map(|(a, b)|
                        vec![
                            FuzzInput::new(a, b, Op::Add),
                            FuzzInput::new(a, b, Op::Sub),
                            // TODO: These cause overflow but the C lib doesn't throw
                            //FuzzInput::new(a, b, Op::Mul),
                            FuzzInput::new(a, b, Op::Div),
                        ]
                    )
                    .collect::<Vec<_>>();
    let file = File::create(output).map_err(to_str)?;
    serde_json::to_writer_pretty(file, &input).map_err(to_str)?;
    Ok(())
}

fn generate_pairs(size: usize) -> Vec<(String, String)> {
    let mut v = Vec::new();
    for _ in 0..size {
        let i_int = rand::random::<u64>();
        let i_frac = rand::random::<u64>();
        let j_int = rand::random::<u64>();
        let j_frac = rand::random::<u64>();
        v.push((format!("{}.{}", i_int, i_frac), format!("{}.{}", j_int, j_frac)));
    }
    v
}

pub fn run(path: &Path) -> Result<(), String> {
    // Load in the json input
    let file = File::open(path).map_err(to_str)?;
    let input : Vec<FuzzInput> = serde_json::from_reader(file).map_err(to_str)?;
    let mut index = 0;
    for item in input {
        let a = Decimal::from_str(&item.left)
                    .expect(&format!("Failed to unwrap left for index: {}", index));
        let b = Decimal::from_str(&item.right)
                    .expect(&format!("Failed to unwrap right for index: {}", index));
        let result = match item.operator {
            Op::Add => a + b,
            Op::Sub => a - b,
            Op::Mul => a * b,
            Op::Div => a / b,
        }.to_string();
        // Finally, see if we match the result
        if result.ne(&item.result) {
            panic!("Result mismatch for index {}: {}", index, result);
        }
        index += 1;
    }
    Ok(())
}
<commit_msg>Adds naive rounding for fuzzer<commit_after>use std::fs::File;
use std::path::Path;
use std::str::FromStr;

use rust_decimal::Decimal;

#[derive(Serialize, Deserialize)]
struct FuzzInput {
    test: String,
    left: String,
    right: String,
    operator: Op,
    result: String,
}

impl FuzzInput {
    fn new(test_number: u32, a: &String, b: &String, op: Op) -> FuzzInput {
        // Use the decimal crate that wraps the C library to calculate
        // the result. This has higher precision so we then round it naively.
        FuzzInput {
            test: format!("{}.{}", test_number, op),
            left: a.to_string(),
            right: b.to_string(),
            operator: op,
            result: FuzzInput::calculate(a, b, op),
        }
    }

    fn calculate(a: &String, b: &String, op: Op) -> String {
        use decimal::d128;

        let a = d128::from_str(a).unwrap();
        let b = d128::from_str(b).unwrap();
        let result = match op {
            Op::Add => a + b,
            Op::Sub => a - b,
            Op::Mul => a * b,
            Op::Div => a / b,
        }.to_string();
        if result.len() > 30 {
            // Absolute max of 29 + decimal point
            let (r1, r2) = result.split_at(30);
            //let negative = r1.chars().next().unwrap() == '-';
            let mut r1 = r1.to_string();
            // TODO: This rounding is naive and mostly wrong.
            let next_digit = r2.chars().next().unwrap().to_digit(10).unwrap();
            if next_digit >= 5 {
                let last_digit = r1.pop().unwrap().to_digit(10).unwrap() + 1;
                // If it is 10 then add one to the previous
                // Obviously, this could keep going but for now just do the next digit
                if last_digit > 9 {
                    let prev_digit = r1.pop().unwrap().to_digit(10).unwrap() + 1;
                    if prev_digit > 9 {
                        // We're in the loop scenario. Let's ignore rather than looping
                        // for now.
                        panic!("TODO");
                    }
                    r1.push_str(&format!("{}0", prev_digit));
                } else {
                    r1.push_str(&format!("{}", last_digit));
                }
            }
            r1
        } else {
            result
        }
    }
}

#[derive(Clone, Copy, Serialize, Deserialize)]
enum Op {
    Add,
    Sub,
    Mul,
    Div,
}

impl ::std::fmt::Display for Op {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        write!(f, "{}", match self {
            Op::Add => "add",
            Op::Sub => "sub",
            Op::Mul => "mul",
            Op::Div => "div",
        })
    }
}

fn to_str<E: ::std::fmt::Display>(e: E) -> String {
    format!("{}", e)
}

pub fn generate(sample_size: u32, output: &Path) -> Result<(), String> {
    let pairs = generate_pairs(sample_size as usize);
    let mut test_number = 0;
    let input = pairs.iter()
                    .flat_map(move |(a, b)| {
                        test_number += 1;
                        vec![
                            FuzzInput::new(test_number, a, b, Op::Add),
                            FuzzInput::new(test_number, a, b, Op::Sub),
                            // TODO: These cause overflow but the C lib doesn't throw
                            //FuzzInput::new(test_number, a, b, Op::Mul),
                            FuzzInput::new(test_number, a, b, Op::Div),
                        ]
                    })
                    .collect::<Vec<_>>();
    let file = File::create(output).map_err(to_str)?;
    serde_json::to_writer_pretty(file, &input).map_err(to_str)?;
    Ok(())
}

fn generate_pairs(size: usize) -> Vec<(String, String)> {
    let mut v = Vec::new();
    for _ in 0..size {
        let i_int = rand::random::<u64>();
        let i_frac = rand::random::<u64>();
        let j_int = rand::random::<u64>();
        let j_frac = rand::random::<u64>();
        v.push((format!("{}.{}", i_int, i_frac), format!("{}.{}", j_int, j_frac)));
    }
    v
}

pub fn run(path: &Path) -> Result<(), String> {
    // Load in the json input
    let file = File::open(path).map_err(to_str)?;
    let input : Vec<FuzzInput> = serde_json::from_reader(file).map_err(to_str)?;
    for item in input {
        let a = Decimal::from_str(&item.left)
                    .expect(&format!("Failed to unwrap left for test: {}", item.test));
        let b = Decimal::from_str(&item.right)
                    .expect(&format!("Failed to unwrap right for test: {}", item.test));
        let result = match item.operator {
            Op::Add => a + b,
            Op::Sub => a - b,
            Op::Mul => a * b,
            Op::Div => a / b,
        }.to_string();
        // Finally, see if we match the result
        if result.ne(&item.result) {
            panic!("Result mismatch for test {}: {}", item.test, result);
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>use crate::model::{GameId, Speed};
use shakmaty::san::San;
use shakmaty::fen::Fen;
use serde::Deserialize;
use serde_with::{serde_as, DisplayFromStr, StringWithSeparator, SpaceSeparator};

#[serde_as]
#[derive(Deserialize)]
struct Game {
    #[serde_as(as = "DisplayFromStr")]
    id: GameId,
    rated: bool, // TODO: mode
    status: Status,
    variant: LilaVariant,
    players: Players,
    speed: Speed,
    #[serde_as(as = "StringWithSeparator::<SpaceSeparator, San>")]
    moves: Vec<San>,
    #[serde(default)]
    winner: Option<WinnerColor>,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default, rename = "initialFen")]
    initial_fen: Option<Fen>
}

#[derive(Deserialize)]
struct Players {
    white: Player,
    black: Player,
}

#[derive(Deserialize)]
struct Player {
    user: User,
    rating: u16,
}

#[derive(Deserialize)]
struct User {
    name: String,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
enum LilaVariant {
    Antichess,
    Atomic,
    Chess960,
    Crazyhouse,
    FromPosition,
    Horde,
    KingOfTheHill,
    RacingKings,
    Standard,
    ThreeCheck,
}

#[derive(Deserialize)]
enum WinnerColor {
    #[serde(rename = "white")]
    White,
    #[serde(rename = "black")]
    Black,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
enum Status {
    Created,
    Started,
    Aborted,
    Mate,
    Resign,
    Stalemate,
    Timeout,
    Draw,
    #[serde(rename = "outoftime")]
    OutOfTime,
    Cheat,
    NoStart,
    UnknownFinish,
    VariantEnd,
}

impl Status {
    pub fn is_ongoing(self) -> bool {
        matches!(self, Status::Created | Status::Started)
    }

    pub fn is_unindexable(self) -> bool {
        matches!(self, Status::UnknownFinish | Status::NoStart | Status::Aborted)
    }
}
<commit_msg>let rated stay a bool<commit_after>use crate::model::{GameId, Speed};
use shakmaty::san::San;
use shakmaty::fen::Fen;
use serde::Deserialize;
use serde_with::{serde_as, DisplayFromStr, StringWithSeparator, SpaceSeparator};

#[serde_as]
#[derive(Deserialize)]
struct Game {
    #[serde_as(as = "DisplayFromStr")]
    id: GameId,
    rated: bool,
    status: Status,
    variant: LilaVariant,
    players: Players,
    speed: Speed,
    #[serde_as(as = "StringWithSeparator::<SpaceSeparator, San>")]
    moves: Vec<San>,
    #[serde(default)]
    winner: Option<WinnerColor>,
    #[serde_as(as = "Option<DisplayFromStr>")]
    #[serde(default, rename = "initialFen")]
    initial_fen: Option<Fen>
}

#[derive(Deserialize)]
struct Players {
    white: Player,
    black: Player,
}

#[derive(Deserialize)]
struct Player {
    user: User,
    rating: u16,
}

#[derive(Deserialize)]
struct User {
    name: String,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
enum LilaVariant {
    Antichess,
    Atomic,
    Chess960,
    Crazyhouse,
    FromPosition,
    Horde,
    KingOfTheHill,
    RacingKings,
    Standard,
    ThreeCheck,
}

#[derive(Deserialize)]
enum WinnerColor {
    #[serde(rename = "white")]
    White,
    #[serde(rename = "black")]
    Black,
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
enum Status {
    Created,
    Started,
    Aborted,
    Mate,
    Resign,
    Stalemate,
    Timeout,
    Draw,
    #[serde(rename = "outoftime")]
    OutOfTime,
    Cheat,
    NoStart,
    UnknownFinish,
    VariantEnd,
}

impl Status {
    pub fn is_ongoing(self) -> bool {
        matches!(self, Status::Created | Status::Started)
    }

    pub fn is_unindexable(self) -> bool {
        matches!(self, Status::UnknownFinish | Status::NoStart | Status::Aborted)
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use super::super::{BinaryRateLimiter, Connection, ConnectionID, Config};

/// Trait for implementation of client / server event handling.
pub trait Handler<T> {

    // Factories

    /// Method that returns a new `RateLimiter` instance for use with a
    /// freshly instantiated `Connection`.
    fn rate_limiter(&self, config: &Config) -> Box<BinaryRateLimiter> {
        BinaryRateLimiter::new(config)
    }

    // Server only

    /// Method that is called once a `Server` has successfully bound itself
    /// to its local address.
    fn bind(&mut self, _: &mut T) {
    }

    /// Method that is called each time a `Server` "ticks". A "tick" occurs
    /// in-between the receiving and sending data from / to connections.
    fn tick_connections(
        &mut self, _: &mut T, _: &mut HashMap<ConnectionID, Connection>
    ) {
    }

    /// Method that is called once a `Server` is going to shutdown.
    fn shutdown(&mut self, _: &mut T) {
    }

    // Client Only

    /// Method that is called once a `Client` has successfully bound itself
    /// to its local address.
    fn connect(&mut self, _: &mut T) {
    }

    /// Method that is called each time a `Client` "ticks". A "tick" occurs
    /// in-between the receiving and sending data from / to connections.
    fn tick_connection(&mut self, _: &mut T, _: &mut Connection) {
    }

    /// Method that is called once a `Client` is going to close.
    fn close(&mut self, _: &mut T) {
    }

    // Connection specific

    /// Method that is called each time a new connection is established.
    fn connection(&mut self, _: &mut T, _: &mut Connection) {
    }

    /// Method that is called each time a connection fails to establish.
    fn connection_failed(&mut self, _: &mut T, _: &mut Connection) {
    }

    /// Method that is called each time a packet send by a connection is lost.
    fn connection_packet_lost(
        &mut self, _: &mut T, _: &mut Connection, _: &[u8]
    ) {

    }

    /// Method that is called each time the congestion state of connection
    /// changes.
    fn connection_congestion_state(&mut self, _: &mut T, _: &mut Connection, _: bool) {
    }

    /// Method that is called each time a connection is lost and dropped.
    fn connection_lost(&mut self, _: &mut T, _: &mut Connection) {
    }

}

<commit_msg>Correct Handler::rate_limiter to return a RateLimiter trait object.<commit_after>use std::collections::HashMap;
use super::super::{
    BinaryRateLimiter, Connection, ConnectionID, Config, RateLimiter
};

/// Trait for implementation of client / server event handling.
pub trait Handler<T> {

    // Factories

    /// Method that returns a new `RateLimiter` instance for use with a
    /// freshly instantiated `Connection`.
    fn rate_limiter(&self, config: &Config) -> Box<RateLimiter> {
        BinaryRateLimiter::new(config)
    }

    // Server only

    /// Method that is called once a `Server` has successfully bound itself
    /// to its local address.
    fn bind(&mut self, _: &mut T) {
    }

    /// Method that is called each time a `Server` "ticks". A "tick" occurs
    /// in-between the receiving and sending data from / to connections.
    fn tick_connections(
        &mut self, _: &mut T, _: &mut HashMap<ConnectionID, Connection>
    ) {
    }

    /// Method that is called once a `Server` is going to shutdown.
    fn shutdown(&mut self, _: &mut T) {
    }

    // Client Only

    /// Method that is called once a `Client` has successfully bound itself
    /// to its local address.
    fn connect(&mut self, _: &mut T) {
    }

    /// Method that is called each time a `Client` "ticks". A "tick" occurs
    /// in-between the receiving and sending data from / to connections.
    fn tick_connection(&mut self, _: &mut T, _: &mut Connection) {
    }

    /// Method that is called once a `Client` is going to close.
    fn close(&mut self, _: &mut T) {
    }

    // Connection specific

    /// Method that is called each time a new connection is established.
    fn connection(&mut self, _: &mut T, _: &mut Connection) {
    }

    /// Method that is called each time a connection fails to establish.
    fn connection_failed(&mut self, _: &mut T, _: &mut Connection) {
    }

    /// Method that is called each time a packet send by a connection is lost.
    fn connection_packet_lost(
        &mut self, _: &mut T, _: &mut Connection, _: &[u8]
    ) {

    }

    /// Method that is called each time the congestion state of connection
    /// changes.
    fn connection_congestion_state(&mut self, _: &mut T, _: &mut Connection, _: bool) {
    }

    /// Method that is called each time a connection is lost and dropped.
    fn connection_lost(&mut self, _: &mut T, _: &mut Connection) {
    }

}

<|endoftext|>


<commit_before>fn split<'a, T>(list: &'a [T], n: uint) -> (&'a [T], &'a [T]) {
    (list.slice(0, n), list.slice(n, list.len()))
}

fn main() {
    let list = ~['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
    println!("{:?}", split(list, 3));
}

<commit_msg>Neater Problem 17<commit_after>fn split<'a, T>(list: &'a [T], n: uint) -> (&'a [T], &'a [T]) {
    (list.slice_to(n), list.slice_from(n))
}

fn main() {
    let list = ~['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
    println!("{:?}", split(list, 3));
}

<|endoftext|>