<commit_before>extern crate postgres;
extern crate postgres_array;
extern crate rustc_serialize;

pub mod fact_db;
pub mod pg_db;
pub mod engine;

pub mod native_types;

#[derive (Clone)]
pub enum DB {
  Postgres(String)
}

pub enum Error {
  NoDB,
  PgConnect(::postgres::error::ConnectError),
  PgErr(::postgres::error::Error),
  PgDbErr(pg_db::DBError),
  IOErr(::std::io::Error),
  PgConnectStr(Box<::std::error::Error + Send + Sync>),
  EngineErr(engine::Error)
}

use self::Error::*;

use engine::Engine;
use pg_db::PgDB;
use fact_db::FactDB;
use native_types::*;

pub type Result<T> = ::std::result::Result<T, Error>;

use std::fmt::{Debug, Display, Formatter};

impl Display for Error {
  fn fmt(&self, fmt : &mut Formatter)
        -> ::std::result::Result<(),::std::fmt::Error> {
    match *self {
      NoDB             => fmt.write_str("No database specified"),
      PgConnect(ref e) => fmt.write_fmt(format_args!("Connection failed: {}", e)),
      PgErr(ref e)     => fmt.write_fmt(format_args!("Postgres error: {}", e)),
      PgDbErr(ref e)   => fmt.write_fmt(format_args!("Deductive DB (postgres) error: {}", e)),
      PgConnectStr(ref e) => fmt.write_fmt(format_args!("Connection string failed to parse: {}", e)),
      IOErr(ref e) => fmt.write_fmt(format_args!("IO failed: {}", e)),
      EngineErr(ref e) => fmt.write_fmt(format_args!("Engine Error: {}", e))
    }
  }
}

impl Debug for Error  {
  fn fmt(&self, fmt : &mut Formatter)
        -> ::std::result::Result<(),::std::fmt::Error> {
    Display::fmt(self, fmt)
  }
}

impl ::std::error::Error for Error {
  fn description(&self) -> &str {
    match self {
      &NoDB              => "No database specified",
      &PgConnect(ref e)  => e.description(),
      &PgErr(ref e)      => e.description(),
      &PgDbErr(ref e)    => e.description(),
      &IOErr(ref e)      => e.description(),
      &EngineErr(ref e)  => e.description(),
      &PgConnectStr(_)   => "Connection string failed to parse"
    }
  }
}

impl From<::postgres::error::ConnectError> for Error {
  fn from(ce : ::postgres::error::ConnectError) -> Error {PgConnect(ce)}
}

impl From<::postgres::error::Error> for Error {
  fn from(e : ::postgres::error::Error) -> Error {PgErr(e)}
}

impl From<pg_db::DBError> for Error {
  fn from(e : pg_db::DBError) -> Error {PgDbErr(e)}
}

impl From<engine::Error> for Error {
  fn from(e : engine::Error) -> Error {EngineErr(e)}
}

impl From<::std::io::Error> for Error {
  fn from(e : ::std::io::Error) -> Error {IOErr(e)}
}

impl<'a> DB {
  fn destroy(&self) -> Result<()> {
    match self {
      &DB::Postgres(ref str) => {
        use postgres::{Connection, SslMode, IntoConnectParams};
        let mut params = try!(str.into_connect_params().map_err(PgConnectStr));
        let old_db = try!(params.database.ok_or(NoDB));
        params.database = Some("postgres".to_owned());
        let conn = try!(Connection::connect(params, SslMode::None));
        let disco_query = format!("SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '{}' AND pid <> pg_backend_pid()", &old_db);
        try!(conn.execute(&disco_query, &[]));
        let drop_query = format!("DROP DATABASE {}", &old_db);
        try!(conn.execute(&drop_query, &[]));
      }
    }
    Ok(())
  }
  fn create(&self) -> Result<Box<FactDB>> {
    match self {
      &DB::Postgres(ref str) => {
        use postgres::{Connection, SslMode, IntoConnectParams};
        let mut params = try!(str.into_connect_params().map_err(PgConnectStr));
        let old_db = try!(params.database.ok_or(NoDB));
        params.database = Some("postgres".to_owned());
        let conn = try!(Connection::connect(params, SslMode::None));
        let create_query = format!("CREATE DATABASE {}", &old_db);
        //TODO accept success or db already exists, not other errors
        let _ = conn.execute(&create_query, &[]);
        Ok(Box::new(try!(PgDB::new(str))))
      }
    }
  }
}

pub struct Holmes {
  db : DB,
  engine : Engine
}

impl Holmes {
  pub fn new(db : DB) -> Result<Holmes> {
    Ok(Holmes {
      engine : Engine::new(try!(db.create())),
      db : db
    })
  }
  pub fn destroy(self) -> Result<()> {
    let db = self.db.clone();
    drop(self);
    db.destroy()
  }
  pub fn add_predicate(&mut self, pred : &native_types::Predicate)
                      -> Result<()> {
    self.engine.new_predicate(pred).map_err(|e| {EngineErr(e)})
  }
  pub fn add_fact(&mut self, fact : &native_types::Fact)
                      -> Result<()> {
    self.engine.new_fact(fact).map_err(|e| {EngineErr(e)})
  }
  pub fn query(&mut self, query : &Vec<native_types::Clause>) -> Result<Vec<Vec<native_types::HValue>>> {
    self.engine.derive(query).map_err(|e| {EngineErr(e)})
  }
  pub fn add_rule(&mut self, rule : &native_types::Rule) -> Result<()> {
    self.engine.new_rule(rule).map_err(|e| {EngineErr(e)})
  }
  pub fn reg_func(&mut self,
                  name : String,
                  input_type  : native_types::HType,
                  output_type : native_types::HType,
                  func : Box<Fn(native_types::HValue) -> native_types::HValue>) -> Result<()> {
    self.engine.reg_func(name, native_types::HFunc {
      input_type  : input_type,
      output_type : output_type,
      run : func
    });
    Ok(())
  }
}

#[macro_export]
macro_rules! htype_raw {
  (string) => { ::holmes::native_types::HType::HString};
  (blob  ) => { ::holmes::native_types::HType::Blob};
  (uint64) => { ::holmes::native_types::HType::UInt64};
}

#[macro_export]
macro_rules! htype {
  ([$t:tt]) => { ::holmes::native_types::HType::List(Box::new(htype!($t))) };
  (($($t:tt),*)) => { ::holmes::native_types::HType::Tuple(vec![$(htype!($t)),*]) };
  ($i:ident) => { htype_raw!($i) };
}

#[macro_export]
macro_rules! holmes_exec {
  ($holmes:ident, { $( $action:expr );* }) => {
      {
        $( try!($action($holmes)); );*
        let res : Result<()> = Ok(());
        res
      }
  };
}

#[macro_export]
macro_rules! predicate {
  ($holmes:ident, $pred_name:ident($($t:tt),*)) => {
    $holmes.add_predicate(&::holmes::native_types::Predicate {
      name  : stringify!($pred_name).to_string(),
      types : vec![$(htype!($t),)*]
    })
  };
  ($pred_name:ident($($t:tt),*)) => { |holmes : &mut Holmes| {
    let res : Result<()> = predicate!(holmes, $pred_name($($t),*));
    res
  }};
}

#[macro_export]
macro_rules! fact {
  ($holmes:ident, $pred_name:ident($($a:expr),*)) => {
    $holmes.add_fact(&::holmes::native_types::Fact {
      pred_name : stringify!($pred_name).to_string(),
      args : vec![$($a.to_hvalue()),*]
    })
  };
  ($pred_name:ident($($a:expr),*)) => { |holmes : &mut Holmes| {
    let res : Result<()> = fact!(holmes, $pred_name($($a),*));
    res
  }};
}

#[macro_export]
macro_rules! bind_match {
  ($vars:ident, $n:ident, [$bm:tt]) => { ::holmes::native_types::BindExpr::Iterate(Box::new(bind_match!($vars, $n, $bm))) };
  ($vars:ident, $n:ident, |$($bm:tt),*|) => {
    ::holmes::native_types::BindExpr::Destructure(vec![$(bind_match!($vars, $n, $bm)),*])
  };
  ($vars:ident, $n:ident, $cm:tt) => { ::holmes::native_types::BindExpr::Normal(clause_match!($vars, $n, $cm)) };
}

#[macro_export]
macro_rules! clause_match {
  ($vars:ident, $n:ident, [_]) => { ::holmes::native_types::MatchExpr::Unbound };
  ($vars:ident, $n:ident, ($v:expr)) => { ::holmes::native_types::MatchExpr::HConst($v.to_hvalue()) };
  ($vars:ident, $n:ident, $m:ident) => {{
    use std::collections::hash_map::Entry::*;
    use ::holmes::native_types::MatchExpr::*;
    match $vars.entry(stringify!($m).to_string()) {
      Occupied(entry) => Var(*entry.get()),
      Vacant(entry) => {
        $n = $n + 1;
        entry.insert($n - 1);
        Var($n - 1)
      }
    }
  }};
}

#[macro_export]
macro_rules! query {
  ($holmes:ident, $($pred_name:ident($($m:tt),*))&*) => {{
    use std::collections::HashMap;
    let mut vars : HashMap<String, ::holmes::native_types::HVar> = HashMap::new();
    let mut n : ::holmes::native_types::HVar = 0;
    $holmes.query(&vec![$(::holmes::native_types::Clause {
      pred_name : stringify!($pred_name).to_string(),
      args : vec![$(clause_match!(vars, n, $m)),*]
    }),*])
  }}
}

pub fn var_to_evar(var : MatchExpr) -> Expr {
  match var {
    MatchExpr::Var(var_no) => Expr::EVar(var_no),
    x => panic!("var_to_evar was passed nonvar: {:?}", x)
  }
}

#[macro_export]
macro_rules! hexpr {
  ($vars:ident, $n:ident, [$hexpr_name:ident]) => {
    var_to_evar(clause_match!($vars, $n, $hexpr_name))
  };
  ($vars:ident, $n:ident, ($hexpr:expr)) => {
    Expr::EVal($hexpr.to_hvalue())
  };
  ($vars:ident, $n:ident, {$hexpr_func:ident($($hexpr_arg:tt),*)}) => {
    Expr::EApp(stringify!($hexpr_func).to_string(), vec![$(hexpr!($vars, $n, $hexpr_arg)),*])
  };
}

#[macro_export]
macro_rules! rule {
  ($holmes:ident, $head_name:ident($($m:tt),*) <= $($body_name:ident($($mb:tt),*))&*,
   {$(let $bind:tt = $hexpr:tt);*}) => {{
    use std::collections::HashMap;
    let mut vars : HashMap<String, ::holmes::native_types::HVar> = HashMap::new();
    let mut n : ::holmes::native_types::HVar = 0;
    $holmes.add_rule(&::holmes::native_types::Rule {
      body : vec![$(::holmes::native_types::Clause {
        pred_name : stringify!($body_name).to_string(),
        args : vec![$(clause_match!(vars, n, $mb)),*]
      }),*],
      head : ::holmes::native_types::Clause {
        pred_name : stringify!($head_name).to_string(),
        args : vec![$(clause_match!(vars, n, $m)),*]
      },
      wheres : vec! [$(::holmes::native_types::WhereClause {
        lhs   : bind_match!(vars, n, $bind),
        rhs   : hexpr!(vars, n, $hexpr)
      }),*]
    })
  }};
  ($holmes:ident, $head_name:ident($($m:tt),*) <= $($body_name:ident($($mb:tt),*))&*,
   {$(let $($bind:tt),* = $hexpr:tt);*}) => {{
    use std::collections::HashMap;
    let mut vars : HashMap<String, ::holmes::native_types::HVar> = HashMap::new();
    let mut n : ::holmes::native_types::HVar = 0;
    $holmes.add_rule(&::holmes::native_types::Rule {
      body : vec![$(::holmes::native_types::Clause {
        pred_name : stringify!($body_name).to_string(),
        args : vec![$(clause_match!(vars, n, $mb)),*]
      }),*],
      head : ::holmes::native_types::Clause {
        pred_name : stringify!($head_name).to_string(),
        args : vec![$(clause_match!(vars, n, $m)),*]
      },
      wheres : vec! [$(::holmes::native_types::WhereClause {
        lhs   : ::holmes::native_types::BindExpr::Destructure(
                  vec![$(::holmes::native_types::BindExpr::Normal(
                    clause_match!(vars, n, $bind))),*]),
        rhs   : hexpr!(vars, n, $hexpr)
      }),*]
    })
  }};
  ($($head_name:ident($($m:tt),*)),* <= $($body_name:ident($($mb:tt),*))&*) => {
    |holmes : &mut Holmes| {
      rule!(holmes, $($head_name($($m),*)),* <= $($body_name($($mb),*))&*, {})
    }
  };
  ($($head_name:ident($($m:tt),*)),* <= $($body_name:ident($($mb:tt),*))&*, {$(let $($bind:tt),* = $hexpr:tt);*}) => {
    |holmes : &mut Holmes| {
      rule!(holmes, $($head_name($($m),*)),* <= $($body_name($($mb),*))&*, {$(let $($bind),* = $hexpr);*})
    }
  };

}

#[macro_export]
macro_rules! func {
  ($holmes:ident, let $name:ident : $src:tt -> $dst:tt = $body:expr) => {
    $holmes.reg_func(stringify!($name).to_string(),
                     htype!($src),
                     htype!($dst),
                     Box::new($body))
  };
  (let $name:ident : $src:tt -> $dst:tt = $body:expr) => {
    |holmes : &mut Holmes| {
      func!(holmes, let $name : $src -> $dst = $body)
    }
  };
}
<commit_msg>Use global paths inside macros<commit_after>extern crate postgres;
extern crate postgres_array;
extern crate rustc_serialize;

pub mod fact_db;
pub mod pg_db;
pub mod engine;

pub mod native_types;

#[derive (Clone)]
pub enum DB {
  Postgres(String)
}

pub enum Error {
  NoDB,
  PgConnect(::postgres::error::ConnectError),
  PgErr(::postgres::error::Error),
  PgDbErr(pg_db::DBError),
  IOErr(::std::io::Error),
  PgConnectStr(Box<::std::error::Error + Send + Sync>),
  EngineErr(engine::Error)
}

use self::Error::*;

use engine::Engine;
use pg_db::PgDB;
use fact_db::FactDB;
use native_types::*;

pub type Result<T> = ::std::result::Result<T, Error>;

use std::fmt::{Debug, Display, Formatter};

impl Display for Error {
  fn fmt(&self, fmt : &mut Formatter)
        -> ::std::result::Result<(),::std::fmt::Error> {
    match *self {
      NoDB             => fmt.write_str("No database specified"),
      PgConnect(ref e) => fmt.write_fmt(format_args!("Connection failed: {}", e)),
      PgErr(ref e)     => fmt.write_fmt(format_args!("Postgres error: {}", e)),
      PgDbErr(ref e)   => fmt.write_fmt(format_args!("Deductive DB (postgres) error: {}", e)),
      PgConnectStr(ref e) => fmt.write_fmt(format_args!("Connection string failed to parse: {}", e)),
      IOErr(ref e) => fmt.write_fmt(format_args!("IO failed: {}", e)),
      EngineErr(ref e) => fmt.write_fmt(format_args!("Engine Error: {}", e))
    }
  }
}

impl Debug for Error  {
  fn fmt(&self, fmt : &mut Formatter)
        -> ::std::result::Result<(),::std::fmt::Error> {
    Display::fmt(self, fmt)
  }
}

impl ::std::error::Error for Error {
  fn description(&self) -> &str {
    match self {
      &NoDB              => "No database specified",
      &PgConnect(ref e)  => e.description(),
      &PgErr(ref e)      => e.description(),
      &PgDbErr(ref e)    => e.description(),
      &IOErr(ref e)      => e.description(),
      &EngineErr(ref e)  => e.description(),
      &PgConnectStr(_)   => "Connection string failed to parse"
    }
  }
}

impl From<::postgres::error::ConnectError> for Error {
  fn from(ce : ::postgres::error::ConnectError) -> Error {PgConnect(ce)}
}

impl From<::postgres::error::Error> for Error {
  fn from(e : ::postgres::error::Error) -> Error {PgErr(e)}
}

impl From<pg_db::DBError> for Error {
  fn from(e : pg_db::DBError) -> Error {PgDbErr(e)}
}

impl From<engine::Error> for Error {
  fn from(e : engine::Error) -> Error {EngineErr(e)}
}

impl From<::std::io::Error> for Error {
  fn from(e : ::std::io::Error) -> Error {IOErr(e)}
}

impl<'a> DB {
  fn destroy(&self) -> Result<()> {
    match self {
      &DB::Postgres(ref str) => {
        use postgres::{Connection, SslMode, IntoConnectParams};
        let mut params = try!(str.into_connect_params().map_err(PgConnectStr));
        let old_db = try!(params.database.ok_or(NoDB));
        params.database = Some("postgres".to_owned());
        let conn = try!(Connection::connect(params, SslMode::None));
        let disco_query = format!("SELECT pg_terminate_backend(pg_stat_activity.pid) FROM pg_stat_activity WHERE pg_stat_activity.datname = '{}' AND pid <> pg_backend_pid()", &old_db);
        try!(conn.execute(&disco_query, &[]));
        let drop_query = format!("DROP DATABASE {}", &old_db);
        try!(conn.execute(&drop_query, &[]));
      }
    }
    Ok(())
  }
  fn create(&self) -> Result<Box<FactDB>> {
    match self {
      &DB::Postgres(ref str) => {
        use postgres::{Connection, SslMode, IntoConnectParams};
        let mut params = try!(str.into_connect_params().map_err(PgConnectStr));
        let old_db = try!(params.database.ok_or(NoDB));
        params.database = Some("postgres".to_owned());
        let conn = try!(Connection::connect(params, SslMode::None));
        let create_query = format!("CREATE DATABASE {}", &old_db);
        //TODO accept success or db already exists, not other errors
        let _ = conn.execute(&create_query, &[]);
        Ok(Box::new(try!(PgDB::new(str))))
      }
    }
  }
}

pub struct Holmes {
  db : DB,
  engine : Engine
}

impl Holmes {
  pub fn new(db : DB) -> Result<Holmes> {
    Ok(Holmes {
      engine : Engine::new(try!(db.create())),
      db : db
    })
  }
  pub fn destroy(self) -> Result<()> {
    let db = self.db.clone();
    drop(self);
    db.destroy()
  }
  pub fn add_predicate(&mut self, pred : &native_types::Predicate)
                      -> Result<()> {
    self.engine.new_predicate(pred).map_err(|e| {EngineErr(e)})
  }
  pub fn add_fact(&mut self, fact : &native_types::Fact)
                      -> Result<()> {
    self.engine.new_fact(fact).map_err(|e| {EngineErr(e)})
  }
  pub fn query(&mut self, query : &Vec<native_types::Clause>) -> Result<Vec<Vec<native_types::HValue>>> {
    self.engine.derive(query).map_err(|e| {EngineErr(e)})
  }
  pub fn add_rule(&mut self, rule : &native_types::Rule) -> Result<()> {
    self.engine.new_rule(rule).map_err(|e| {EngineErr(e)})
  }
  pub fn reg_func(&mut self,
                  name : String,
                  input_type  : native_types::HType,
                  output_type : native_types::HType,
                  func : Box<Fn(native_types::HValue) -> native_types::HValue>) -> Result<()> {
    self.engine.reg_func(name, native_types::HFunc {
      input_type  : input_type,
      output_type : output_type,
      run : func
    });
    Ok(())
  }
}

#[macro_export]
macro_rules! htype_raw {
  (string) => { ::holmes::native_types::HType::HString};
  (blob  ) => { ::holmes::native_types::HType::Blob};
  (uint64) => { ::holmes::native_types::HType::UInt64};
}

#[macro_export]
macro_rules! htype {
  ([$t:tt]) => { ::holmes::native_types::HType::List(Box::new(htype!($t))) };
  (($($t:tt),*)) => { ::holmes::native_types::HType::Tuple(vec![$(htype!($t)),*]) };
  ($i:ident) => { htype_raw!($i) };
}

#[macro_export]
macro_rules! holmes_exec {
  ($holmes:ident, { $( $action:expr );* }) => {
      {
        $( try!($action($holmes)); );*
        let res : ::holmes::Result<()> = Ok(());
        res
      }
  };
}

#[macro_export]
macro_rules! predicate {
  ($holmes:ident, $pred_name:ident($($t:tt),*)) => {
    $holmes.add_predicate(&::holmes::native_types::Predicate {
      name  : stringify!($pred_name).to_string(),
      types : vec![$(htype!($t),)*]
    })
  };
  ($pred_name:ident($($t:tt),*)) => { |holmes : &mut Holmes| {
    let res : ::holmes::Result<()> = predicate!(holmes, $pred_name($($t),*));
    res
  }};
}

#[macro_export]
macro_rules! fact {
  ($holmes:ident, $pred_name:ident($($a:expr),*)) => {
    $holmes.add_fact(&::holmes::native_types::Fact {
      pred_name : stringify!($pred_name).to_string(),
      args : vec![$($a.to_hvalue()),*]
    })
  };
  ($pred_name:ident($($a:expr),*)) => { |holmes : &mut Holmes| {
    let res : ::holmes::Result<()> = fact!(holmes, $pred_name($($a),*));
    res
  }};
}

#[macro_export]
macro_rules! bind_match {
  ($vars:ident, $n:ident, [$bm:tt]) => { ::holmes::native_types::BindExpr::Iterate(Box::new(bind_match!($vars, $n, $bm))) };
  ($vars:ident, $n:ident, |$($bm:tt),*|) => {
    ::holmes::native_types::BindExpr::Destructure(vec![$(bind_match!($vars, $n, $bm)),*])
  };
  ($vars:ident, $n:ident, $cm:tt) => { ::holmes::native_types::BindExpr::Normal(clause_match!($vars, $n, $cm)) };
}

#[macro_export]
macro_rules! clause_match {
  ($vars:ident, $n:ident, [_]) => { ::holmes::native_types::MatchExpr::Unbound };
  ($vars:ident, $n:ident, ($v:expr)) => { ::holmes::native_types::MatchExpr::HConst($v.to_hvalue()) };
  ($vars:ident, $n:ident, $m:ident) => {{
    use std::collections::hash_map::Entry::*;
    use ::holmes::native_types::MatchExpr::*;
    match $vars.entry(stringify!($m).to_string()) {
      Occupied(entry) => Var(*entry.get()),
      Vacant(entry) => {
        $n = $n + 1;
        entry.insert($n - 1);
        Var($n - 1)
      }
    }
  }};
}

#[macro_export]
macro_rules! query {
  ($holmes:ident, $($pred_name:ident($($m:tt),*))&*) => {{
    use std::collections::HashMap;
    let mut vars : HashMap<String, ::holmes::native_types::HVar> = HashMap::new();
    let mut n : ::holmes::native_types::HVar = 0;
    $holmes.query(&vec![$(::holmes::native_types::Clause {
      pred_name : stringify!($pred_name).to_string(),
      args : vec![$(clause_match!(vars, n, $m)),*]
    }),*])
  }}
}

pub fn var_to_evar(var : MatchExpr) -> Expr {
  match var {
    MatchExpr::Var(var_no) => Expr::EVar(var_no),
    x => panic!("var_to_evar was passed nonvar: {:?}", x)
  }
}

#[macro_export]
macro_rules! hexpr {
  ($vars:ident, $n:ident, [$hexpr_name:ident]) => {
    var_to_evar(clause_match!($vars, $n, $hexpr_name))
  };
  ($vars:ident, $n:ident, ($hexpr:expr)) => {
    Expr::EVal($hexpr.to_hvalue())
  };
  ($vars:ident, $n:ident, {$hexpr_func:ident($($hexpr_arg:tt),*)}) => {
    Expr::EApp(stringify!($hexpr_func).to_string(), vec![$(hexpr!($vars, $n, $hexpr_arg)),*])
  };
}

#[macro_export]
macro_rules! rule {
  ($holmes:ident, $head_name:ident($($m:tt),*) <= $($body_name:ident($($mb:tt),*))&*,
   {$(let $bind:tt = $hexpr:tt);*}) => {{
    use std::collections::HashMap;
    let mut vars : HashMap<String, ::holmes::native_types::HVar> = HashMap::new();
    let mut n : ::holmes::native_types::HVar = 0;
    $holmes.add_rule(&::holmes::native_types::Rule {
      body : vec![$(::holmes::native_types::Clause {
        pred_name : stringify!($body_name).to_string(),
        args : vec![$(clause_match!(vars, n, $mb)),*]
      }),*],
      head : ::holmes::native_types::Clause {
        pred_name : stringify!($head_name).to_string(),
        args : vec![$(clause_match!(vars, n, $m)),*]
      },
      wheres : vec! [$(::holmes::native_types::WhereClause {
        lhs   : bind_match!(vars, n, $bind),
        rhs   : hexpr!(vars, n, $hexpr)
      }),*]
    })
  }};
  ($holmes:ident, $head_name:ident($($m:tt),*) <= $($body_name:ident($($mb:tt),*))&*,
   {$(let $($bind:tt),* = $hexpr:tt);*}) => {{
    use std::collections::HashMap;
    let mut vars : HashMap<String, ::holmes::native_types::HVar> = HashMap::new();
    let mut n : ::holmes::native_types::HVar = 0;
    $holmes.add_rule(&::holmes::native_types::Rule {
      body : vec![$(::holmes::native_types::Clause {
        pred_name : stringify!($body_name).to_string(),
        args : vec![$(clause_match!(vars, n, $mb)),*]
      }),*],
      head : ::holmes::native_types::Clause {
        pred_name : stringify!($head_name).to_string(),
        args : vec![$(clause_match!(vars, n, $m)),*]
      },
      wheres : vec! [$(::holmes::native_types::WhereClause {
        lhs   : ::holmes::native_types::BindExpr::Destructure(
                  vec![$(::holmes::native_types::BindExpr::Normal(
                    clause_match!(vars, n, $bind))),*]),
        rhs   : hexpr!(vars, n, $hexpr)
      }),*]
    })
  }};
  ($($head_name:ident($($m:tt),*)),* <= $($body_name:ident($($mb:tt),*))&*) => {
    |holmes : &mut Holmes| {
      rule!(holmes, $($head_name($($m),*)),* <= $($body_name($($mb),*))&*, {})
    }
  };
  ($($head_name:ident($($m:tt),*)),* <= $($body_name:ident($($mb:tt),*))&*, {$(let $($bind:tt),* = $hexpr:tt);*}) => {
    |holmes : &mut Holmes| {
      rule!(holmes, $($head_name($($m),*)),* <= $($body_name($($mb),*))&*, {$(let $($bind),* = $hexpr);*})
    }
  };

}

#[macro_export]
macro_rules! func {
  ($holmes:ident, let $name:ident : $src:tt -> $dst:tt = $body:expr) => {
    $holmes.reg_func(stringify!($name).to_string(),
                     htype!($src),
                     htype!($dst),
                     Box::new($body))
  };
  (let $name:ident : $src:tt -> $dst:tt = $body:expr) => {
    |holmes : &mut Holmes| {
      func!(holmes, let $name : $src -> $dst = $body)
    }
  };
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name = "cssparser"]
#![crate_type = "rlib"]

#![deny(missing_docs)]

/*!

Implementation of [CSS Syntax Module Level 3](http://dev.w3.org/csswg/css-syntax-3/) for Rust.

# Input

Everything is based on `Parser` objects, which borrow a `&str` input.
If you have bytes (from a file, the network, or something),
see the `decode_stylesheet_bytes` function.

# Conventions for parsing functions

* Take (at least) a `input: &mut cssparser::Parser` parameter
* Return `Result<_, ()>`
* When returning `Ok(_)`,
  the function must have consume exactly the amount of input that represents the parsed value.
* When returning `Err(())`, any amount of input may have been consumed.

As a consequence, when calling another parsing function, either:

* Any `Err(())` return value must be propagated.
  This happens by definition for tail calls,
  and can otherwise be done with the `try!` macro.
* Or the call must be wrapped in a `Parser::try` call.
  `try` takes a closure that takes a `Parser` and returns a `Result`,
  calls it once,
  and returns itself that same result.
  If the result is `Err`,
  it restores the position inside the input to the one saved before calling the closure.

Examples:

```{rust,ignore}
// 'none' | <image>
fn parse_background_image(context: &ParserContext, input: &mut Parser)
                                    -> Result<Option<Image>, ()> {
    if input.try(|input| input.expect_ident_matching("none")).is_ok() {
        Ok(None)
    } else {
        Image::parse(context, input).map(Some)  // tail call
    }
}
```

```{rust,ignore}
// [ <length> | <percentage> ] [ <length> | <percentage> ]?
fn parse_border_spacing(_context: &ParserContext, input: &mut Parser)
                          -> Result<(LengthOrPercentage, LengthOrPercentage), ()> {
    let first = try!(LengthOrPercentage::parse);
    let second = input.try(LengthOrPercentage::parse).unwrap_or(first);
    (first, second)
}
```

*/

extern crate encoding;
extern crate text_writer;
#[macro_use] extern crate matches;
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate "rustc-serialize" as serialize;

pub use tokenizer::{Token, NumericValue, PercentageValue, SourceLocation};
pub use rules_and_declarations::{parse_important};
pub use rules_and_declarations::{DeclarationParser, DeclarationListParser, parse_one_declaration};
pub use rules_and_declarations::{RuleListParser, parse_one_rule};
pub use rules_and_declarations::{AtRuleType, QualifiedRuleParser, AtRuleParser};
pub use from_bytes::decode_stylesheet_bytes;
pub use color::{RGBA, Color, parse_color_keyword};
pub use nth::parse_nth;
pub use serializer::{ToCss, CssStringWriter, serialize_identifier, serialize_string};
pub use parser::{Parser, Delimiter, Delimiters, SourcePosition};

/**

This macro is equivalent to a `match` expression on an `&str` value,
but matching is case-insensitive in the ASCII range.

Usage example:

```{rust,ignore}
match_ignore_ascii_case! { string:
    "foo" => Some(Foo),
    "bar" => Some(Bar),
    "baz" => Some(Baz)
    _ => None
}
```

The macro also calls `.as_slice()` on the value,
so that a `String` or `CowString` could be passed directly instead of a `&str`.

Note that because of `macro_rules` ambiguity resolutions quirks,
each arm except the fallback and the one before it must end with a comma.

*/
#[macro_export]
macro_rules! match_ignore_ascii_case {
    ( $value: expr, $( $string: expr => $result: expr ),+ _ => $fallback: expr ) => {
        {
            use std::ascii::AsciiExt;
            match $value.as_slice() {
                $(
                    s if s.eq_ignore_ascii_case($string) => $result,
                )+
                _ => $fallback
            }
        }
    };
}

mod rules_and_declarations;
mod tokenizer;
mod parser;
mod from_bytes;
mod color;
mod nth;
mod serializer;

#[cfg(test)]
mod tests;
<commit_msg>Update match_ignore_ascii_case documentation.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![crate_name = "cssparser"]
#![crate_type = "rlib"]

#![deny(missing_docs)]

/*!

Implementation of [CSS Syntax Module Level 3](http://dev.w3.org/csswg/css-syntax-3/) for Rust.

# Input

Everything is based on `Parser` objects, which borrow a `&str` input.
If you have bytes (from a file, the network, or something),
see the `decode_stylesheet_bytes` function.

# Conventions for parsing functions

* Take (at least) a `input: &mut cssparser::Parser` parameter
* Return `Result<_, ()>`
* When returning `Ok(_)`,
  the function must have consume exactly the amount of input that represents the parsed value.
* When returning `Err(())`, any amount of input may have been consumed.

As a consequence, when calling another parsing function, either:

* Any `Err(())` return value must be propagated.
  This happens by definition for tail calls,
  and can otherwise be done with the `try!` macro.
* Or the call must be wrapped in a `Parser::try` call.
  `try` takes a closure that takes a `Parser` and returns a `Result`,
  calls it once,
  and returns itself that same result.
  If the result is `Err`,
  it restores the position inside the input to the one saved before calling the closure.

Examples:

```{rust,ignore}
// 'none' | <image>
fn parse_background_image(context: &ParserContext, input: &mut Parser)
                                    -> Result<Option<Image>, ()> {
    if input.try(|input| input.expect_ident_matching("none")).is_ok() {
        Ok(None)
    } else {
        Image::parse(context, input).map(Some)  // tail call
    }
}
```

```{rust,ignore}
// [ <length> | <percentage> ] [ <length> | <percentage> ]?
fn parse_border_spacing(_context: &ParserContext, input: &mut Parser)
                          -> Result<(LengthOrPercentage, LengthOrPercentage), ()> {
    let first = try!(LengthOrPercentage::parse);
    let second = input.try(LengthOrPercentage::parse).unwrap_or(first);
    (first, second)
}
```

*/

extern crate encoding;
extern crate text_writer;
#[macro_use] extern crate matches;
#[cfg(test)] extern crate test;
#[cfg(test)] extern crate "rustc-serialize" as serialize;

pub use tokenizer::{Token, NumericValue, PercentageValue, SourceLocation};
pub use rules_and_declarations::{parse_important};
pub use rules_and_declarations::{DeclarationParser, DeclarationListParser, parse_one_declaration};
pub use rules_and_declarations::{RuleListParser, parse_one_rule};
pub use rules_and_declarations::{AtRuleType, QualifiedRuleParser, AtRuleParser};
pub use from_bytes::decode_stylesheet_bytes;
pub use color::{RGBA, Color, parse_color_keyword};
pub use nth::parse_nth;
pub use serializer::{ToCss, CssStringWriter, serialize_identifier, serialize_string};
pub use parser::{Parser, Delimiter, Delimiters, SourcePosition};

/**

This macro is equivalent to a `match` expression on an `&str` value,
but matching is case-insensitive in the ASCII range.

Usage example:

```{rust,ignore}
match_ignore_ascii_case! { string,
    "foo" => Some(Foo),
    "bar" => Some(Bar),
    "baz" => Some(Baz)
    _ => None
}
```

The macro also calls `.as_slice()` on the value,
so that a `String` or `CowString` could be passed directly instead of a `&str`.

Note that because of `macro_rules` ambiguity resolutions quirks,
each arm except the fallback and the one before it must end with a comma.

*/
#[macro_export]
macro_rules! match_ignore_ascii_case {
    ( $value: expr, $( $string: expr => $result: expr ),+ _ => $fallback: expr ) => {
        {
            use std::ascii::AsciiExt;
            match $value.as_slice() {
                $(
                    s if s.eq_ignore_ascii_case($string) => $result,
                )+
                _ => $fallback
            }
        }
    };
}

mod rules_and_declarations;
mod tokenizer;
mod parser;
mod from_bytes;
mod color;
mod nth;
mod serializer;

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>//! This crate allows you to specify an offset for reads and writes, without changing the current
//! position in a file. This is similar to [`pread()` and `pwrite()`][pread] in C.
//!
//! The major advantages of this type of I/O are:
//!
//! * You don't need to seek before doing a random-access read or write, which is convenient.
//! * Reads don't modify the file at all, so don't require mutability.
//!
//! [pread]: http://man7.org/linux/man-pages/man2/pread.2.html
//!
//! # Examples
//!
//! Read the fifth 512-byte sector of a file:
//!
//! ```no_run
//! # use std::io;
//! use std::fs::File;
//! use positioned_io::ReadAt;
//!
//! # fn foo() -> io::Result<()> {
//! // Note that file does not need to be mut!
//! let file = File::open("foo.data")?;
//! let mut buf = vec![0; 512];
//! let bytes_read = file.read_at(2048, &mut buf)?;
//! # Ok(())
//! # }
//! ```
//!
//! Write an integer to the middle of a file:
//!
//! ```no_run
//! # extern crate positioned_io;
//! # extern crate byteorder;
//! # use std::io;
//! use std::fs::OpenOptions;
//! use positioned_io::WriteAt;
//! use byteorder::{ByteOrder, LittleEndian};
//!
//! # fn foo() -> io::Result<()> {
//! // Put the integer in a buffer.
//! let mut buf = vec![0; 4];
//! LittleEndian::write_u32(&mut buf, 1234);
//!
//! // Write it to the file.
//! let mut file = OpenOptions::new().write(true).open("foo.data")?;
//! file.write_all_at(1 << 20, &buf)?;
//! # Ok(())
//! # }
//! # fn main() { foo().unwrap() }
//! ```
//!
//! Or, more simply:
//!
//! ```no_run
//! # extern crate positioned_io;
//! # extern crate byteorder;
//! # use std::io;
//! # use std::fs::OpenOptions;
//! # use byteorder::LittleEndian;
//! // Extend files with writing integers at offsets.
//! use positioned_io::WriteBytesAtExt;
//!
//! # fn foo() -> io::Result<()> {
//! let mut file = OpenOptions::new().write(true).open("foo.data")?;
//! file.write_u32_at::<LittleEndian>(1 << 20, 1234)?;
//! # Ok(())
//! # }
//! # fn main() { foo().unwrap() }
//! ```
//!
//! Read from anything else that supports ReadAt, like a byte array:
//!
//! ```rust
//! # extern crate positioned_io;
//! # extern crate byteorder;
//! # use std::io;
//! # use byteorder::BigEndian;
//! use positioned_io::ReadBytesAtExt;
//!
//! # fn foo() -> io::Result<()> {
//! let buf = [0, 5, 254, 212, 0, 3];
//! let n = buf.as_ref().read_i16_at::<BigEndian>(2)?;
//! assert_eq!(n, -300);
//! # Ok(())
//! # }
//! # fn main() { foo().unwrap() }
//! ```

#![doc(html_root_url = "https://docs.rs/positioned-io/0.2.2")]

#![warn(missing_debug_implementations)]
#![warn(bare_trait_objects)]

extern crate byteorder;

mod cursor;
pub use cursor::{Cursor, SizeCursor};

mod slice;
pub use slice::Slice;

mod byteio;
pub use byteio::{ByteIo, ReadBytesAtExt, WriteBytesAtExt};

use std::fs::File;
use std::io;

/// Trait for reading bytes at an offset.
///
/// Implementations should be able to read bytes without changing any sort of
/// read position. Self should not change at all. Buffering reads is unlikely
/// to be useful, since each time `read_at()` is called, the position may be
/// completely different.
///
/// # Examples
///
/// Read the fifth 512-byte sector of a file:
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use std::fs::File;
/// use positioned_io::ReadAt;
///
/// // note that file does not need to be mut
/// let file = File::open("tests/pi.txt")?;
/// let mut buf = [0; 512];
///
/// // read up to 512 bytes
/// let bytes_read = file.read_at(2048, &mut buf)?;
/// #     assert!(buf.starts_with(b"4"));
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
/// ```
pub trait ReadAt {
    /// Reads bytes from an offset in this source into a buffer, returning how
    /// many bytes were read.
    ///
    /// This function may yield fewer bytes than the size of `buf`, if it was
    /// interrupted or hit the "end of file".
    ///
    /// See [`Read::read()`](https://doc.rust-lang.org/std/io/trait.Read.html#tymethod.read)
    /// for details.
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize>;

    /// Reads the exact number of bytes required to fill `buf` from an offset.
    ///
    /// Errors if the "end of file" is encountered before filling the buffer.
    ///
    /// See [`Read::read_exact()`](https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact)
    /// for details.
    fn read_exact_at(&self, mut pos: u64, mut buf: &mut [u8]) -> io::Result<()> {
        while !buf.is_empty() {
            match self.read_at(pos, buf) {
                Ok(0) => break,
                Ok(n) => {
                    let tmp = buf;
                    buf = &mut tmp[n..];
                    pos += n as u64;
                }
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        if !buf.is_empty() {
            Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
        } else {
            Ok(())
        }
    }
}

/// Trait for writing bytes at an offset.
///
/// Implementations should be able to write bytes at an offset, without
/// changing any sort of write position. Self should not change at all.
///
/// When writing beyond the end of the underlying object it is extended and
/// intermediate bytes are filled with the value 0.
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use std::fs::OpenOptions;
/// use positioned_io::WriteAt;
///
/// let mut file = OpenOptions::new().write(true).open("tests/pi.txt")?;
///
/// // write some bytes
/// let bytes_written = file.write_at(2, b"1415926535897932384626433")?;
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
/// ```
pub trait WriteAt {
    /// Writes bytes from a buffer to an offset, returning the number of bytes
    /// written.
    ///
    /// This function may write fewer bytes than the size of `buf`, for example
    /// if it is interrupted.
    ///
    /// See [`Write::write()`](https://doc.rust-lang.org/std/io/trait.Write.html#tymethod.write)
    /// for details.
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize>;

    /// Writes a complete buffer at an offset.
    ///
    /// Errors if it could not write the entire buffer.
    ///
    /// See [`Write::write_all()`](https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all)
    /// for details.
    fn write_all_at(&mut self, mut pos: u64, mut buf: &[u8]) -> io::Result<()> {
        while !buf.is_empty() {
            match self.write_at(pos, buf) {
                Ok(0) => break,
                Ok(n) => {
                    let tmp = buf;
                    buf = &tmp[n..];
                    pos += n as u64;
                }
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }

    /// Flush this writer, ensuring that any intermediately buffered data
    /// reaches its destination.
    ///
    /// This should rarely do anything, since buffering is not very useful for
    /// positioned writes.
    fn flush(&mut self) -> io::Result<()>;
}

/// Trait to get the size in bytes of an I/O object.
///
/// Implementing this for a types with `ReadAt` or `WriteAt` makes it easier
/// for users to predict whether they will read past end-of-file. However, it
/// may not be possible to implement for certain readers or writers that have
/// unknown size.
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use std::fs::File;
/// use positioned_io::Size;
///
/// let file = File::open("tests/pi.txt")?;
/// let size = file.size()?;
/// assert_eq!(size, Some(1000002));
///
/// // some special files do not have a known size
/// let file = File::open("/dev/stdin")?;
/// let size = file.size()?;
/// assert_eq!(size, None);
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #    try_main().unwrap();
/// # }
/// ```
pub trait Size {
    /// Get the size of this object, in bytes.
    ///
    /// This function may return `Ok(None)` if the size is unknown, for example
    /// for pipes.
    fn size(&self) -> io::Result<Option<u64>>;
}

impl Size for File {
    fn size(&self) -> io::Result<Option<u64>> {
        let md = self.metadata()?;
        if md.is_file() {
            Ok(Some(md.len()))
        } else {
            Ok(None)
        }
    }
}

// Implementation for Unix files.
#[cfg(unix)]
mod unix;

// Implementation for Windows files.
#[cfg(windows)]
mod windows;

// Implementation for arrays, vectors.
mod array;
mod vec;
mod refs;

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

    struct _AssertObjectSafe1(Box<dyn ReadAt>);
    struct _AssertObjectSafe2(Box<dyn WriteAt>);
    struct _AssertObjectSafe3(Box<dyn Size>);
}
<commit_msg>clarify WriteAt::flush<commit_after>//! This crate allows you to specify an offset for reads and writes, without changing the current
//! position in a file. This is similar to [`pread()` and `pwrite()`][pread] in C.
//!
//! The major advantages of this type of I/O are:
//!
//! * You don't need to seek before doing a random-access read or write, which is convenient.
//! * Reads don't modify the file at all, so don't require mutability.
//!
//! [pread]: http://man7.org/linux/man-pages/man2/pread.2.html
//!
//! # Examples
//!
//! Read the fifth 512-byte sector of a file:
//!
//! ```no_run
//! # use std::io;
//! use std::fs::File;
//! use positioned_io::ReadAt;
//!
//! # fn foo() -> io::Result<()> {
//! // Note that file does not need to be mut!
//! let file = File::open("foo.data")?;
//! let mut buf = vec![0; 512];
//! let bytes_read = file.read_at(2048, &mut buf)?;
//! # Ok(())
//! # }
//! ```
//!
//! Write an integer to the middle of a file:
//!
//! ```no_run
//! # extern crate positioned_io;
//! # extern crate byteorder;
//! # use std::io;
//! use std::fs::OpenOptions;
//! use positioned_io::WriteAt;
//! use byteorder::{ByteOrder, LittleEndian};
//!
//! # fn foo() -> io::Result<()> {
//! // Put the integer in a buffer.
//! let mut buf = vec![0; 4];
//! LittleEndian::write_u32(&mut buf, 1234);
//!
//! // Write it to the file.
//! let mut file = OpenOptions::new().write(true).open("foo.data")?;
//! file.write_all_at(1 << 20, &buf)?;
//! # Ok(())
//! # }
//! # fn main() { foo().unwrap() }
//! ```
//!
//! Or, more simply:
//!
//! ```no_run
//! # extern crate positioned_io;
//! # extern crate byteorder;
//! # use std::io;
//! # use std::fs::OpenOptions;
//! # use byteorder::LittleEndian;
//! // Extend files with writing integers at offsets.
//! use positioned_io::WriteBytesAtExt;
//!
//! # fn foo() -> io::Result<()> {
//! let mut file = OpenOptions::new().write(true).open("foo.data")?;
//! file.write_u32_at::<LittleEndian>(1 << 20, 1234)?;
//! # Ok(())
//! # }
//! # fn main() { foo().unwrap() }
//! ```
//!
//! Read from anything else that supports ReadAt, like a byte array:
//!
//! ```rust
//! # extern crate positioned_io;
//! # extern crate byteorder;
//! # use std::io;
//! # use byteorder::BigEndian;
//! use positioned_io::ReadBytesAtExt;
//!
//! # fn foo() -> io::Result<()> {
//! let buf = [0, 5, 254, 212, 0, 3];
//! let n = buf.as_ref().read_i16_at::<BigEndian>(2)?;
//! assert_eq!(n, -300);
//! # Ok(())
//! # }
//! # fn main() { foo().unwrap() }
//! ```

#![doc(html_root_url = "https://docs.rs/positioned-io/0.2.2")]

#![warn(missing_debug_implementations)]
#![warn(bare_trait_objects)]

extern crate byteorder;

mod cursor;
pub use cursor::{Cursor, SizeCursor};

mod slice;
pub use slice::Slice;

mod byteio;
pub use byteio::{ByteIo, ReadBytesAtExt, WriteBytesAtExt};

use std::fs::File;
use std::io;

/// Trait for reading bytes at an offset.
///
/// Implementations should be able to read bytes without changing any sort of
/// read position. Self should not change at all. Buffering reads is unlikely
/// to be useful, since each time `read_at()` is called, the position may be
/// completely different.
///
/// # Examples
///
/// Read the fifth 512-byte sector of a file:
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use std::fs::File;
/// use positioned_io::ReadAt;
///
/// // note that file does not need to be mut
/// let file = File::open("tests/pi.txt")?;
/// let mut buf = [0; 512];
///
/// // read up to 512 bytes
/// let bytes_read = file.read_at(2048, &mut buf)?;
/// #     assert!(buf.starts_with(b"4"));
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
/// ```
pub trait ReadAt {
    /// Reads bytes from an offset in this source into a buffer, returning how
    /// many bytes were read.
    ///
    /// This function may yield fewer bytes than the size of `buf`, if it was
    /// interrupted or hit the "end of file".
    ///
    /// See [`Read::read()`](https://doc.rust-lang.org/std/io/trait.Read.html#tymethod.read)
    /// for details.
    fn read_at(&self, pos: u64, buf: &mut [u8]) -> io::Result<usize>;

    /// Reads the exact number of bytes required to fill `buf` from an offset.
    ///
    /// Errors if the "end of file" is encountered before filling the buffer.
    ///
    /// See [`Read::read_exact()`](https://doc.rust-lang.org/std/io/trait.Read.html#method.read_exact)
    /// for details.
    fn read_exact_at(&self, mut pos: u64, mut buf: &mut [u8]) -> io::Result<()> {
        while !buf.is_empty() {
            match self.read_at(pos, buf) {
                Ok(0) => break,
                Ok(n) => {
                    let tmp = buf;
                    buf = &mut tmp[n..];
                    pos += n as u64;
                }
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        if !buf.is_empty() {
            Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
        } else {
            Ok(())
        }
    }
}

/// Trait for writing bytes at an offset.
///
/// Implementations should be able to write bytes at an offset, without
/// changing any sort of write position. Self should not change at all.
///
/// When writing beyond the end of the underlying object it is extended and
/// intermediate bytes are filled with the value 0.
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use std::fs::OpenOptions;
/// use positioned_io::WriteAt;
///
/// let mut file = OpenOptions::new().write(true).open("tests/pi.txt")?;
///
/// // write some bytes
/// let bytes_written = file.write_at(2, b"1415926535897932384626433")?;
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #     try_main().unwrap();
/// # }
/// ```
pub trait WriteAt {
    /// Writes bytes from a buffer to an offset, returning the number of bytes
    /// written.
    ///
    /// This function may write fewer bytes than the size of `buf`, for example
    /// if it is interrupted.
    ///
    /// See [`Write::write()`](https://doc.rust-lang.org/std/io/trait.Write.html#tymethod.write)
    /// for details.
    fn write_at(&mut self, pos: u64, buf: &[u8]) -> io::Result<usize>;

    /// Writes a complete buffer at an offset.
    ///
    /// Errors if it could not write the entire buffer.
    ///
    /// See [`Write::write_all()`](https://doc.rust-lang.org/std/io/trait.Write.html#method.write_all)
    /// for details.
    fn write_all_at(&mut self, mut pos: u64, mut buf: &[u8]) -> io::Result<()> {
        while !buf.is_empty() {
            match self.write_at(pos, buf) {
                Ok(0) => break,
                Ok(n) => {
                    let tmp = buf;
                    buf = &tmp[n..];
                    pos += n as u64;
                }
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                Err(e) => return Err(e),
            }
        }
        Ok(())
    }

    /// Flush this writer, ensuring that any intermediately buffered data
    /// reaches its destination.
    ///
    /// This should rarely do anything, since buffering is not very useful for
    /// positioned writes.
    ///
    /// This should be equivalent to
    /// [`Write::flush()`](https://doc.rust-lang.org/std/io/trait.Write.html#tymethod.flush),
    /// so it does not actually sync changes to disk when writing a `File`.
    /// Use
    /// [`File::sync_data()`](https://doc.rust-lang.org/std/fs/struct.File.html#method.sync_data)
    /// instead.
    fn flush(&mut self) -> io::Result<()>;
}

/// Trait to get the size in bytes of an I/O object.
///
/// Implementing this for a types with `ReadAt` or `WriteAt` makes it easier
/// for users to predict whether they will read past end-of-file. However, it
/// may not be possible to implement for certain readers or writers that have
/// unknown size.
///
/// # Examples
///
/// ```
/// # use std::error::Error;
/// #
/// # fn try_main() -> Result<(), Box<Error>> {
/// use std::fs::File;
/// use positioned_io::Size;
///
/// let file = File::open("tests/pi.txt")?;
/// let size = file.size()?;
/// assert_eq!(size, Some(1000002));
///
/// // some special files do not have a known size
/// let file = File::open("/dev/stdin")?;
/// let size = file.size()?;
/// assert_eq!(size, None);
/// #     Ok(())
/// # }
/// #
/// # fn main() {
/// #    try_main().unwrap();
/// # }
/// ```
pub trait Size {
    /// Get the size of this object, in bytes.
    ///
    /// This function may return `Ok(None)` if the size is unknown, for example
    /// for pipes.
    fn size(&self) -> io::Result<Option<u64>>;
}

impl Size for File {
    fn size(&self) -> io::Result<Option<u64>> {
        let md = self.metadata()?;
        if md.is_file() {
            Ok(Some(md.len()))
        } else {
            Ok(None)
        }
    }
}

// Implementation for Unix files.
#[cfg(unix)]
mod unix;

// Implementation for Windows files.
#[cfg(windows)]
mod windows;

// Implementation for arrays, vectors.
mod array;
mod vec;
mod refs;

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

    struct _AssertObjectSafe1(Box<dyn ReadAt>);
    struct _AssertObjectSafe2(Box<dyn WriteAt>);
    struct _AssertObjectSafe3(Box<dyn Size>);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#![feature(slicing_syntax)]

static PI: [u8; 722] = [
  3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3,
  8, 3, 2, 7, 9, 5, 0, 2, 8, 8, 4, 1, 9, 7, 1, 6, 9, 3, 9, 9, 3, 7, 5, 1, 0, 5,
  8, 2, 0, 9, 7, 4, 9, 4, 4, 5, 9, 2, 3, 0, 7, 8, 1, 6, 4, 0, 6, 2, 8, 6, 2, 0,
  8, 9, 9, 8, 6, 2, 8, 0, 3, 4, 8, 2, 5, 3, 4, 2, 1, 1, 7, 0, 6, 7, 9, 8, 2, 1,
  4, 8, 0, 8, 6, 5, 1, 3, 2, 8, 2, 3, 0, 6, 6, 4, 7, 0, 9, 3, 8, 4, 4, 6, 0, 9,
  5, 5, 0, 5, 8, 2, 2, 3, 1, 7, 2, 5, 3, 5, 9, 4, 0, 8, 1, 2, 8, 4, 8, 1, 1, 1,
  7, 4, 5, 0, 2, 8, 4, 1, 0, 2, 7, 0, 1, 9, 3, 8, 5, 2, 1, 1, 0, 5, 5, 5, 9, 6,
  4, 4, 6, 2, 2, 9, 4, 8, 9, 5, 4, 9, 3, 0, 3, 8, 1, 9, 6, 4, 4, 2, 8, 8, 1, 0,
  9, 7, 5, 6, 6, 5, 9, 3, 3, 4, 4, 6, 1, 2, 8, 4, 7, 5, 6, 4, 8, 2, 3, 3, 7, 8,
  6, 7, 8, 3, 1, 6, 5, 2, 7, 1, 2, 0, 1, 9, 0, 9, 1, 4, 5, 6, 4, 8, 5, 6, 6, 9,
  2, 3, 4, 6, 0, 3, 4, 8, 6, 1, 0, 4, 5, 4, 3, 2, 6, 6, 4, 8, 2, 1, 3, 3, 9, 3,
  6, 0, 7, 2, 6, 0, 2, 4, 9, 1, 4, 1, 2, 7, 3, 7, 2, 4, 5, 8, 7, 0, 0, 6, 6, 0,
  6, 3, 1, 5, 5, 8, 8, 1, 7, 4, 8, 8, 1, 5, 2, 0, 9, 2, 0, 9, 6, 2, 8, 2, 9, 2,
  5, 4, 0, 9, 1, 7, 1, 5, 3, 6, 4, 3, 6, 7, 8, 9, 2, 5, 9, 0, 3, 6, 0, 0, 1, 1,
  3, 3, 0, 5, 3, 0, 5, 4, 8, 8, 2, 0, 4, 6, 6, 5, 2, 1, 3, 8, 4, 1, 4, 6, 9, 5,
  1, 9, 4, 1, 5, 1, 1, 6, 0, 9, 4, 3, 3, 0, 5, 7, 2, 7, 0, 3, 6, 5, 7, 5, 9, 5,
  9, 1, 9, 5, 3, 0, 9, 2, 1, 8, 6, 1, 1, 7, 3, 8, 1, 9, 3, 2, 6, 1, 1, 7, 9, 3,
  1, 0, 5, 1, 1, 8, 5, 4, 8, 0, 7, 4, 4, 6, 2, 3, 7, 9, 9, 6, 2, 7, 4, 9, 5, 6,
  7, 3, 5, 1, 8, 8, 5, 7, 5, 2, 7, 2, 4, 8, 9, 1, 2, 2, 7, 9, 3, 8, 1, 8, 3, 0,
  1, 1, 9, 4, 9, 1, 2, 9, 8, 3, 3, 6, 7, 3, 3, 6, 2, 4, 4, 0, 6, 5, 6, 6, 4, 3,
  0, 8, 6, 0, 2, 1, 3, 9, 4, 9, 4, 6, 3, 9, 5, 2, 2, 4, 7, 3, 7, 1, 9, 0, 7, 0,
  2, 1, 7, 9, 8, 6, 0, 9, 4, 3, 7, 0, 2, 7, 7, 0, 5, 3, 9, 2, 1, 7, 1, 7, 6, 2,
  9, 3, 1, 7, 6, 7, 5, 2, 3, 8, 4, 6, 7, 4, 8, 1, 8, 4, 6, 7, 6, 6, 9, 4, 0, 5,
  1, 3, 2, 0, 0, 0, 5, 6, 8, 1, 2, 7, 1, 4, 5, 2, 6, 3, 5, 6, 0, 8, 2, 7, 7, 8,
  5, 7, 7, 1, 3, 4, 2, 7, 5, 7, 7, 8, 9, 6, 0, 9, 1, 7, 3, 6, 3, 7, 1, 7, 8, 7,
  2, 1, 4, 6, 8, 4, 4, 0, 9, 0, 1, 2, 2, 4, 9, 5, 3, 4, 3, 0, 1, 4, 6, 5, 4, 9,
  5, 8, 5, 3, 7, 1, 0, 5, 0, 7, 9, 2, 2, 7, 9, 6, 8, 9, 2, 5, 8, 9, 2, 3, 5, 4,
  2, 0, 1, 9, 9, 5, 6, 1, 1, 2, 1, 2, 9, 0, 2, 1, 9, 6, 0, 8
];

struct Rand {
  idx: usize
}

impl Rand {
  pub fn new() -> Rand {
    Rand { idx: 0 }
  }

  fn next_digit(&mut self) -> usize {
    self.idx += 1;
    PI[self.idx - 1] as usize
  }

  pub fn next(&mut self, n: usize) -> usize {
    let mut x = self.next_digit();
    let mut y = 10us;

    if n > 10 {
      x = (x * 10) + self.next_digit();
      y = 100;
    }

    if n > 100 {
      x = (x * 10) + self.next_digit();
      y = 1000;
    }

    // Repeat if the value found is too large.
    if x < (n * (y / n)) { x % n } else { self.next(n) }
  }
}

pub fn compute() -> [u8; 256] {
  let mut state = [0u8; 256];

  // Initialize state to [0, 1, 2, .., 255].
  for i in 1..256 {
    state[i] = i as u8;
  }

  let mut r = Rand::new();

  // Perform "random" swaps.
  for i in 2..257 {
    state.swap(i - 1, r.next(i));
  }

  state
}

#[cfg(test)]
mod test {
  use compute;

  // S-box as given in RFC 1319.
  static SBOX: [u8; 256] = [
    0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, 0x3d, 0x36, 0x54, 0xa1,
    0xec, 0xf0, 0x06, 0x13, 0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c,
    0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca, 0x1e, 0x9b, 0x57, 0x3c,
    0xfd, 0xd4, 0xe0, 0x16, 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,
    0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, 0xa0, 0xfb, 0xf5, 0x8e,
    0xbb, 0x2f, 0xee, 0x7a, 0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f,
    0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21, 0x80, 0x7f, 0x5d, 0x9a,
    0x5a, 0x90, 0x32, 0x27, 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03,
    0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, 0xd7, 0x5e, 0x92, 0x2a,
    0xac, 0x56, 0xaa, 0xc6, 0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6,
    0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1, 0x45, 0x9d, 0x70, 0x59,
    0x64, 0x71, 0x87, 0x20, 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02,
    0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, 0x1c, 0x46, 0x61, 0x69,
    0x34, 0x40, 0x7e, 0x0f, 0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a,
    0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26, 0x2c, 0x53, 0x0d, 0x6e,
    0x85, 0x28, 0x84, 0x09, 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52,
    0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, 0x24, 0xe1, 0x7b, 0x08,
    0x0c, 0xbd, 0xb1, 0x4a, 0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d,
    0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39, 0xf2, 0xef, 0xb7, 0x0e,
    0x66, 0x58, 0xd0, 0xe4, 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a,
    0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, 0xdb, 0x99, 0x8d, 0x33,
    0x9f, 0x11, 0x83, 0x14
  ];

  #[test]
  fn test() {
    assert_eq!(SBOX.to_vec(), compute().to_vec());
  }
}
<commit_msg>rust 1.0 changes<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

static PI: [u8; 722] = [
  3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 8, 9, 7, 9, 3, 2, 3, 8, 4, 6, 2, 6, 4, 3, 3,
  8, 3, 2, 7, 9, 5, 0, 2, 8, 8, 4, 1, 9, 7, 1, 6, 9, 3, 9, 9, 3, 7, 5, 1, 0, 5,
  8, 2, 0, 9, 7, 4, 9, 4, 4, 5, 9, 2, 3, 0, 7, 8, 1, 6, 4, 0, 6, 2, 8, 6, 2, 0,
  8, 9, 9, 8, 6, 2, 8, 0, 3, 4, 8, 2, 5, 3, 4, 2, 1, 1, 7, 0, 6, 7, 9, 8, 2, 1,
  4, 8, 0, 8, 6, 5, 1, 3, 2, 8, 2, 3, 0, 6, 6, 4, 7, 0, 9, 3, 8, 4, 4, 6, 0, 9,
  5, 5, 0, 5, 8, 2, 2, 3, 1, 7, 2, 5, 3, 5, 9, 4, 0, 8, 1, 2, 8, 4, 8, 1, 1, 1,
  7, 4, 5, 0, 2, 8, 4, 1, 0, 2, 7, 0, 1, 9, 3, 8, 5, 2, 1, 1, 0, 5, 5, 5, 9, 6,
  4, 4, 6, 2, 2, 9, 4, 8, 9, 5, 4, 9, 3, 0, 3, 8, 1, 9, 6, 4, 4, 2, 8, 8, 1, 0,
  9, 7, 5, 6, 6, 5, 9, 3, 3, 4, 4, 6, 1, 2, 8, 4, 7, 5, 6, 4, 8, 2, 3, 3, 7, 8,
  6, 7, 8, 3, 1, 6, 5, 2, 7, 1, 2, 0, 1, 9, 0, 9, 1, 4, 5, 6, 4, 8, 5, 6, 6, 9,
  2, 3, 4, 6, 0, 3, 4, 8, 6, 1, 0, 4, 5, 4, 3, 2, 6, 6, 4, 8, 2, 1, 3, 3, 9, 3,
  6, 0, 7, 2, 6, 0, 2, 4, 9, 1, 4, 1, 2, 7, 3, 7, 2, 4, 5, 8, 7, 0, 0, 6, 6, 0,
  6, 3, 1, 5, 5, 8, 8, 1, 7, 4, 8, 8, 1, 5, 2, 0, 9, 2, 0, 9, 6, 2, 8, 2, 9, 2,
  5, 4, 0, 9, 1, 7, 1, 5, 3, 6, 4, 3, 6, 7, 8, 9, 2, 5, 9, 0, 3, 6, 0, 0, 1, 1,
  3, 3, 0, 5, 3, 0, 5, 4, 8, 8, 2, 0, 4, 6, 6, 5, 2, 1, 3, 8, 4, 1, 4, 6, 9, 5,
  1, 9, 4, 1, 5, 1, 1, 6, 0, 9, 4, 3, 3, 0, 5, 7, 2, 7, 0, 3, 6, 5, 7, 5, 9, 5,
  9, 1, 9, 5, 3, 0, 9, 2, 1, 8, 6, 1, 1, 7, 3, 8, 1, 9, 3, 2, 6, 1, 1, 7, 9, 3,
  1, 0, 5, 1, 1, 8, 5, 4, 8, 0, 7, 4, 4, 6, 2, 3, 7, 9, 9, 6, 2, 7, 4, 9, 5, 6,
  7, 3, 5, 1, 8, 8, 5, 7, 5, 2, 7, 2, 4, 8, 9, 1, 2, 2, 7, 9, 3, 8, 1, 8, 3, 0,
  1, 1, 9, 4, 9, 1, 2, 9, 8, 3, 3, 6, 7, 3, 3, 6, 2, 4, 4, 0, 6, 5, 6, 6, 4, 3,
  0, 8, 6, 0, 2, 1, 3, 9, 4, 9, 4, 6, 3, 9, 5, 2, 2, 4, 7, 3, 7, 1, 9, 0, 7, 0,
  2, 1, 7, 9, 8, 6, 0, 9, 4, 3, 7, 0, 2, 7, 7, 0, 5, 3, 9, 2, 1, 7, 1, 7, 6, 2,
  9, 3, 1, 7, 6, 7, 5, 2, 3, 8, 4, 6, 7, 4, 8, 1, 8, 4, 6, 7, 6, 6, 9, 4, 0, 5,
  1, 3, 2, 0, 0, 0, 5, 6, 8, 1, 2, 7, 1, 4, 5, 2, 6, 3, 5, 6, 0, 8, 2, 7, 7, 8,
  5, 7, 7, 1, 3, 4, 2, 7, 5, 7, 7, 8, 9, 6, 0, 9, 1, 7, 3, 6, 3, 7, 1, 7, 8, 7,
  2, 1, 4, 6, 8, 4, 4, 0, 9, 0, 1, 2, 2, 4, 9, 5, 3, 4, 3, 0, 1, 4, 6, 5, 4, 9,
  5, 8, 5, 3, 7, 1, 0, 5, 0, 7, 9, 2, 2, 7, 9, 6, 8, 9, 2, 5, 8, 9, 2, 3, 5, 4,
  2, 0, 1, 9, 9, 5, 6, 1, 1, 2, 1, 2, 9, 0, 2, 1, 9, 6, 0, 8
];

struct Rand {
  idx: usize
}

impl Rand {
  pub fn new() -> Rand {
    Rand { idx: 0 }
  }

  fn next_digit(&mut self) -> usize {
    self.idx += 1;
    PI[self.idx - 1] as usize
  }

  pub fn next(&mut self, n: usize) -> usize {
    let mut x = self.next_digit();
    let mut y = 10usize;

    if n > 10 {
      x = (x * 10) + self.next_digit();
      y = 100;
    }

    if n > 100 {
      x = (x * 10) + self.next_digit();
      y = 1000;
    }

    // Repeat if the value found is too large.
    if x < (n * (y / n)) { x % n } else { self.next(n) }
  }
}

pub fn compute() -> [u8; 256] {
  let mut state = [0u8; 256];

  // Initialize state to [0, 1, 2, .., 255].
  for i in 1..256 {
    state[i] = i as u8;
  }

  let mut r = Rand::new();

  // Perform "random" swaps.
  for i in 2..257 {
    state.swap(i - 1, r.next(i));
  }

  state
}

#[cfg(test)]
mod test {
  use compute;

  // S-box as given in RFC 1319.
  static SBOX: [u8; 256] = [
    0x29, 0x2e, 0x43, 0xc9, 0xa2, 0xd8, 0x7c, 0x01, 0x3d, 0x36, 0x54, 0xa1,
    0xec, 0xf0, 0x06, 0x13, 0x62, 0xa7, 0x05, 0xf3, 0xc0, 0xc7, 0x73, 0x8c,
    0x98, 0x93, 0x2b, 0xd9, 0xbc, 0x4c, 0x82, 0xca, 0x1e, 0x9b, 0x57, 0x3c,
    0xfd, 0xd4, 0xe0, 0x16, 0x67, 0x42, 0x6f, 0x18, 0x8a, 0x17, 0xe5, 0x12,
    0xbe, 0x4e, 0xc4, 0xd6, 0xda, 0x9e, 0xde, 0x49, 0xa0, 0xfb, 0xf5, 0x8e,
    0xbb, 0x2f, 0xee, 0x7a, 0xa9, 0x68, 0x79, 0x91, 0x15, 0xb2, 0x07, 0x3f,
    0x94, 0xc2, 0x10, 0x89, 0x0b, 0x22, 0x5f, 0x21, 0x80, 0x7f, 0x5d, 0x9a,
    0x5a, 0x90, 0x32, 0x27, 0x35, 0x3e, 0xcc, 0xe7, 0xbf, 0xf7, 0x97, 0x03,
    0xff, 0x19, 0x30, 0xb3, 0x48, 0xa5, 0xb5, 0xd1, 0xd7, 0x5e, 0x92, 0x2a,
    0xac, 0x56, 0xaa, 0xc6, 0x4f, 0xb8, 0x38, 0xd2, 0x96, 0xa4, 0x7d, 0xb6,
    0x76, 0xfc, 0x6b, 0xe2, 0x9c, 0x74, 0x04, 0xf1, 0x45, 0x9d, 0x70, 0x59,
    0x64, 0x71, 0x87, 0x20, 0x86, 0x5b, 0xcf, 0x65, 0xe6, 0x2d, 0xa8, 0x02,
    0x1b, 0x60, 0x25, 0xad, 0xae, 0xb0, 0xb9, 0xf6, 0x1c, 0x46, 0x61, 0x69,
    0x34, 0x40, 0x7e, 0x0f, 0x55, 0x47, 0xa3, 0x23, 0xdd, 0x51, 0xaf, 0x3a,
    0xc3, 0x5c, 0xf9, 0xce, 0xba, 0xc5, 0xea, 0x26, 0x2c, 0x53, 0x0d, 0x6e,
    0x85, 0x28, 0x84, 0x09, 0xd3, 0xdf, 0xcd, 0xf4, 0x41, 0x81, 0x4d, 0x52,
    0x6a, 0xdc, 0x37, 0xc8, 0x6c, 0xc1, 0xab, 0xfa, 0x24, 0xe1, 0x7b, 0x08,
    0x0c, 0xbd, 0xb1, 0x4a, 0x78, 0x88, 0x95, 0x8b, 0xe3, 0x63, 0xe8, 0x6d,
    0xe9, 0xcb, 0xd5, 0xfe, 0x3b, 0x00, 0x1d, 0x39, 0xf2, 0xef, 0xb7, 0x0e,
    0x66, 0x58, 0xd0, 0xe4, 0xa6, 0x77, 0x72, 0xf8, 0xeb, 0x75, 0x4b, 0x0a,
    0x31, 0x44, 0x50, 0xb4, 0x8f, 0xed, 0x1f, 0x1a, 0xdb, 0x99, 0x8d, 0x33,
    0x9f, 0x11, 0x83, 0x14
  ];

  #[test]
  fn test() {
    assert_eq!(SBOX.to_vec(), compute().to_vec());
  }
}
<|endoftext|>


<commit_before>#![crate_name = "shader_version"]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]
#![feature(globs)]

//! A helper library for detecting and picking compatible shaders.

pub use opengl::OpenGL;

pub mod opengl;
pub mod glsl;

<commit_msg>Reflect removal of globs feature gate<commit_after>#![crate_name = "shader_version"]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]

//! A helper library for detecting and picking compatible shaders.

pub use opengl::OpenGL;

pub mod opengl;
pub mod glsl;

<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use futures::stream::Stream;
use lazy_static::lazy_static;
use regex::Regex;

pub struct Entity {
    pub identifier: String,
}

pub enum Object {
    Entity(Entity),
    Literal(Literal),
}

pub enum Literal {
    LangLiteral(LangLiteral),
    StringLiteral(String),
    BooleanLiteral(bool),
    LongLiteral(i64),
    DoubleLiteral(f64),
}

pub struct LangLiteral {
    pub value: String,
    pub lang_tag: String,
}

pub struct Predicate {
    pub predicate: String,
}

pub enum Range {
    LangLiteralRange(LangLiteral, LangLiteral),
    StringLiteralRange(String, String),
    LongLiteralRange(i64, i64),
    DoubleLiteralRange(f64, f64),
}

pub struct Statement {
    pub subject: Entity,
    pub predicate: Predicate,
    pub object: Object,
    pub context: Entity,
}

pub struct CollectionName {
    pub name: String,
}

pub trait LigatureStore {
    fn read_tx(&self) -> Box<dyn ReadTx>;
    fn write_tx(&self) -> Box<dyn WriteTx>;

    fn compute<F: FnOnce(&Box<dyn ReadTx>) -> T, T>(&self, fun: F) -> T {
        let read_tx = self.read_tx();
        let result = fun(&read_tx);
        if read_tx.is_open() {
            read_tx.cancel();
        }
        result
    }

    fn write<F: FnOnce(&Box<dyn WriteTx>)>(&self, fun: F) {
        let write_tx = self.write_tx();
        fun(&write_tx);
        if write_tx.is_open() {
            write_tx.commit();
        }
    }

    /**
     * Close connection with the Store.
     */
    fn close(&self);

    fn is_open(&self) -> bool;
}

pub trait ReadTx {
    /**
     * Returns a Stream of all existing collections.
     */
    fn collections(&self) -> dyn Stream<Item = CollectionName>;

    /**
     * Returns a Stream of all existing collections that start with the given prefix.
     */
    fn collections_prefix(&self, prefix: CollectionName) -> dyn Stream<Item = CollectionName>;

    /**
     * Returns a Stream of all existing collections that are within the given range.
     * `from` is inclusive and `to` is exclusive.
     */
    fn collections_range(
        &self,
        from: CollectionName,
        to: CollectionName,
    ) -> dyn Stream<Item = CollectionName>;

    /**
     * Accepts nothing but returns a Stream of all Statements in the Collection.
     */
    fn all_statements(&self, collection: CollectionName) -> dyn Stream<Item = Statement>;

    /**
     * Is passed a pattern and returns a seq with all matching Statements.
     */
    fn match_statements(
        &self,
        collection: CollectionName,
        subject: Option<Entity>,
        predicate: Option<Predicate>,
        object: Option<Object>,
        context: Option<Entity>,
    ) -> dyn Stream<Item = Statement>;

    /**
     * Is passed a pattern and returns a seq with all matching Statements.
     */
    fn match_statements_range(
        &self,
        collection: CollectionName,
        subject: Option<Entity>,
        predicate: Option<Predicate>,
        range: Option<Range>,
        context: Option<Entity>,
    ) -> dyn Stream<Item = Statement>;

    /**
     * Cancels this transaction.
     */
    fn cancel(&self);

    fn is_open(&self) -> bool;
}

pub trait WriteTx {
    /**
     * Creates a collection with the given name or does nothing if the collection already exists.
     * Only useful for creating an empty collection.
     */
    fn create_collection(&self, collection: CollectionName);

    /**
     * Deletes the collection of the name given and does nothing if the collection doesn't exist.
     */
    fn delete_collection(&self, collection: CollectionName);

    /**
     * Returns a new, unique to this collection identifier in the form _:NUMBER
     */
    fn new_entity(&self, collection: CollectionName) -> Entity;
    fn remove_entity(&self, collection: CollectionName, entity: Entity);
    fn add_statement(&self, collection: CollectionName, statement: Statement);
    fn remove_statement(&self, collection: CollectionName, statement: Statement);

    /**
     * Commits this transaction.
     */
    fn commit(&self);

    /**
     * Cancels this transaction.
     */
    fn cancel(&self);

    fn is_open(&self) -> bool;
}

/**
 * Accepts a String representing an identifier and returns true or false depending on if it is valid.
 */
pub fn valid_predicate(identifier: &str) -> bool {
    lazy_static! {
        static ref RE: Regex =
            Regex::new("^[a-zA-Z_][^\\s\\(\\)\\[\\]\\{\\}'\"`<>\\\\]*$").unwrap();
    }

    return RE.is_match(identifier);
}

/**
 * Accepts a String representing a lang tag and returns true or false depending on if it is valid.
 */
pub fn valid_lang_tag(lang_tag: &str) -> bool {
    lazy_static! {
        static ref RE: Regex = Regex::new("^[a-zA-Z]+(-[a-zA-Z0-9]+)*$").unwrap();
    }

    return RE.is_match(lang_tag);
}

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

    #[test]
    fn valid_identifier_tests() {
        assert_eq!(valid_predicate(""), false);
        assert_eq!(valid_predicate("http://localhost/people/7"), true);
        assert_eq!(valid_predicate("http://localhost(/people/7"), false);
        assert_eq!(valid_predicate("http://localhost /people/7"), false);
        assert_eq!(valid_predicate("hello"), true);
        assert_eq!(valid_predicate("_:"), true);
        assert_eq!(valid_predicate("_:valid"), true);
        assert_eq!(valid_predicate("_:1"), true);
        assert_eq!(valid_predicate("_:1344"), true);
    }

    #[test]
    fn valid_lang_tag_tests() {
        assert_eq!(valid_lang_tag(""), false);
        assert_eq!(valid_lang_tag("en"), true);
        assert_eq!(valid_lang_tag("en-"), false);
        assert_eq!(valid_lang_tag("en-fr"), true);
        assert_eq!(valid_lang_tag("en-fr-"), false);
        assert_eq!(valid_lang_tag("en-fr-sp"), true);
        assert_eq!(
            valid_lang_tag("ennnenefnk-dkfjkjfl-dfakjelfkjalkf-fakjeflkajlkfj"),
            true
        );
        assert_eq!(valid_lang_tag("en-fr-ef "), false);
    }
}
<commit_msg>removing compute and write methods<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use futures::stream::Stream;
use lazy_static::lazy_static;
use regex::Regex;

pub struct Entity {
    pub identifier: String,
}

pub enum Object {
    Entity(Entity),
    Literal(Literal),
}

pub enum Literal {
    LangLiteral(LangLiteral),
    StringLiteral(String),
    BooleanLiteral(bool),
    LongLiteral(i64),
    DoubleLiteral(f64),
}

pub struct LangLiteral {
    pub value: String,
    pub lang_tag: String,
}

pub struct Predicate {
    pub predicate: String,
}

pub enum Range {
    LangLiteralRange(LangLiteral, LangLiteral),
    StringLiteralRange(String, String),
    LongLiteralRange(i64, i64),
    DoubleLiteralRange(f64, f64),
}

pub struct Statement {
    pub subject: Entity,
    pub predicate: Predicate,
    pub object: Object,
    pub context: Entity,
}

pub struct CollectionName {
    pub name: String,
}

pub trait LigatureStore {
    fn read_tx(&self) -> Box<dyn ReadTx>;
    fn write_tx(&self) -> Box<dyn WriteTx>;

    /**
     * Close connection with the Store.
     */
    fn close(&self);

    fn is_open(&self) -> bool;
}

pub trait ReadTx {
    /**
     * Returns a Stream of all existing collections.
     */
    fn collections(&self) -> dyn Stream<Item = CollectionName>;

    /**
     * Returns a Stream of all existing collections that start with the given prefix.
     */
    fn collections_prefix(&self, prefix: CollectionName) -> dyn Stream<Item = CollectionName>;

    /**
     * Returns a Stream of all existing collections that are within the given range.
     * `from` is inclusive and `to` is exclusive.
     */
    fn collections_range(
        &self,
        from: CollectionName,
        to: CollectionName,
    ) -> dyn Stream<Item = CollectionName>;

    /**
     * Accepts nothing but returns a Stream of all Statements in the Collection.
     */
    fn all_statements(&self, collection: CollectionName) -> dyn Stream<Item = Statement>;

    /**
     * Is passed a pattern and returns a seq with all matching Statements.
     */
    fn match_statements(
        &self,
        collection: CollectionName,
        subject: Option<Entity>,
        predicate: Option<Predicate>,
        object: Option<Object>,
        context: Option<Entity>,
    ) -> dyn Stream<Item = Statement>;

    /**
     * Is passed a pattern and returns a seq with all matching Statements.
     */
    fn match_statements_range(
        &self,
        collection: CollectionName,
        subject: Option<Entity>,
        predicate: Option<Predicate>,
        range: Option<Range>,
        context: Option<Entity>,
    ) -> dyn Stream<Item = Statement>;

    /**
     * Cancels this transaction.
     */
    fn cancel(&self);

    fn is_open(&self) -> bool;
}

pub trait WriteTx {
    /**
     * Creates a collection with the given name or does nothing if the collection already exists.
     * Only useful for creating an empty collection.
     */
    fn create_collection(&self, collection: CollectionName);

    /**
     * Deletes the collection of the name given and does nothing if the collection doesn't exist.
     */
    fn delete_collection(&self, collection: CollectionName);

    /**
     * Returns a new, unique to this collection identifier in the form _:NUMBER
     */
    fn new_entity(&self, collection: CollectionName) -> Entity;
    fn remove_entity(&self, collection: CollectionName, entity: Entity);
    fn add_statement(&self, collection: CollectionName, statement: Statement);
    fn remove_statement(&self, collection: CollectionName, statement: Statement);

    /**
     * Commits this transaction.
     */
    fn commit(&self);

    /**
     * Cancels this transaction.
     */
    fn cancel(&self);

    fn is_open(&self) -> bool;
}

/**
 * Accepts a String representing an identifier and returns true or false depending on if it is valid.
 */
pub fn valid_predicate(identifier: &str) -> bool {
    lazy_static! {
        static ref RE: Regex =
            Regex::new("^[a-zA-Z_][^\\s\\(\\)\\[\\]\\{\\}'\"`<>\\\\]*$").unwrap();
    }

    return RE.is_match(identifier);
}

/**
 * Accepts a String representing a lang tag and returns true or false depending on if it is valid.
 */
pub fn valid_lang_tag(lang_tag: &str) -> bool {
    lazy_static! {
        static ref RE: Regex = Regex::new("^[a-zA-Z]+(-[a-zA-Z0-9]+)*$").unwrap();
    }

    return RE.is_match(lang_tag);
}

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

    #[test]
    fn valid_identifier_tests() {
        assert_eq!(valid_predicate(""), false);
        assert_eq!(valid_predicate("http://localhost/people/7"), true);
        assert_eq!(valid_predicate("http://localhost(/people/7"), false);
        assert_eq!(valid_predicate("http://localhost /people/7"), false);
        assert_eq!(valid_predicate("hello"), true);
        assert_eq!(valid_predicate("_:"), true);
        assert_eq!(valid_predicate("_:valid"), true);
        assert_eq!(valid_predicate("_:1"), true);
        assert_eq!(valid_predicate("_:1344"), true);
    }

    #[test]
    fn valid_lang_tag_tests() {
        assert_eq!(valid_lang_tag(""), false);
        assert_eq!(valid_lang_tag("en"), true);
        assert_eq!(valid_lang_tag("en-"), false);
        assert_eq!(valid_lang_tag("en-fr"), true);
        assert_eq!(valid_lang_tag("en-fr-"), false);
        assert_eq!(valid_lang_tag("en-fr-sp"), true);
        assert_eq!(
            valid_lang_tag("ennnenefnk-dkfjkjfl-dfakjelfkjalkf-fakjeflkajlkfj"),
            true
        );
        assert_eq!(valid_lang_tag("en-fr-ef "), false);
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs, warnings)]

//! Request logging middleware for Iron

extern crate iron;
extern crate time;
extern crate term;

use iron::{AfterMiddleware, BeforeMiddleware, IronResult, IronError, Request, Response, status};
use iron::typemap::Key;
use term::{StdoutTerminal, color, stdout};

use std::io;
use std::io::Write;

use format::FormatText::{Str, Method, URI, Status, ResponseTime};
use format::FormatColor::{ConstantColor, FunctionColor};
use format::FormatAttr::{ConstantAttrs, FunctionAttrs};
use format::{Format, FormatText};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
pub struct Logger {
    format: Option<Format>
}

impl Logger {
    /// Create a pair of `Logger` middlewares with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    ///
    /// While the returned value can be passed straight to `Chain::link`, consider making the logger `BeforeMiddleware`
    /// the first in your chain and the logger `AfterMiddleware` the last by doing something like this:
    ///
    /// ```ignore
    /// let mut chain = Chain::new(handler);
    /// let (logger_before, logger_after) = Logger::new(None);
    /// chain.link_before(logger_before);
    /// // link other middlewares here...
    /// chain.link_after(logger_after);
    /// ```
    pub fn new(format: Option<Format>) -> (Logger, Logger) {
        (Logger { format: format.clone() }, Logger { format: format })
    }
}

struct StartTime;
impl Key for StartTime { type Value = u64; }

impl Logger {
    fn initialise(&self, req: &mut Request) {
        req.extensions.insert::<StartTime>(time::precise_time_ns());
    }

    fn log(&self, req: &mut Request, res: &Response) -> IronResult<()> {
        let exit_time = time::precise_time_ns();
        let entry_time = *req.extensions.get::<StartTime>().unwrap();

        let response_time_ms = (exit_time - entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or_default();

        {
            macro_rules! tryio {
                ($expr:expr) => (match $expr {
                    std::result::Result::Ok(val) => val,
                    std::result::Result::Err(err) => {
                        return Err(IronError::new(err, status::InternalServerError))
                    }
                })
            }

            let render = |text: &FormatText| {
                match *text {
                    Str(ref string) => string.clone(),
                    Method => format!("{}", req.method),
                    URI => format!("{}", req.url),
                    Status => format!("{}", res.status.unwrap()),
                    ResponseTime => format!("{} ms", response_time_ms)
                }
            };

            let log = |w: &mut LogWriter| -> IronResult<()> {
                for unit in format.iter() {
                    let c = match unit.color {
                        ConstantColor(color) => color,
                        FunctionColor(f) => f(req, res)
                    };
                    let mut fn_attrs;
                    let ref attrs = match unit.attrs {
                        ConstantAttrs(ref attrs) => attrs,
                        FunctionAttrs(f) => {
                            fn_attrs = f(req, res);
                            &fn_attrs
                        }
                    };
                    tryio!(w.write_item(render(&unit.text), c, attrs));
                }
                tryio!(w.new_line());
                Ok(())
            };

            match stdout() {
                Some(terminal) => {
                    try!(log(&mut TermWriter::new(terminal)));
                }
                None => {
                    try!(log(&mut io::stdout()));
                }
            };
        }

        Ok(())
    }
}

trait LogWriter {
    fn write_item(&mut self, text: String, color: Option<color::Color>, attrs: &Vec<term::Attr>) -> io::Result<()>;
    fn new_line(&mut self) -> io::Result<()>;
}

struct TermWriter {
    term: Box<StdoutTerminal>
}

impl TermWriter {
    fn new(term: Box<StdoutTerminal>) -> TermWriter {
        TermWriter {
            term: term
        }
    }
}

impl LogWriter for TermWriter {
    fn write_item(&mut self, text: String, color: Option<color::Color>, attrs: &Vec<term::Attr>) -> io::Result<()> {
        match color {
            Some(c) => { try!(self.term.fg(c)); }
            None => {},
        }
        for &attr in attrs.iter() {
            try!(self.term.attr(attr));
        }
        try!(write!(self.term, "{}", text));
        try!(self.term.reset());
        Ok(())
    }

    fn new_line(&mut self) -> io::Result<()> {
        try!(writeln!(self.term, ""));
        Ok(())
    }
}

impl<T: Write> LogWriter for T {
    fn write_item(&mut self, text: String, _: Option<color::Color>, _: &Vec<term::Attr>) -> io::Result<()> {
        try!(write!(self, "{}", text));
        Ok(())
    }

    fn new_line(&mut self) -> io::Result<()> {
        try!(writeln!(self, ""));
        Ok(())
    }
}

impl BeforeMiddleware for Logger {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        self.initialise(req);
        Ok(())
    }

    fn catch(&self, req: &mut Request, err: IronError) -> IronResult<()> {
        self.initialise(req);
        Err(err)
    }
}

impl AfterMiddleware for Logger {
    fn after(&self, req: &mut Request, res: Response) -> IronResult<Response> {
        try!(self.log(req, &res));
        Ok(res)
    }

    fn catch(&self, req: &mut Request, err: IronError) -> IronResult<Response> {
        try!(self.log(req, &err.response));
        Err(err)
    }
}
<commit_msg>Fix compilation (unused_mut)<commit_after>#![deny(missing_docs, warnings)]

//! Request logging middleware for Iron

extern crate iron;
extern crate time;
extern crate term;

use iron::{AfterMiddleware, BeforeMiddleware, IronResult, IronError, Request, Response, status};
use iron::typemap::Key;
use term::{StdoutTerminal, color, stdout};

use std::io;
use std::io::Write;

use format::FormatText::{Str, Method, URI, Status, ResponseTime};
use format::FormatColor::{ConstantColor, FunctionColor};
use format::FormatAttr::{ConstantAttrs, FunctionAttrs};
use format::{Format, FormatText};

pub mod format;

/// `Middleware` for logging request and response info to the terminal.
pub struct Logger {
    format: Option<Format>
}

impl Logger {
    /// Create a pair of `Logger` middlewares with the specified `format`. If a `None` is passed in, uses the default format:
    ///
    /// ```ignore
    /// {method} {uri} -> {status} ({response_time} ms)
    /// ```
    ///
    /// While the returned value can be passed straight to `Chain::link`, consider making the logger `BeforeMiddleware`
    /// the first in your chain and the logger `AfterMiddleware` the last by doing something like this:
    ///
    /// ```ignore
    /// let mut chain = Chain::new(handler);
    /// let (logger_before, logger_after) = Logger::new(None);
    /// chain.link_before(logger_before);
    /// // link other middlewares here...
    /// chain.link_after(logger_after);
    /// ```
    pub fn new(format: Option<Format>) -> (Logger, Logger) {
        (Logger { format: format.clone() }, Logger { format: format })
    }
}

struct StartTime;
impl Key for StartTime { type Value = u64; }

impl Logger {
    fn initialise(&self, req: &mut Request) {
        req.extensions.insert::<StartTime>(time::precise_time_ns());
    }

    fn log(&self, req: &mut Request, res: &Response) -> IronResult<()> {
        let exit_time = time::precise_time_ns();
        let entry_time = *req.extensions.get::<StartTime>().unwrap();

        let response_time_ms = (exit_time - entry_time) as f64 / 1000000.0;
        let Format(format) = self.format.clone().unwrap_or_default();

        {
            macro_rules! tryio {
                ($expr:expr) => (match $expr {
                    std::result::Result::Ok(val) => val,
                    std::result::Result::Err(err) => {
                        return Err(IronError::new(err, status::InternalServerError))
                    }
                })
            }

            let render = |text: &FormatText| {
                match *text {
                    Str(ref string) => string.clone(),
                    Method => format!("{}", req.method),
                    URI => format!("{}", req.url),
                    Status => format!("{}", res.status.unwrap()),
                    ResponseTime => format!("{} ms", response_time_ms)
                }
            };

            let log = |w: &mut LogWriter| -> IronResult<()> {
                for unit in format.iter() {
                    let c = match unit.color {
                        ConstantColor(color) => color,
                        FunctionColor(f) => f(req, res)
                    };
                    let fn_attrs;
                    let ref attrs = match unit.attrs {
                        ConstantAttrs(ref attrs) => attrs,
                        FunctionAttrs(f) => {
                            fn_attrs = f(req, res);
                            &fn_attrs
                        }
                    };
                    tryio!(w.write_item(render(&unit.text), c, attrs));
                }
                tryio!(w.new_line());
                Ok(())
            };

            match stdout() {
                Some(terminal) => {
                    try!(log(&mut TermWriter::new(terminal)));
                }
                None => {
                    try!(log(&mut io::stdout()));
                }
            };
        }

        Ok(())
    }
}

trait LogWriter {
    fn write_item(&mut self, text: String, color: Option<color::Color>, attrs: &Vec<term::Attr>) -> io::Result<()>;
    fn new_line(&mut self) -> io::Result<()>;
}

struct TermWriter {
    term: Box<StdoutTerminal>
}

impl TermWriter {
    fn new(term: Box<StdoutTerminal>) -> TermWriter {
        TermWriter {
            term: term
        }
    }
}

impl LogWriter for TermWriter {
    fn write_item(&mut self, text: String, color: Option<color::Color>, attrs: &Vec<term::Attr>) -> io::Result<()> {
        match color {
            Some(c) => { try!(self.term.fg(c)); }
            None => {},
        }
        for &attr in attrs.iter() {
            try!(self.term.attr(attr));
        }
        try!(write!(self.term, "{}", text));
        try!(self.term.reset());
        Ok(())
    }

    fn new_line(&mut self) -> io::Result<()> {
        try!(writeln!(self.term, ""));
        Ok(())
    }
}

impl<T: Write> LogWriter for T {
    fn write_item(&mut self, text: String, _: Option<color::Color>, _: &Vec<term::Attr>) -> io::Result<()> {
        try!(write!(self, "{}", text));
        Ok(())
    }

    fn new_line(&mut self) -> io::Result<()> {
        try!(writeln!(self, ""));
        Ok(())
    }
}

impl BeforeMiddleware for Logger {
    fn before(&self, req: &mut Request) -> IronResult<()> {
        self.initialise(req);
        Ok(())
    }

    fn catch(&self, req: &mut Request, err: IronError) -> IronResult<()> {
        self.initialise(req);
        Err(err)
    }
}

impl AfterMiddleware for Logger {
    fn after(&self, req: &mut Request, res: Response) -> IronResult<Response> {
        try!(self.log(req, &res));
        Ok(res)
    }

    fn catch(&self, req: &mut Request, err: IronError) -> IronResult<Response> {
        try!(self.log(req, &err.response));
        Err(err)
    }
}
<|endoftext|>