<commit_before>//! The simplest possible implementation of the TimeSteward API.
//!
//! This implementation is unusably slow on large simulations. Its main use is to cross-check with other TimeSteward implementations to make sure they are implementing the API correctly.
//!
//!

use {DeterministicRandomId, ColumnId, FieldId, PredictorId, Column, ExtendedTime, StewardRc,
             Basics, FieldRc, TimeSteward, FiatEventOperationError, ValidSince, PredictorFn, TimeStewardSettings};
use std::collections::{HashMap};
// use std::collections::Bound::{Included, Excluded, Unbounded};
use std::cmp::max;
use std::marker::PhantomData;
use Snapshot as SuperSnapshot;

#[derive (Clone)]
pub struct Steward<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  Steward0,
  Steward1,
  StewardRc <HashMap<ColumnId, fn (&FieldRc, &FieldRc)>>,
  PhantomData <B::Constants>
);
pub struct Snapshot<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  <Steward0 as TimeSteward <B>>::Snapshot,
  <Steward1 as TimeSteward <B>>::Snapshot,
  StewardRc <HashMap<ColumnId, fn (&FieldRc, &FieldRc)>>,
);
pub struct Settings <B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  <Steward0 as TimeSteward <B>>::Settings,
  <Steward1 as TimeSteward <B>>::Settings,
  pub HashMap<ColumnId, fn (&FieldRc, &FieldRc)>,
);

pub fn check_equality <C: Column> (first: &FieldRc, second: &FieldRc) {
  assert_eq!(::unwrap_field::<C>(first), ::unwrap_field::<C>(second), "Snapshots returned the same field with the same last change times but different data; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types");
}

#[macro_export]
macro_rules! __time_steward_insert_crossverification_function {
  ($column: ty, $table: expr) => {
    $table.insert (<$column as $crate::Column>::column_id(), $crate::stewards::crossverified::check_equality::<$column>);
  }
}

#[macro_export]
macro_rules! populate_crossverified_time_stewards_equality_table {
($settings: ident) => {
  for_all_columns! (__time_steward_insert_crossverification_function {Column, $settings.2});
}
}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > ::Accessor<B> for Snapshot<B, Steward0, Steward1> {
  //macro_rules! forward_snapshot_method ($method: ident ($self, $($argument_name: ident: $argument_type:ty),*)->$return_type:ty
  // TODO: forward all the methods properly
  // and check equality by serialization
  fn generic_data_and_extended_last_change (&self, id: FieldId)->Option <(& FieldRc, & ExtendedTime <B>)> {
    match (
      self.0.generic_data_and_extended_last_change (id),
      self.1.generic_data_and_extended_last_change (id)
    ) {
      (None, None) => None,
      (Some (value_0), Some (value_1)) => {
        assert_eq!(value_0.1, value_1.1, "Snapshots returned different last change times for the same field; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types");
        (self.2.get (& id.column_id).expect ("Column missing from crossverification table; did you forget to call populate_crossverified_time_stewards_equality_table!()? Or did you forget to list a column in for_all_columns!()?")) (value_0.0, value_1.0);
        Some (value_0)
      },
      //however, we CAN tell the difference between something and nothing
      _=> panic! ("One snapshot returned a value and the other didn't; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types")
    }
  }
  fn constants(&self) -> &B::Constants {
    //constants methods are usually implemented trivially; we don't bother checking them.
    //Since the user only gives you one set of constants, it's hard to return a wrong value
    self.0.constants()
  }
  fn unsafe_now(&self) -> &B::Time {
    let result = (self.0.unsafe_now(), self.1.unsafe_now());
    assert! (result.0 == result.1, "Snapshots returned different times; this is an egregious bug!");
    result.0
  }
}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > ::MomentaryAccessor<B> for Snapshot<B, Steward0, Steward1> {}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > ::Snapshot<B> for Snapshot<B, Steward0, Steward1> {
  fn num_fields(&self) -> usize {
    assert_eq!(self.0.num_fields(), self.1.num_fields());
    self.0.num_fields()
  }
}

pub struct SnapshotIter <'a, B: Basics, Steward0: TimeSteward<B> + 'a, Steward1: TimeSteward<B> + 'a>
where & 'a Steward0::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>
{
  iter: <& 'a Steward0::Snapshot as IntoIterator>::IntoIter,
  #[allow (dead_code)]
  snapshot: & 'a Snapshot <B, Steward0, Steward1>,
}
impl <'a, B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B>> Iterator for SnapshotIter<'a, B, Steward0, Steward1>
where & 'a Steward0::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>> {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  fn next (&mut self)->Option <Self::Item> {
    self. iter.next()
  }
  fn size_hint (&self)->(usize, Option <usize>) {self. iter.size_hint()}
}
impl <'a, B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B>> IntoIterator for & 'a Snapshot <B, Steward0, Steward1>
where & 'a Steward0::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>,

 {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  type IntoIter = SnapshotIter <'a, B, Steward0, Steward1>;
  fn into_iter (self)->Self::IntoIter {
    assert_eq! (self.0.num_fields(), self.1.num_fields());
    let mut fields = HashMap::new();
    for (id, data) in & self.0 {
      fields.insert (id, (data.0.clone(), data.1.clone()));
    }
    for (id, data) in & self.1 {
      let other_data = fields.get (& id).expect ("field existed in Steward1 snapshot but not Steward0 snapshot");
      assert_eq!(*data .1, other_data .1, "Snapshots returned different last change times for the same field; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types");
      (self.2.get (& id.column_id).expect ("Column missing from crossverification table; did you forget to call populate_crossverified_time_stewards_equality_table!()? Or did you forget to list a column in for_all_columns!()?")) (data .0, & other_data .0);
    }
    SnapshotIter:: <'a, B, Steward0, Steward1> {
      iter: (& self.0).into_iter(),
      snapshot: self
    }
  }
}

//TODO: implement snapshot iterating

/*
//TODO: should we just require PredictorFn to implement Clone?
#[derive (Serialize, Deserialize)]
struct ShareablePredictorFn <B: Basics, P: PredictorFn <B>> (StewardRc <P>, PhantomData <B>);
impl <B: Basics, P: PredictorFn <B>> PredictorFn <B> for ShareablePredictorFn <B, P> {
  fn call <PA: ::PredictorAccessor <B>> (&self, accessor: &mut PA, id: RowId) {
    self.0.call (accessor, id);
  }
}
// explicitly implement Clone to work around [a compiler weakness](https://github.com/rust-lang/rust/issues/26925).
impl<B: Basics> Clone for DynamicPredictor<B> {
  fn clone(&self) -> Self {
    DynamicPredictor {
      predictor_id: self.predictor_id,
      column_id: self.column_id,
      function: self.function.clone(),
      _marker: PhantomData,
    }
  }
}
*/

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > TimeStewardSettings <B> for Settings <B, Steward0, Steward1> {
  fn new()->Self {
    Settings (<Steward0::Settings as TimeStewardSettings <B>>::new(), <Steward1::Settings as TimeStewardSettings <B>>::new(), HashMap::new())
  }
  fn insert_predictor <P: PredictorFn <B>> (&mut self, predictor_id: PredictorId, column_id: ColumnId, function: P) {
    //let function = ShareablePredictorFn::<B, P> (StewardRc::new (function), PhantomData);
    self.0.insert_predictor (predictor_id, column_id, function.clone());
    self.1.insert_predictor (predictor_id, column_id, function);
  }
}

impl<B: Basics, Steward0: TimeSteward<B> , Steward1: TimeSteward<B> > TimeSteward<B> for Steward<B, Steward0, Steward1> {
  type Snapshot = Snapshot<B, Steward0, Steward1>;
  type Settings = Settings<B, Steward0, Steward1>;

  fn valid_since(&self) -> ValidSince<B::Time> {
    max (self.0.valid_since(), self.1.valid_since())
  }
  fn new_empty(constants: B::Constants, settings: Self::Settings) -> Self {
    Steward (
      TimeSteward::new_empty (constants.clone(), settings.0),
      TimeSteward::new_empty (constants, settings.1),
      StewardRc::new (settings.2),
      PhantomData,
    )
  }

  fn from_snapshot<'a, S: ::Snapshot<B>>(snapshot: & 'a S,
                                              settings: Self::Settings)
                                              -> Self
                                              where & 'a S: IntoIterator <Item = ::SnapshotEntry <'a, B>> {
    Steward (
      Steward0::from_snapshot::<'a, S>(snapshot, settings.0),
      Steward1::from_snapshot::<'a, S>(snapshot, settings.1),
      StewardRc::new (settings.2),
      PhantomData,
    )
  }
  fn insert_fiat_event <E: ::EventFn <B>> (&mut self,
                       time: B::Time,
                       id: DeterministicRandomId,
                       event: E)
                       -> Result<(), FiatEventOperationError> {
    if self.valid_since() > time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match (
      self.0.insert_fiat_event (time.clone(), id, event.clone()),
      self.1.insert_fiat_event (time, id, event)
    ){
      (Ok (()), Ok (())) => Ok (()),
      (Err (FiatEventOperationError::InvalidTime),_) => panic!("Steward0 returned InvalidTime after its own ValidSince"),
      (_,Err (FiatEventOperationError::InvalidTime)) => panic!("Steward1 returned InvalidTime after its own ValidSince"),
      (Err (FiatEventOperationError::InvalidInput),Err (FiatEventOperationError::InvalidInput)) => Err (FiatEventOperationError::InvalidInput),
      _=> panic!("stewards returned different results for insert_fiat_event; I believe this is ALWAYS a bug in one of the stewards (that is, it cannot be caused by invalid input)"),
    }
  }
  fn erase_fiat_event(&mut self,
                      time: &B::Time,
                      id: DeterministicRandomId)
                      -> Result<(), FiatEventOperationError> {
    if self.valid_since() > *time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match (
      self.0.erase_fiat_event (time, id),
      self.1.erase_fiat_event (time, id)
    ){
      (Ok (()), Ok (())) => Ok (()),
      (Err (FiatEventOperationError::InvalidTime),_) => panic!("Steward0 returned InvalidTime after its own ValidSince"),
      (_,Err (FiatEventOperationError::InvalidTime)) => panic!("Steward1 returned InvalidTime after its own ValidSince"),
      (Err (FiatEventOperationError::InvalidInput),Err (FiatEventOperationError::InvalidInput)) => Err (FiatEventOperationError::InvalidInput),
      _=> panic!("stewards returned different results for insert_fiat_event; I believe this is ALWAYS a bug in one of the stewards (that is, it cannot be caused by invalid input)"),
    }
  }

  fn snapshot_before<'b>(&'b mut self, time: &'b B::Time) -> Option<Self::Snapshot> {
    if self.valid_since() > *time {
      return None;
    }
    match (
      self.0.snapshot_before (time),
      self.1.snapshot_before (time)
    ) {
      (Some (snapshot_0), Some (snapshot_1)) => Some (Snapshot (snapshot_0, snapshot_1, self.2.clone())),
      (None, _) => panic! ("Steward0 failed to return a snapshot at a time it claims to be valid"),
      (_, None) => panic! ("Steward1 failed to return a snapshot at a time it claims to be valid"),
    }
  }
}

<commit_msg>Cross verified time stewards also audit for the ValidSince rules<commit_after>//! The simplest possible implementation of the TimeSteward API.
//!
//! This implementation is unusably slow on large simulations. Its main use is to cross-check with other TimeSteward implementations to make sure they are implementing the API correctly.
//!
//!

use {DeterministicRandomId, ColumnId, FieldId, PredictorId, Column, ExtendedTime, StewardRc,
             Basics, FieldRc, TimeSteward, FiatEventOperationError, ValidSince, PredictorFn, TimeStewardSettings};
use std::collections::{HashMap};
// use std::collections::Bound::{Included, Excluded, Unbounded};
use std::cmp::max;
use std::marker::PhantomData;
use Snapshot as SuperSnapshot;

#[derive (Clone)]
pub struct Steward<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  Steward0,
  Steward1,
  StewardRc <HashMap<ColumnId, fn (&FieldRc, &FieldRc)>>,
  PhantomData <B::Constants>
);
pub struct Snapshot<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  <Steward0 as TimeSteward <B>>::Snapshot,
  <Steward1 as TimeSteward <B>>::Snapshot,
  StewardRc <HashMap<ColumnId, fn (&FieldRc, &FieldRc)>>,
);
pub struct Settings <B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > (
  <Steward0 as TimeSteward <B>>::Settings,
  <Steward1 as TimeSteward <B>>::Settings,
  pub HashMap<ColumnId, fn (&FieldRc, &FieldRc)>,
);

pub fn check_equality <C: Column> (first: &FieldRc, second: &FieldRc) {
  assert_eq!(::unwrap_field::<C>(first), ::unwrap_field::<C>(second), "Snapshots returned the same field with the same last change times but different data; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types");
}

#[macro_export]
macro_rules! __time_steward_insert_crossverification_function {
  ($column: ty, $table: expr) => {
    $table.insert (<$column as $crate::Column>::column_id(), $crate::stewards::crossverified::check_equality::<$column>);
  }
}

#[macro_export]
macro_rules! populate_crossverified_time_stewards_equality_table {
($settings: ident) => {
  for_all_columns! (__time_steward_insert_crossverification_function {Column, $settings.2});
}
}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > ::Accessor<B> for Snapshot<B, Steward0, Steward1> {
  //macro_rules! forward_snapshot_method ($method: ident ($self, $($argument_name: ident: $argument_type:ty),*)->$return_type:ty
  // TODO: forward all the methods properly
  // and check equality by serialization
  fn generic_data_and_extended_last_change (&self, id: FieldId)->Option <(& FieldRc, & ExtendedTime <B>)> {
    match (
      self.0.generic_data_and_extended_last_change (id),
      self.1.generic_data_and_extended_last_change (id)
    ) {
      (None, None) => None,
      (Some (value_0), Some (value_1)) => {
        assert_eq!(value_0.1, value_1.1, "Snapshots returned different last change times for the same field; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types");
        (self.2.get (& id.column_id).expect ("Column missing from crossverification table; did you forget to call populate_crossverified_time_stewards_equality_table!()? Or did you forget to list a column in for_all_columns!()?")) (value_0.0, value_1.0);
        Some (value_0)
      },
      //however, we CAN tell the difference between something and nothing
      _=> panic! ("One snapshot returned a value and the other didn't; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types")
    }
  }
  fn constants(&self) -> &B::Constants {
    //constants methods are usually implemented trivially; we don't bother checking them.
    //Since the user only gives you one set of constants, it's hard to return a wrong value
    self.0.constants()
  }
  fn unsafe_now(&self) -> &B::Time {
    let result = (self.0.unsafe_now(), self.1.unsafe_now());
    assert! (result.0 == result.1, "Snapshots returned different times; this is an egregious bug!");
    result.0
  }
}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > ::MomentaryAccessor<B> for Snapshot<B, Steward0, Steward1> {}

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > ::Snapshot<B> for Snapshot<B, Steward0, Steward1> {
  fn num_fields(&self) -> usize {
    assert_eq!(self.0.num_fields(), self.1.num_fields());
    self.0.num_fields()
  }
}

pub struct SnapshotIter <'a, B: Basics, Steward0: TimeSteward<B> + 'a, Steward1: TimeSteward<B> + 'a>
where & 'a Steward0::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>
{
  iter: <& 'a Steward0::Snapshot as IntoIterator>::IntoIter,
  #[allow (dead_code)]
  snapshot: & 'a Snapshot <B, Steward0, Steward1>,
}
impl <'a, B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B>> Iterator for SnapshotIter<'a, B, Steward0, Steward1>
where & 'a Steward0::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>> {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  fn next (&mut self)->Option <Self::Item> {
    self. iter.next()
  }
  fn size_hint (&self)->(usize, Option <usize>) {self. iter.size_hint()}
}
impl <'a, B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B>> IntoIterator for & 'a Snapshot <B, Steward0, Steward1>
where & 'a Steward0::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>,
& 'a Steward1::Snapshot: IntoIterator <Item = ::SnapshotEntry <'a, B>>,

 {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  type IntoIter = SnapshotIter <'a, B, Steward0, Steward1>;
  fn into_iter (self)->Self::IntoIter {
    assert_eq! (self.0.num_fields(), self.1.num_fields());
    let mut fields = HashMap::new();
    for (id, data) in & self.0 {
      fields.insert (id, (data.0.clone(), data.1.clone()));
    }
    for (id, data) in & self.1 {
      let other_data = fields.get (& id).expect ("field existed in Steward1 snapshot but not Steward0 snapshot");
      assert_eq!(*data .1, other_data .1, "Snapshots returned different last change times for the same field; one or both of the stewards is buggy, or the caller submitted very nondeterministic event/predictor types");
      (self.2.get (& id.column_id).expect ("Column missing from crossverification table; did you forget to call populate_crossverified_time_stewards_equality_table!()? Or did you forget to list a column in for_all_columns!()?")) (data .0, & other_data .0);
    }
    SnapshotIter:: <'a, B, Steward0, Steward1> {
      iter: (& self.0).into_iter(),
      snapshot: self
    }
  }
}

//TODO: implement snapshot iterating

/*
//TODO: should we just require PredictorFn to implement Clone?
#[derive (Serialize, Deserialize)]
struct ShareablePredictorFn <B: Basics, P: PredictorFn <B>> (StewardRc <P>, PhantomData <B>);
impl <B: Basics, P: PredictorFn <B>> PredictorFn <B> for ShareablePredictorFn <B, P> {
  fn call <PA: ::PredictorAccessor <B>> (&self, accessor: &mut PA, id: RowId) {
    self.0.call (accessor, id);
  }
}
// explicitly implement Clone to work around [a compiler weakness](https://github.com/rust-lang/rust/issues/26925).
impl<B: Basics> Clone for DynamicPredictor<B> {
  fn clone(&self) -> Self {
    DynamicPredictor {
      predictor_id: self.predictor_id,
      column_id: self.column_id,
      function: self.function.clone(),
      _marker: PhantomData,
    }
  }
}
*/

impl<B: Basics, Steward0: TimeSteward<B>, Steward1: TimeSteward<B> > TimeStewardSettings <B> for Settings <B, Steward0, Steward1> {
  fn new()->Self {
    Settings (<Steward0::Settings as TimeStewardSettings <B>>::new(), <Steward1::Settings as TimeStewardSettings <B>>::new(), HashMap::new())
  }
  fn insert_predictor <P: PredictorFn <B>> (&mut self, predictor_id: PredictorId, column_id: ColumnId, function: P) {
    //let function = ShareablePredictorFn::<B, P> (StewardRc::new (function), PhantomData);
    self.0.insert_predictor (predictor_id, column_id, function.clone());
    self.1.insert_predictor (predictor_id, column_id, function);
  }
}

impl<B: Basics, Steward0: TimeSteward<B> , Steward1: TimeSteward<B> > TimeSteward<B> for Steward<B, Steward0, Steward1> {
  type Snapshot = Snapshot<B, Steward0, Steward1>;
  type Settings = Settings<B, Steward0, Steward1>;

  fn valid_since(&self) -> ValidSince<B::Time> {
    max (self.0.valid_since(), self.1.valid_since())
  }
  fn new_empty(constants: B::Constants, settings: Self::Settings) -> Self {
    let result = Steward::<B, Steward0, Steward1> (
      TimeSteward::new_empty (constants.clone(), settings.0),
      TimeSteward::new_empty (constants, settings.1),
      StewardRc::new (settings.2),
      PhantomData,
    );
    assert!(result.0.valid_since() == ValidSince::TheBeginning, "Steward0 broke the ValidSince rules");
    assert!(result.1.valid_since() == ValidSince::TheBeginning, "Steward1 broke the ValidSince rules");
    result
  }

  fn from_snapshot<'a, S: ::Snapshot<B>>(snapshot: & 'a S,
                                              settings: Self::Settings)
                                              -> Self
                                              where & 'a S: IntoIterator <Item = ::SnapshotEntry <'a, B>> {
    let result = Steward (
      Steward0::from_snapshot::<'a, S>(snapshot, settings.0),
      Steward1::from_snapshot::<'a, S>(snapshot, settings.1),
      StewardRc::new (settings.2),
      PhantomData,
    );
    assert!(result.0.valid_since() == ValidSince::Before (snapshot.now().clone()), "Steward0 broke the ValidSince rules");
    assert!(result.1.valid_since() == ValidSince::Before (snapshot.now().clone()), "Steward1 broke the ValidSince rules");
    result
  }
  fn insert_fiat_event <E: ::EventFn <B>> (&mut self,
                       time: B::Time,
                       id: DeterministicRandomId,
                       event: E)
                       -> Result<(), FiatEventOperationError> {
    if self.valid_since() > time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    let old_valid_since = (self.0.valid_since(), self.1.valid_since());
    let result = match (
      self.0.insert_fiat_event (time.clone(), id, event.clone()),
      self.1.insert_fiat_event (time, id, event)
    ){
      (Ok (()), Ok (())) => Ok (()),
      (Err (FiatEventOperationError::InvalidTime),_) => panic!("Steward0 returned InvalidTime after its own ValidSince"),
      (_,Err (FiatEventOperationError::InvalidTime)) => panic!("Steward1 returned InvalidTime after its own ValidSince"),
      (Err (FiatEventOperationError::InvalidInput),Err (FiatEventOperationError::InvalidInput)) => Err (FiatEventOperationError::InvalidInput),
      _=> panic!("stewards returned different results for insert_fiat_event; I believe this is ALWAYS a bug in one of the stewards (that is, it cannot be caused by invalid input)"),
    };
    assert!(self .0.valid_since() == old_valid_since.0, "Steward0 broke the ValidSince rules");
    assert!(self .1.valid_since() == old_valid_since.1, "Steward1 broke the ValidSince rules");
    result
  }
  fn erase_fiat_event(&mut self,
                      time: &B::Time,
                      id: DeterministicRandomId)
                      -> Result<(), FiatEventOperationError> {
    if self.valid_since() > *time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    let old_valid_since = (self.0.valid_since(), self.1.valid_since());
    let result = match (
      self.0.erase_fiat_event (time, id),
      self.1.erase_fiat_event (time, id)
    ){
      (Ok (()), Ok (())) => Ok (()),
      (Err (FiatEventOperationError::InvalidTime),_) => panic!("Steward0 returned InvalidTime after its own ValidSince"),
      (_,Err (FiatEventOperationError::InvalidTime)) => panic!("Steward1 returned InvalidTime after its own ValidSince"),
      (Err (FiatEventOperationError::InvalidInput),Err (FiatEventOperationError::InvalidInput)) => Err (FiatEventOperationError::InvalidInput),
      _=> panic!("stewards returned different results for insert_fiat_event; I believe this is ALWAYS a bug in one of the stewards (that is, it cannot be caused by invalid input)"),
    };
    assert!(self .0.valid_since() == old_valid_since.0, "Steward0 broke the ValidSince rules");
    assert!(self .1.valid_since() == old_valid_since.1, "Steward1 broke the ValidSince rules");
    result
  }

  fn snapshot_before<'b>(&'b mut self, time: &'b B::Time) -> Option<Self::Snapshot> {
    if self.valid_since() > *time {
      return None;
    }
    let result = match (
      self.0.snapshot_before (time),
      self.1.snapshot_before (time)
    ) {
      (Some (snapshot_0), Some (snapshot_1)) => Some (Snapshot (snapshot_0, snapshot_1, self.2.clone())),
      (None, _) => panic! ("Steward0 failed to return a snapshot at a time it claims to be valid"),
      (_, None) => panic! ("Steward1 failed to return a snapshot at a time it claims to be valid"),
    };
    assert!(self .0.valid_since() <*time, "Steward0 broke the ValidSince rules");
    assert!(self .1.valid_since() <*time, "Steward1 broke the ValidSince rules");
    result
  }
}

<|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(const_fn)]
#![cfg(feature = "debugmozjs")]

#[macro_use]
extern crate js;
extern crate libc;

use js::jsapi::CompartmentOptions;
use js::jsapi::JSAutoCompartment;
use js::jsapi::JSClass;
use js::jsapi::JSContext;
use js::jsapi::JSFunctionSpec;
use js::jsapi::JS_GetObjectPrototype;
use js::jsapi::JSNativeWrapper;
use js::jsapi::JS_NewGlobalObject;
use js::jsapi::JS_NewObjectWithUniqueType;
use js::jsapi::JSPROP_ENUMERATE;
use js::jsapi::JS_SetGCZeal;
use js::jsapi::OnNewGlobalHookOption;
use js::jsapi::Value;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS, define_methods};
use std::ptr;

#[test]
fn rooting() {
    unsafe {
        let runtime = Runtime::new().unwrap();
        JS_SetGCZeal(runtime.rt(), 2, 1);

        let cx = runtime.cx();
        let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
        let c_option = CompartmentOptions::default();

        rooted!(in(cx) let global = JS_NewGlobalObject(cx,
                                                       &SIMPLE_GLOBAL_CLASS,
                                                       ptr::null_mut(),
                                                       h_option,
                                                       &c_option));
        let _ac = JSAutoCompartment::new(cx, global.get());
        rooted!(in(cx) let prototype_proto = JS_GetObjectPrototype(cx, global.handle()));
        rooted!(in(cx) let proto = JS_NewObjectWithUniqueType(cx,
                                                              &CLASS as *const _,
                                                              prototype_proto.handle()));
        define_methods(cx, proto.handle(), METHODS).unwrap();
    }
}

unsafe extern "C" fn generic_method(_: *mut JSContext, _: u32, _: *mut Value) -> bool {
    true
}

const METHODS: &'static [JSFunctionSpec] = &[
    JSFunctionSpec {
        name: b"addEventListener\0" as *const u8 as *const libc::c_char,
        call: JSNativeWrapper { op: Some(generic_method), info: ptr::null() },
        nargs: 2,
        flags: JSPROP_ENUMERATE as u16,
        selfHostedName: 0 as *const libc::c_char
    },
    JSFunctionSpec {
        name: b"removeEventListener\0" as *const u8 as *const libc::c_char,
        call: JSNativeWrapper { op: Some(generic_method), info: ptr::null() },
        nargs: 2,
        flags: JSPROP_ENUMERATE as u16,
        selfHostedName: 0 as *const libc::c_char
    },
    JSFunctionSpec {
        name: b"dispatchEvent\0" as *const u8 as *const libc::c_char,
        call: JSNativeWrapper { op: Some(generic_method), info: ptr::null() },
        nargs: 1,
        flags: JSPROP_ENUMERATE as u16,
        selfHostedName: 0 as *const libc::c_char
    },
    JSFunctionSpec {
        name: ptr::null(),
        call: JSNativeWrapper { op: None, info: ptr::null() },
        nargs: 0,
        flags: 0,
        selfHostedName: ptr::null()
    }
];

static CLASS: JSClass = JSClass {
    name: b"EventTargetPrototype\0" as *const u8 as *const libc::c_char,
    flags: 0,
    cOps: 0 as *const _,
    reserved: [0 as *mut _; 3]
};
<commit_msg>Auto merge of #371 - servo:jdm-patch-2, r=SimonSapin<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/. */

#![feature(const_fn)]
#![feature(const_ptr_null)]
#![cfg(feature = "debugmozjs")]

#[macro_use]
extern crate js;
extern crate libc;

use js::jsapi::CompartmentOptions;
use js::jsapi::JSAutoCompartment;
use js::jsapi::JSClass;
use js::jsapi::JSContext;
use js::jsapi::JSFunctionSpec;
use js::jsapi::JS_GetObjectPrototype;
use js::jsapi::JSNativeWrapper;
use js::jsapi::JS_NewGlobalObject;
use js::jsapi::JS_NewObjectWithUniqueType;
use js::jsapi::JSPROP_ENUMERATE;
use js::jsapi::JS_SetGCZeal;
use js::jsapi::OnNewGlobalHookOption;
use js::jsapi::Value;
use js::rust::{Runtime, SIMPLE_GLOBAL_CLASS, define_methods};
use std::ptr;

#[test]
fn rooting() {
    unsafe {
        let runtime = Runtime::new().unwrap();
        JS_SetGCZeal(runtime.rt(), 2, 1);

        let cx = runtime.cx();
        let h_option = OnNewGlobalHookOption::FireOnNewGlobalHook;
        let c_option = CompartmentOptions::default();

        rooted!(in(cx) let global = JS_NewGlobalObject(cx,
                                                       &SIMPLE_GLOBAL_CLASS,
                                                       ptr::null_mut(),
                                                       h_option,
                                                       &c_option));
        let _ac = JSAutoCompartment::new(cx, global.get());
        rooted!(in(cx) let prototype_proto = JS_GetObjectPrototype(cx, global.handle()));
        rooted!(in(cx) let proto = JS_NewObjectWithUniqueType(cx,
                                                              &CLASS as *const _,
                                                              prototype_proto.handle()));
        define_methods(cx, proto.handle(), METHODS).unwrap();
    }
}

unsafe extern "C" fn generic_method(_: *mut JSContext, _: u32, _: *mut Value) -> bool {
    true
}

const METHODS: &'static [JSFunctionSpec] = &[
    JSFunctionSpec {
        name: b"addEventListener\0" as *const u8 as *const libc::c_char,
        call: JSNativeWrapper { op: Some(generic_method), info: ptr::null() },
        nargs: 2,
        flags: JSPROP_ENUMERATE as u16,
        selfHostedName: 0 as *const libc::c_char
    },
    JSFunctionSpec {
        name: b"removeEventListener\0" as *const u8 as *const libc::c_char,
        call: JSNativeWrapper { op: Some(generic_method), info: ptr::null() },
        nargs: 2,
        flags: JSPROP_ENUMERATE as u16,
        selfHostedName: 0 as *const libc::c_char
    },
    JSFunctionSpec {
        name: b"dispatchEvent\0" as *const u8 as *const libc::c_char,
        call: JSNativeWrapper { op: Some(generic_method), info: ptr::null() },
        nargs: 1,
        flags: JSPROP_ENUMERATE as u16,
        selfHostedName: 0 as *const libc::c_char
    },
    JSFunctionSpec {
        name: ptr::null(),
        call: JSNativeWrapper { op: None, info: ptr::null() },
        nargs: 0,
        flags: 0,
        selfHostedName: ptr::null()
    }
];

static CLASS: JSClass = JSClass {
    name: b"EventTargetPrototype\0" as *const u8 as *const libc::c_char,
    flags: 0,
    cOps: 0 as *const _,
    reserved: [0 as *mut _; 3]
};
<|endoftext|>


<commit_before>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
//!   marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//!   expresses the presence or absence of a value. This type is so commonly
//!   used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//!   that may succeed or fail. Like [`Option`], its variants are exported as
//!   well.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//!   vector.
//!
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Unpin`]: ../marker/trait.Unpin.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone
//! [`mem::drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`std::vec`]: ../vec/index.html
//! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html
//! [book-enums]: ../../book/ch06-01-defining-an-enum.html
//! [book-iter]: ../../book/ch13-02-iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<commit_msg>Move to doc links inside the prelude<commit_after>//! The Rust Prelude.
//!
//! Rust comes with a variety of things in its standard library. However, if
//! you had to manually import every single thing that you used, it would be
//! very verbose. But importing a lot of things that a program never uses isn't
//! good either. A balance needs to be struck.
//!
//! The *prelude* is the list of things that Rust automatically imports into
//! every Rust program. It's kept as small as possible, and is focused on
//! things, particularly traits, which are used in almost every single Rust
//! program.
//!
//! # Other preludes
//!
//! Preludes can be seen as a pattern to make using multiple types more
//! convenient. As such, you'll find other preludes in the standard library,
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: crate::io::prelude
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
//! easier than importing all of their constituent components.
//!
//! # Prelude contents
//!
//! The current version of the prelude (version 1) lives in
//! [`std::prelude::v1`], and re-exports the following.
//!
//! * [`std::marker`]::{[`Copy`], [`Send`], [`Sized`], [`Sync`], [`Unpin`]}. The
//!   marker traits indicate fundamental properties of types.
//! * [`std::ops`]::{[`Drop`], [`Fn`], [`FnMut`], [`FnOnce`]}. Various
//!   operations for both destructors and overloading `()`.
//! * [`std::mem`]::[`drop`][`mem::drop`], a convenience function for explicitly
//!   dropping a value.
//! * [`std::boxed`]::[`Box`], a way to allocate values on the heap.
//! * [`std::borrow`]::[`ToOwned`], The conversion trait that defines
//!   [`to_owned`], the generic method for creating an owned type from a
//!   borrowed type.
//! * [`std::clone`]::[`Clone`], the ubiquitous trait that defines
//!   [`clone`][`Clone::clone`], the method for producing a copy of a value.
//! * [`std::cmp`]::{[`PartialEq`], [`PartialOrd`], [`Eq`], [`Ord`] }. The
//!   comparison traits, which implement the comparison operators and are often
//!   seen in trait bounds.
//! * [`std::convert`]::{[`AsRef`], [`AsMut`], [`Into`], [`From`]}. Generic
//!   conversions, used by savvy API authors to create overloaded methods.
//! * [`std::default`]::[`Default`], types that have default values.
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//!   [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//!   kinds.
//! * [`std::option`]::[`Option`]::{[`self`][`Option`], [`Some`], [`None`]}. A
//!   type which expresses the presence or absence of a value. This type is so
//!   commonly used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{[`self`][`Result`], [`Ok`], [`Err`]}. A type
//!   for functions that may succeed or fail. Like [`Option`], its variants are
//!   exported as well.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`], a growable, heap-allocated
//!   vector.
//!
//! [`mem::drop`]: crate::mem::drop
//! [`std::borrow`]: crate::borrow
//! [`std::boxed`]: crate::boxed
//! [`std::clone`]: crate::clone
//! [`std::cmp`]: crate::cmp
//! [`std::convert`]: crate::convert
//! [`std::default`]: crate::default
//! [`std::iter`]: crate::iter
//! [`std::marker`]: crate::marker
//! [`std::mem`]: crate::mem
//! [`std::ops`]: crate::ops
//! [`std::option`]: crate::option
//! [`std::prelude::v1`]: v1
//! [`std::result`]: crate::result
//! [`std::slice`]: crate::slice
//! [`std::string`]: crate::string
//! [`std::vec`]: module@crate::vec
//! [`to_owned`]: crate::borrow::ToOwned::to_owned
//! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html
//! [book-enums]: ../../book/ch06-01-defining-an-enum.html
//! [book-iter]: ../../book/ch13-02-iterators.html

#![stable(feature = "rust1", since = "1.0.0")]

pub mod v1;
<|endoftext|>


<commit_before>use std::cmp::Ordering;

use package::Version;
use package::PackageType;

/// A struct for storing package informations, such as its name and version.
#[derive(Debug, Serialize, Deserialize)]
pub struct Package {
    name: String,
    hash: u32,
    version: Version,
    package_type: PackageType,
    path: String, // relative path
    dependencies: Vec<Package>,
}

impl PartialEq for Package {
    fn eq(&self, other: &Self) -> bool {
        self.name == other.name &&
        self.version == other.version
    }
}

impl Package {
    /// Returns the name of the package.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Returns the version of the package.
    pub fn version(&self) -> &Version {
        &self.version
    }

    /// Returns the hash of the package.
    pub fn hash(&self) -> u32 {
        self.hash
    }

    /// Returns the type of the package.
    pub fn package_type(&self) -> &PackageType {
        &self.package_type
    }
}<commit_msg>Unused import.<commit_after>use package::Version;
use package::PackageType;

/// A struct for storing package informations, such as its name and version.
#[derive(Debug, Serialize, Deserialize)]
pub struct Package {
    name: String,
    hash: u32,
    version: Version,
    package_type: PackageType,
    path: String, // relative path
    dependencies: Vec<Package>,
}

impl PartialEq for Package {
    fn eq(&self, other: &Self) -> bool {
        self.name == other.name &&
        self.version == other.version
    }
}

impl Package {
    /// Returns the name of the package.
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Returns the version of the package.
    pub fn version(&self) -> &Version {
        &self.version
    }

    /// Returns the hash of the package.
    pub fn hash(&self) -> u32 {
        self.hash
    }

    /// Returns the type of the package.
    pub fn package_type(&self) -> &PackageType {
        &self.package_type
    }
}<|endoftext|>


<commit_before>use super::internal::*;
use super::*;
use std::cmp::min;

/// Test if a byte is the start of a UTF-8 character.
/// (extracted from `str::is_char_boundary`)
fn is_char_boundary(b: u8) -> bool {
    // This is bit magic equivalent to: b < 128 || b >= 192
    (b as i8) >= -0x40
}

/// Find the index of a character boundary near the midpoint.
fn find_char_midpoint(chars: &str) -> usize {
    let mid = chars.len() / 2;

    // We want to split near the midpoint, but we need to find an actual
    // character boundary.  So we look at the raw bytes, first scanning
    // forward from the midpoint for a boundary, then trying backward.
    let (left, right) = chars.as_bytes().split_at(mid);
    right.iter()
        .cloned()
        .position(is_char_boundary)
        .map(|i| mid + i)
        .or_else(|| left.iter().cloned().rposition(is_char_boundary))
        .unwrap_or(0)
}

/// Parallel extensions for strings.
pub trait ParallelString {
    /// Returns a parallel iterator over the characters of a string.
    fn par_chars(&self) -> ParChars;

    /// Returns a parallel iterator over substrings separated by a
    /// given character, similar to `str::split`.
    fn par_split(&self, char) -> ParSplit;

    /// Returns a parallel iterator over substrings terminated by a
    /// given character, similar to `str::split_terminator`.  It's
    /// equivalent to `par_split`, except it doesn't produce an empty
    /// substring after a trailing terminator.
    fn par_split_terminator(&self, char) -> ParSplitTerminator;

    /// Returns a parallel iterator over the lines of a string, ending with an
    /// optional carriage return and with a newline (`\r\n` or just `\n`).
    /// The final line ending is optional, and line endings are not included in
    /// the output strings.
    fn par_lines(&self) -> ParLines;
}

impl ParallelString for str {
    fn par_chars(&self) -> ParChars {
        ParChars { chars: self }
    }

    fn par_split(&self, separator: char) -> ParSplit {
        ParSplit::new(self, separator)
    }

    fn par_split_terminator(&self, terminator: char) -> ParSplitTerminator {
        ParSplitTerminator::new(self, terminator)
    }

    fn par_lines(&self) -> ParLines {
        ParLines(self)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParChars<'a> {
    chars: &'a str,
}

impl<'a> ParallelIterator for ParChars<'a> {
    type Item = char;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'a> UnindexedProducer for ParChars<'a> {
    type Item = char;

    fn split(&mut self) -> Option<Self> {
        let index = find_char_midpoint(self.chars);
        if index > 0 {
            let (left, right) = self.chars.split_at(index);
            self.chars = left;
            Some(ParChars { chars: right })
        } else {
            None
        }
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        folder.consume_iter(self.chars.chars())
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplit<'a> {
    chars: &'a str,
    separator: char,

    /// Marks the endpoint beyond which we've already found no separators.
    tail: usize,
}

impl<'a> ParSplit<'a> {
    fn new(chars: &'a str, separator: char) -> Self {
        ParSplit {
            chars: chars,
            separator: separator,
            tail: chars.len(),
        }
    }

    /// Common `fold_with` implementation, integrating `ParSplitTerminator`'s
    /// need to sometimes skip its final empty item.
    fn fold_with<F>(self, folder: F, skip_last: bool) -> F
        where F: Folder<<Self as UnindexedProducer>::Item>
    {
        let ParSplit { chars, separator, tail } = self;

        if tail == chars.len() {
            // No tail section, so just let `str::split` handle it.
            let mut split = chars.split(separator);
            if skip_last {
                split.next_back();
            }
            folder.consume_iter(split)

        } else if let Some(index) = chars[..tail].rfind(separator) {
            // We found the last separator to complete the tail, so
            // end with that slice after `str::split` finds the rest.
            let head = &chars[..index];
            let folder = folder.consume_iter(head.split(separator));
            if skip_last || folder.full() {
                folder
            } else {
                let last = &chars[index + separator.len_utf8()..];
                folder.consume(last)
            }

        } else {
            // We know there are no separators at all.  Return our whole string.
            if skip_last {
                folder
            } else {
                folder.consume(chars)
            }
        }
    }
}

impl<'a> ParallelIterator for ParSplit<'a> {
    type Item = &'a str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'a> UnindexedProducer for ParSplit<'a> {
    type Item = &'a str;

    fn split(&mut self) -> Option<Self> {
        let ParSplit { chars, separator, tail } = *self;

        // First find a suitable UTF-8 boundary in the unsearched region.
        let char_index = find_char_midpoint(&chars[..tail]);

        // Look forward for the separator, and failing that look backward.
        let index = chars[char_index..tail]
            .find(separator)
            .map(|i| char_index + i)
            .or_else(|| chars[..char_index].rfind(separator));

        if let Some(index) = index {
            // Update `self` as the region before the separator.
            self.chars = &chars[..index];
            self.tail = min(char_index, index);

            // Create the right split following the separator.
            let right_index = index + separator.len_utf8();
            let mut right = ParSplit {
                chars: &chars[right_index..],
                separator: separator,
                tail: tail - right_index,
            };

            // If we scanned backwards to find the separator, everything in
            // the right side is exhausted, with no separators left to find.
            if index < char_index {
                right.tail = 0;
            }

            Some(right)

        } else {
            self.tail = 0;
            None
        }
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        self.fold_with(folder, false)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplitTerminator<'a> {
    splitter: ParSplit<'a>,
    endpoint: bool,
}

impl<'a> ParSplitTerminator<'a> {
    fn new(chars: &'a str, terminator: char) -> Self {
        ParSplitTerminator {
            splitter: ParSplit::new(chars, terminator),
            endpoint: true,
        }
    }
}

impl<'a> ParallelIterator for ParSplitTerminator<'a> {
    type Item = &'a str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'a> UnindexedProducer for ParSplitTerminator<'a> {
    type Item = &'a str;

    fn split(&mut self) -> Option<Self> {
        self.splitter.split().map(|right| {
            let endpoint = self.endpoint;
            self.endpoint = false;
            ParSplitTerminator {
                splitter: right,
                endpoint: endpoint,
            }
        })
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        // See if we need to eat the empty trailing substring
        let skip_last = if self.endpoint {
            let chars = self.splitter.chars;
            let terminator = self.splitter.separator;
            chars.is_empty() || chars.ends_with(terminator)
        } else {
            false
        };

        self.splitter.fold_with(folder, skip_last)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParLines<'a>(&'a str);

impl<'a> ParallelIterator for ParLines<'a> {
    type Item = &'a str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        self.0
            .par_split_terminator('\n')
            .map(|line| {
                if line.ends_with('\r') {
                    &line[..line.len() - 1]
                } else {
                    line
                }
            })
            .drive_unindexed(consumer)
    }
}
<commit_msg>Add indirection to the ParSplit separator<commit_after>use super::internal::*;
use super::*;
use std::cmp::min;

/// Test if a byte is the start of a UTF-8 character.
/// (extracted from `str::is_char_boundary`)
fn is_char_boundary(b: u8) -> bool {
    // This is bit magic equivalent to: b < 128 || b >= 192
    (b as i8) >= -0x40
}

/// Find the index of a character boundary near the midpoint.
fn find_char_midpoint(chars: &str) -> usize {
    let mid = chars.len() / 2;

    // We want to split near the midpoint, but we need to find an actual
    // character boundary.  So we look at the raw bytes, first scanning
    // forward from the midpoint for a boundary, then trying backward.
    let (left, right) = chars.as_bytes().split_at(mid);
    right.iter()
        .cloned()
        .position(is_char_boundary)
        .map(|i| mid + i)
        .or_else(|| left.iter().cloned().rposition(is_char_boundary))
        .unwrap_or(0)
}

/// Parallel extensions for strings.
pub trait ParallelString {
    /// Returns a parallel iterator over the characters of a string.
    fn par_chars(&self) -> ParChars;

    /// Returns a parallel iterator over substrings separated by a
    /// given character, similar to `str::split`.
    fn par_split(&self, char) -> ParSplit;

    /// Returns a parallel iterator over substrings terminated by a
    /// given character, similar to `str::split_terminator`.  It's
    /// equivalent to `par_split`, except it doesn't produce an empty
    /// substring after a trailing terminator.
    fn par_split_terminator(&self, char) -> ParSplitTerminator;

    /// Returns a parallel iterator over the lines of a string, ending with an
    /// optional carriage return and with a newline (`\r\n` or just `\n`).
    /// The final line ending is optional, and line endings are not included in
    /// the output strings.
    fn par_lines(&self) -> ParLines;
}

impl ParallelString for str {
    fn par_chars(&self) -> ParChars {
        ParChars { chars: self }
    }

    fn par_split(&self, separator: char) -> ParSplit {
        ParSplit::new(self, separator)
    }

    fn par_split_terminator(&self, terminator: char) -> ParSplitTerminator {
        ParSplitTerminator::new(self, terminator)
    }

    fn par_lines(&self) -> ParLines {
        ParLines(self)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParChars<'ch> {
    chars: &'ch str,
}

impl<'ch> ParallelIterator for ParChars<'ch> {
    type Item = char;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge_unindexed(self, consumer)
    }
}

impl<'ch> UnindexedProducer for ParChars<'ch> {
    type Item = char;

    fn split(&mut self) -> Option<Self> {
        let index = find_char_midpoint(self.chars);
        if index > 0 {
            let (left, right) = self.chars.split_at(index);
            self.chars = left;
            Some(ParChars { chars: right })
        } else {
            None
        }
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        folder.consume_iter(self.chars.chars())
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplit<'ch> {
    chars: &'ch str,
    separator: char,
}

pub struct ParSplitProducer<'ch, 'sep> {
    chars: &'ch str,
    separator: &'sep char,

    /// Marks the endpoint beyond which we've already found no separators.
    tail: usize,
}

impl<'ch> ParSplit<'ch> {
    fn new(chars: &'ch str, separator: char) -> Self {
        ParSplit {
            chars: chars,
            separator: separator,
        }
    }
}

impl<'ch, 'sep> ParSplitProducer<'ch, 'sep> {
    fn new(split: &'sep ParSplit<'ch>) -> Self {
        ParSplitProducer {
            chars: split.chars,
            separator: &split.separator,
            tail: split.chars.len(),
        }
    }

    /// Common `fold_with` implementation, integrating `ParSplitTerminator`'s
    /// need to sometimes skip its final empty item.
    fn fold_with<F>(self, folder: F, skip_last: bool) -> F
        where F: Folder<<Self as UnindexedProducer>::Item>
    {
        let ParSplitProducer { chars, separator, tail } = self;

        if tail == chars.len() {
            // No tail section, so just let `str::split` handle it.
            let mut split = chars.split(*separator);
            if skip_last {
                split.next_back();
            }
            folder.consume_iter(split)

        } else if let Some(index) = chars[..tail].rfind(*separator) {
            // We found the last separator to complete the tail, so
            // end with that slice after `str::split` finds the rest.
            let head = &chars[..index];
            let folder = folder.consume_iter(head.split(*separator));
            if skip_last || folder.full() {
                folder
            } else {
                let last = &chars[index + separator.len_utf8()..];
                folder.consume(last)
            }

        } else {
            // We know there are no separators at all.  Return our whole string.
            if skip_last {
                folder
            } else {
                folder.consume(chars)
            }
        }
    }
}

impl<'ch> ParallelIterator for ParSplit<'ch> {
    type Item = &'ch str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let producer = ParSplitProducer::new(&self);
        bridge_unindexed(producer, consumer)
    }
}

impl<'ch, 'sep> UnindexedProducer for ParSplitProducer<'ch, 'sep> {
    type Item = &'ch str;

    fn split(&mut self) -> Option<Self> {
        let ParSplitProducer { chars, separator, tail } = *self;

        // First find a suitable UTF-8 boundary in the unsearched region.
        let char_index = find_char_midpoint(&chars[..tail]);

        // Look forward for the separator, and failing that look backward.
        let index = chars[char_index..tail]
            .find(*separator)
            .map(|i| char_index + i)
            .or_else(|| chars[..char_index].rfind(*separator));

        if let Some(index) = index {
            // Update `self` as the region before the separator.
            self.chars = &chars[..index];
            self.tail = min(char_index, index);

            // Create the right split following the separator.
            let right_index = index + separator.len_utf8();
            let mut right = ParSplitProducer {
                chars: &chars[right_index..],
                separator: separator,
                tail: tail - right_index,
            };

            // If we scanned backwards to find the separator, everything in
            // the right side is exhausted, with no separators left to find.
            if index < char_index {
                right.tail = 0;
            }

            Some(right)

        } else {
            self.tail = 0;
            None
        }
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        self.fold_with(folder, false)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParSplitTerminator<'ch> {
    splitter: ParSplit<'ch>,
}

pub struct ParSplitTerminatorProducer<'ch, 'sep> {
    splitter: ParSplitProducer<'ch, 'sep>,
    endpoint: bool,
}

impl<'ch> ParSplitTerminator<'ch> {
    fn new(chars: &'ch str, terminator: char) -> Self {
        ParSplitTerminator {
            splitter: ParSplit::new(chars, terminator),
        }
    }
}

impl<'ch, 'sep> ParSplitTerminatorProducer<'ch, 'sep> {
    fn new(split: &'sep ParSplitTerminator<'ch>) -> Self {
        ParSplitTerminatorProducer {
            splitter: ParSplitProducer::new(&split.splitter),
            endpoint: true,
        }
    }
}

impl<'ch> ParallelIterator for ParSplitTerminator<'ch> {
    type Item = &'ch str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let producer = ParSplitTerminatorProducer::new(&self);
        bridge_unindexed(producer, consumer)
    }
}

impl<'ch, 'sep> UnindexedProducer for ParSplitTerminatorProducer<'ch, 'sep> {
    type Item = &'ch str;

    fn split(&mut self) -> Option<Self> {
        self.splitter.split().map(|right| {
            let endpoint = self.endpoint;
            self.endpoint = false;
            ParSplitTerminatorProducer {
                splitter: right,
                endpoint: endpoint,
            }
        })
    }

    fn fold_with<F>(self, folder: F) -> F
        where F: Folder<Self::Item>
    {
        // See if we need to eat the empty trailing substring
        let skip_last = if self.endpoint {
            let chars = self.splitter.chars;
            let terminator = self.splitter.separator;
            chars.is_empty() || chars.ends_with(*terminator)
        } else {
            false
        };

        self.splitter.fold_with(folder, skip_last)
    }
}

// /////////////////////////////////////////////////////////////////////////

pub struct ParLines<'ch>(&'ch str);

impl<'ch> ParallelIterator for ParLines<'ch> {
    type Item = &'ch str;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        self.0
            .par_split_terminator('\n')
            .map(|line| {
                if line.ends_with('\r') {
                    &line[..line.len() - 1]
                } else {
                    line
                }
            })
            .drive_unindexed(consumer)
    }
}
<|endoftext|>


<commit_before>use crate::ast::*;

pub trait Walker {
    fn walk_statement_list(&mut self, stmts: Vec<&mut Statement>) {
        for v in stmts {
            self.walk_statement(v);
        }
    }

    fn walk_statement(&mut self, stmt: &mut Statement) {
        self.visit_statement(stmt);
        match stmt {
            Statement::Let(ref mut def) => {
                self.walk_expression(&mut def.value);
            }
            Statement::Expression(ref mut expr) => {
                self.walk_expression(expr);
            }
            Statement::Assert(_, ref mut expr) => {
                self.walk_expression(expr);
            }
            Statement::Output(_, _, ref mut expr) => {
                self.walk_expression(expr);
            }
            Statement::Print(_, _, ref mut expr) => {
                self.walk_expression(expr);
            }
        }
    }

    fn walk_fieldset(&mut self, fs: &mut FieldList) {
        for &mut (_, ref mut expr) in fs.iter_mut() {
            self.walk_expression(expr);
        }
    }

    fn walk_expression(&mut self, expr: &mut Expression) {
        self.visit_expression(expr);
        match expr {
            Expression::Call(ref mut def) => {
                for expr in def.arglist.iter_mut() {
                    self.walk_expression(expr);
                }
            }
            Expression::Cast(ref mut def) => {
                self.walk_expression(&mut def.target);
            }
            Expression::Copy(ref mut def) => {
                self.walk_fieldset(&mut def.fields);
            }
            Expression::Format(ref mut def) => match def.args {
                FormatArgs::List(ref mut args) => {
                    for expr in args.iter_mut() {
                        self.walk_expression(expr);
                    }
                }
                FormatArgs::Single(ref mut expr) => {
                    self.walk_expression(expr);
                }
            },
            Expression::FuncOp(ref mut def) => match def {
                FuncOpDef::Reduce(ref mut def) => {
                    self.walk_expression(def.target.as_mut());
                    self.walk_expression(def.acc.as_mut())
                }
                FuncOpDef::Map(ref mut def) => {
                    self.walk_expression(def.target.as_mut());
                }
                FuncOpDef::Filter(ref mut def) => {
                    self.walk_expression(def.target.as_mut());
                }
            },
            Expression::Binary(ref mut def) => {
                self.walk_expression(def.left.as_mut());
                self.walk_expression(def.right.as_mut());
            }
            Expression::Grouped(ref mut expr, _) => {
                self.walk_expression(expr);
            }
            Expression::Func(ref mut def) => self.walk_expression(def.fields.as_mut()),
            Expression::Module(ref mut def) => {
                self.walk_fieldset(&mut def.arg_set);
                for stmt in def.statements.iter_mut() {
                    self.walk_statement(stmt);
                }
            }
            Expression::Range(ref mut def) => {
                self.walk_expression(def.start.as_mut());
                self.walk_expression(def.end.as_mut());
                if let Some(ref mut expr) = def.step {
                    self.walk_expression(expr.as_mut());
                }
            }
            Expression::Select(ref mut def) => {
                match def.default {
                    Some(ref mut e) => {
                        self.walk_expression(e.as_mut());
                    }
                    None => {
                        // noop;
                    }
                };
                self.walk_expression(def.val.as_mut());
                self.walk_fieldset(&mut def.tuple);
            }
            Expression::Simple(ref mut val) => {
                self.visit_value(val);
            }
            Expression::Import(_) | Expression::Include(_) | Expression::Fail(_) => {
                //noop
            }
            Expression::Not(ref mut def) => {
                self.walk_expression(def.expr.as_mut());
            }
            Expression::Debug(ref mut def) => {
                self.walk_expression(&mut def.expr);
            }
        }
    }

    fn visit_value(&mut self, val: &mut Value);

    fn visit_expression(&mut self, expr: &mut Expression);

    fn visit_statement(&mut self, stmt: &mut Statement);
}

// TODO this would be better implemented as a Trait I think.
pub struct AstWalker<'a> {
    handle_value: Option<&'a dyn Fn(&mut Value)>,
    handle_expression: Option<&'a dyn Fn(&mut Expression)>,
    handle_statment: Option<&'a dyn Fn(&mut Statement)>,
}

impl<'a> AstWalker<'a> {
    pub fn new() -> Self {
        AstWalker {
            handle_value: None,
            handle_expression: None,
            handle_statment: None,
        }
    }

    pub fn with_value_handler(mut self, h: &'a dyn Fn(&mut Value)) -> Self {
        self.handle_value = Some(h);
        self
    }

    pub fn with_expr_handler(mut self, h: &'a dyn Fn(&mut Expression)) -> Self {
        self.handle_expression = Some(h);
        self
    }

    pub fn with_stmt_handler(mut self, h: &'a dyn Fn(&mut Statement)) -> Self {
        self.handle_statment = Some(h);
        self
    }
}

impl<'a> Walker for AstWalker<'a> {
    fn visit_value(&mut self, val: &mut Value) {
        if let Some(h) = self.handle_value {
            h(val);
        }
    }

    fn visit_expression(&mut self, expr: &mut Expression) {
        if let Some(h) = self.handle_expression {
            h(expr);
        }
    }

    fn visit_statement(&mut self, stmt: &mut Statement) {
        if let Some(h) = self.handle_statment {
            h(stmt);
        }
    }
}
<commit_msg>DEV: Improve the Walk trait a bit.<commit_after>use crate::ast::*;

pub trait Walker {
    fn walk_statement_list(&mut self, stmts: Vec<&mut Statement>) {
        for v in stmts {
            self.walk_statement(v);
        }
    }

    fn walk_statement(&mut self, stmt: &mut Statement) {
        self.visit_statement(stmt);
        match stmt {
            Statement::Let(ref mut def) => {
                self.walk_expression(&mut def.value);
            }
            Statement::Expression(ref mut expr) => {
                self.walk_expression(expr);
            }
            Statement::Assert(_, ref mut expr) => {
                self.walk_expression(expr);
            }
            Statement::Output(_, _, ref mut expr) => {
                self.walk_expression(expr);
            }
            Statement::Print(_, _, ref mut expr) => {
                self.walk_expression(expr);
            }
        }
    }

    fn walk_fieldset(&mut self, fs: &mut FieldList) {
        for &mut (_, ref mut expr) in fs.iter_mut() {
            self.walk_expression(expr);
        }
    }

    fn walk_expression(&mut self, expr: &mut Expression) {
        self.visit_expression(expr);
        match expr {
            Expression::Call(ref mut def) => {
                for expr in def.arglist.iter_mut() {
                    self.walk_expression(expr);
                }
            }
            Expression::Cast(ref mut def) => {
                self.walk_expression(&mut def.target);
            }
            Expression::Copy(ref mut def) => {
                self.walk_fieldset(&mut def.fields);
            }
            Expression::Format(ref mut def) => match def.args {
                FormatArgs::List(ref mut args) => {
                    for expr in args.iter_mut() {
                        self.walk_expression(expr);
                    }
                }
                FormatArgs::Single(ref mut expr) => {
                    self.walk_expression(expr);
                }
            },
            Expression::FuncOp(ref mut def) => match def {
                FuncOpDef::Reduce(ref mut def) => {
                    self.walk_expression(def.target.as_mut());
                    self.walk_expression(def.acc.as_mut())
                }
                FuncOpDef::Map(ref mut def) => {
                    self.walk_expression(def.target.as_mut());
                }
                FuncOpDef::Filter(ref mut def) => {
                    self.walk_expression(def.target.as_mut());
                }
            },
            Expression::Binary(ref mut def) => {
                self.walk_expression(def.left.as_mut());
                self.walk_expression(def.right.as_mut());
            }
            Expression::Grouped(ref mut expr, _) => {
                self.walk_expression(expr);
            }
            Expression::Func(ref mut def) => self.walk_expression(def.fields.as_mut()),
            Expression::Module(ref mut def) => {
                self.walk_fieldset(&mut def.arg_set);
                for stmt in def.statements.iter_mut() {
                    self.walk_statement(stmt);
                }
            }
            Expression::Range(ref mut def) => {
                self.walk_expression(def.start.as_mut());
                self.walk_expression(def.end.as_mut());
                if let Some(ref mut expr) = def.step {
                    self.walk_expression(expr.as_mut());
                }
            }
            Expression::Select(ref mut def) => {
                match def.default {
                    Some(ref mut e) => {
                        self.walk_expression(e.as_mut());
                    }
                    None => {
                        // noop;
                    }
                };
                self.walk_expression(def.val.as_mut());
                self.walk_fieldset(&mut def.tuple);
            }
            Expression::Simple(ref mut val) => {
                self.walk_value(val);
            }

            Expression::Import(i) => {
                self.visit_import(i);
            }
            Expression::Include(i) => {
                self.visit_include(i);
            }
            Expression::Fail(f) => {
                self.visit_fail(f);
            }
            Expression::Not(ref mut def) => {
                self.walk_expression(def.expr.as_mut());
            }
            Expression::Debug(ref mut def) => {
                self.walk_expression(&mut def.expr);
            }
        }
    }

    fn walk_value(&mut self, val: &mut Value) {
        match val {
            Value::Empty(_)
            | Value::Symbol(_)
            | Value::Boolean(_)
            | Value::Int(_)
            | Value::Float(_)
            | Value::Str(_) => self.visit_value(val),
            Value::Tuple(fs) => self.walk_fieldset(&mut fs.val),
            Value::List(vs) => {
                for e in &mut vs.elems {
                    self.walk_expression(e);
                }
            }
        }
    }

    fn visit_import(&mut self, i: &mut ImportDef) {
        // noop by default;
    }

    fn visit_include(&mut self, i: &mut IncludeDef) {
        // noop by default;
    }

    fn visit_fail(&mut self, f: &mut FailDef) {
        // noop by default;
    }

    fn visit_value(&mut self, val: &mut Value);

    fn visit_expression(&mut self, expr: &mut Expression);

    fn visit_statement(&mut self, stmt: &mut Statement);
}

// TODO this would be better implemented as a Trait I think.
pub struct AstWalker<'a> {
    handle_value: Option<&'a dyn Fn(&mut Value)>,
    handle_expression: Option<&'a dyn Fn(&mut Expression)>,
    handle_statment: Option<&'a dyn Fn(&mut Statement)>,
}

impl<'a> AstWalker<'a> {
    pub fn new() -> Self {
        AstWalker {
            handle_value: None,
            handle_expression: None,
            handle_statment: None,
        }
    }

    pub fn with_value_handler(mut self, h: &'a dyn Fn(&mut Value)) -> Self {
        self.handle_value = Some(h);
        self
    }

    pub fn with_expr_handler(mut self, h: &'a dyn Fn(&mut Expression)) -> Self {
        self.handle_expression = Some(h);
        self
    }

    pub fn with_stmt_handler(mut self, h: &'a dyn Fn(&mut Statement)) -> Self {
        self.handle_statment = Some(h);
        self
    }
}

impl<'a> Walker for AstWalker<'a> {
    fn visit_value(&mut self, val: &mut Value) {
        if let Some(h) = self.handle_value {
            h(val);
        }
    }

    fn visit_expression(&mut self, expr: &mut Expression) {
        if let Some(h) = self.handle_expression {
            h(expr);
        }
    }

    fn visit_statement(&mut self, stmt: &mut Statement) {
        if let Some(h) = self.handle_statment {
            h(stmt);
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate crypto;
use crypto::digest::Digest;
use crypto::sha2::Sha256;
extern crate base64;
extern crate u2fhid;
use std::{io, thread, time};
use std::sync::mpsc::channel;
use std::time::Duration;
use u2fhid::U2FDevice;

const PARAMETER_SIZE : usize = 32;

pub struct U2FManager {
}

impl U2FManager {
    pub fn new() -> U2FManager {
        U2FManager{}
    }

    pub fn register<F>(&self, timeout_sec: u8, challenge: Vec<u8>, application: Vec<u8>, callback: F)
        where F: FnOnce(io::Result<Vec<u8>>), F: Send + 'static
    {
        if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
            callback(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid parameter sizes")));
            return;
        }

        let timeout = Duration::from_secs(timeout_sec as u64);

        if let Err(e) = thread::Builder::new().name("Register Runloop".to_string()).spawn(move || {
            let manager = u2fhid::platform::new();
            let result = manager.register(timeout, challenge, application);
            callback(result);
        }) {
            callback(Err(e));
        }
    }

    pub fn sign<F>(&self, timeout_sec: u8, challenge: Vec<u8>, application: Vec<u8>, key_handle: Vec<u8>, callback: F)
        where F: FnOnce(io::Result<Vec<u8>>), F: Send + 'static
    {
        if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
            callback(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid parameter sizes")));
            return;
        }

    }
}

fn u2f_get_key_handle_from_register_response(register_response: &Vec<u8>) -> io::Result<Vec<u8>>
{
    if register_response[0] != 0x05 {
        return Err(io::Error::new(io::ErrorKind::InvalidData, "Reserved byte not set correctly"));
    }

    let key_handle_len = register_response[66] as usize;
    let mut public_key = register_response.clone();
    let mut key_handle = public_key.split_off(67);
    // let attestation = key_handle.split_off(key_handle_len);

    Ok(key_handle)
}

fn main() {
    println!("Searching for keys...");

    let mut challenge = Sha256::new();
    challenge.input_str(r#"{"challenge": "1vQ9mxionq0ngCnjD-wTsv1zUSrGRtFqG2xP09SbZ70", "version": "U2F_V2", "appId": "http://demo.yubico.com"}"#);
    let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    challenge.result(&mut chall_bytes);

    let mut application = Sha256::new();
    application.input_str("http://demo.yubico.com");
    let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    application.result(&mut app_bytes);

    let (tx, rx) = channel();
    let manager = U2FManager::new();

    manager.register(15, chall_bytes, app_bytes, move |result| {
        // Ship back to the main thread
        if let Err(e) = tx.send(result) {
            panic!("Could not send: {}", e);
        }
    });

    let thread_result = match rx.recv() {
        Ok(v) => v,
        Err(e) => panic!("Couldn't read data: {}", e),
    };

    let register_data = match thread_result {
        Ok(v) => v,
        Err(e) => panic!("Register failure: {}", e),
    };

    println!("Register result: {}", base64::encode(&register_data));

    // let key_handle = u2f_get_key_handle_from_register_response(&register_data).unwrap();

    // let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    // challenge.result(&mut chall_bytes);
    // let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    // application.result(&mut app_bytes);

    // manager.sign(15, chall_bytes, app_bytes, key_handle, move|result| {
    //     println!("Sign result: {}", base64::encode(&result.unwrap()));
    // });

    println!("Done.");
}
<commit_msg>More fix<commit_after>#[macro_use]
extern crate crypto;
use crypto::digest::Digest;
use crypto::sha2::Sha256;
extern crate base64;
extern crate u2fhid;
use std::{io, thread, time};
use std::sync::mpsc::channel;
use std::time::Duration;
use u2fhid::U2FDevice;

const PARAMETER_SIZE : usize = 32;

pub struct U2FManager {
}

impl U2FManager {
    pub fn new() -> U2FManager {
        U2FManager{}
    }

    pub fn register<F>(&self, timeout_sec: u8, challenge: Vec<u8>, application: Vec<u8>, callback: F)
        where F: FnOnce(io::Result<Vec<u8>>), F: Send + 'static
    {
        if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
            callback(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid parameter sizes")));
            return;
        }

        let timeout = Duration::from_secs(timeout_sec as u64);

        thread::Builder::new().name("Register Runloop".to_string()).spawn(move || {
            let mut manager = u2fhid::platform::new();
            let result = manager.register(timeout, challenge, application);
            callback(result);
        });
    }

    pub fn sign<F>(&self, timeout_sec: u8, challenge: Vec<u8>, application: Vec<u8>, key_handle: Vec<u8>, callback: F)
        where F: FnOnce(io::Result<Vec<u8>>), F: Send + 'static
    {
        if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
            callback(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid parameter sizes")));
            return;
        }

    }
}

fn u2f_get_key_handle_from_register_response(register_response: &Vec<u8>) -> io::Result<Vec<u8>>
{
    if register_response[0] != 0x05 {
        return Err(io::Error::new(io::ErrorKind::InvalidData, "Reserved byte not set correctly"));
    }

    let key_handle_len = register_response[66] as usize;
    let mut public_key = register_response.clone();
    let mut key_handle = public_key.split_off(67);
    // let attestation = key_handle.split_off(key_handle_len);

    Ok(key_handle)
}

fn main() {
    println!("Searching for keys...");

    let mut challenge = Sha256::new();
    challenge.input_str(r#"{"challenge": "1vQ9mxionq0ngCnjD-wTsv1zUSrGRtFqG2xP09SbZ70", "version": "U2F_V2", "appId": "http://demo.yubico.com"}"#);
    let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    challenge.result(&mut chall_bytes);

    let mut application = Sha256::new();
    application.input_str("http://demo.yubico.com");
    let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    application.result(&mut app_bytes);

    let (tx, rx) = channel();
    let manager = U2FManager::new();

    manager.register(15, chall_bytes, app_bytes, move |result| {
        // Ship back to the main thread
        if let Err(e) = tx.send(result) {
            panic!("Could not send: {}", e);
        }
    });

    let thread_result = match rx.recv() {
        Ok(v) => v,
        Err(e) => panic!("Couldn't read data: {}", e),
    };

    let register_data = match thread_result {
        Ok(v) => v,
        Err(e) => panic!("Register failure: {}", e),
    };

    println!("Register result: {}", base64::encode(&register_data));

    // let key_handle = u2f_get_key_handle_from_register_response(&register_data).unwrap();

    // let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    // challenge.result(&mut chall_bytes);
    // let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    // application.result(&mut app_bytes);

    // manager.sign(15, chall_bytes, app_bytes, key_handle, move|result| {
    //     println!("Sign result: {}", base64::encode(&result.unwrap()));
    // });

    println!("Done.");
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate crypto;
use crypto::digest::Digest;
use crypto::sha2::Sha256;
extern crate base64;
extern crate u2fhid;
use std::{io, thread, time};
use std::io::{Read, Write};
use std::sync::mpsc::{channel, Sender, Receiver, RecvTimeoutError};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use u2fhid::U2FDevice;

const PARAMETER_SIZE : usize = 32;

enum Command {
    Register,
    Sign,
}

pub struct WorkUnit
{
    timeout: Duration,
    start_time: Instant,
    command: Command,
    challenge: Vec<u8>,
    application: Vec<u8>,
    key_handle: Option<Vec<u8>>,
    result_tx: Sender<io::Result<Vec<u8>>>
}

pub struct U2FManager {
    work_tx: Sender<WorkUnit>,
}

pub fn open_u2f_manager() -> io::Result<U2FManager> {
    let (mut tx, rx) = channel::<WorkUnit>();
    let manager = U2FManager{
        work_tx: tx,
    };

    if let Err(e) = thread::Builder::new().name("HID Runloop".to_string()).spawn(move || {
        U2FManager::worker_loop(rx);
    }) {
        return Err(e);
    }
    Ok(manager)
}

impl U2FManager {
    fn worker_loop(work_rx: Receiver<WorkUnit>) {
        let platform = match u2fhid::platform::open_platform_manager() {
            Ok(v) => v,
            Err(e) => panic!("Failure to open platform HID support: {}", e),
        };

        let mut current_job : Option<WorkUnit> = None;
        loop {
            println!("Doing work");

            // Get new work
            match work_rx.recv_timeout(Duration::from_millis(100)) {
                Ok(v) => {
                    // TODO: Cancel existing job?
                    current_job = Some(v)
                },
                Err(e) => {
                    if e != RecvTimeoutError::Timeout {
                        panic!("whoa now {}", e);
                    }
                },
            };

            current_job = match current_job {
                Some(job) => {
                    let mut done = false;
                    let security_keys = match platform.find_keys() {
                        Ok(v) => v,
                        Err(e) => panic!("Problem enumerating keys, {}", e),
                    };

                    for mut device_obj in security_keys {
                        println!("iterating now");
                        if let Ok(_) = U2FManager::perform_job_for_key(&mut device_obj, &job) {
                            done = true;
                            break;
                        }
                    }

                    if job.start_time.elapsed() > job.timeout {
                        job.result_tx.send(Err(io::Error::new(io::ErrorKind::TimedOut, "Timed out")));
                        done = true;
                    }

                    if done {
                        None
                    } else {
                        Some(job)
                    }
                },
                None => None, // Nothing to do
            }
        }
    }

    pub fn perform_job_for_key<T>(dev: &mut T, job: &WorkUnit) -> io::Result<()>
        where T: U2FDevice + Read + Write
    {
        let result = match job.command {
            Command::Register => {
                u2fhid::u2f_register(dev, &job.challenge, &job.application)
            },
            Command::Sign => {
                // It'd be an error if key_handle was None here
                let keybytes = job.key_handle.as_ref().unwrap();
                u2fhid::u2f_sign(dev, &job.challenge, &job.application, keybytes)
            },
        };

        match result {
            Ok(bytes) => {
                job.result_tx.send(Ok(bytes));
                Ok(())
            },
            Err(e) => Err(e),
        }
    }

    pub fn register<F>(&self, timeout_sec: u8, challenge: Vec<u8>, application: Vec<u8>, callback: F)
        where F: FnOnce(io::Result<Vec<u8>>), F: Send + 'static
    {
        if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
            callback(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid parameter sizes")));
            return;
        }

        let (result_tx, result_rx) = channel::<io::Result<Vec<u8>>>();

        if let Err(e) = self.work_tx.send(WorkUnit{
            timeout: Duration::from_secs(timeout_sec as u64),
            start_time: Instant::now(),
            command: Command::Register,
            challenge: challenge,
            application: application,
            key_handle: None,
            result_tx: result_tx,
        }) {
            callback(Err(io::Error::new(io::ErrorKind::Other, format!("Send error {}", e))));
            return;
        }

        match result_rx.recv() {
            Ok(v) => callback(v),
            Err(e) => callback(Err(io::Error::new(io::ErrorKind::Other, e))),
        }
    }

    pub fn sign<F>(&self, timeout_sec: u8, challenge: Vec<u8>, application: Vec<u8>, key_handle: Vec<u8>, callback: F)
        where F: FnOnce(io::Result<Vec<u8>>), F: Send + 'static
    {
        if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
            callback(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid parameter sizes")));
            return;
        }

    }
}

fn u2f_get_key_handle_from_register_response(register_response: &Vec<u8>) -> io::Result<Vec<u8>>
{
    if register_response[0] != 0x05 {
        return Err(io::Error::new(io::ErrorKind::InvalidData, "Reserved byte not set correctly"));
    }

    let key_handle_len = register_response[66] as usize;
    let mut public_key = register_response.clone();
    let mut key_handle = public_key.split_off(67);
    // let attestation = key_handle.split_off(key_handle_len);

    Ok(key_handle)
}

fn main() {
    println!("Searching for keys...");

    let mut challenge = Sha256::new();
    challenge.input_str(r#"{"challenge": "1vQ9mxionq0ngCnjD-wTsv1zUSrGRtFqG2xP09SbZ70", "version": "U2F_V2", "appId": "http://demo.yubico.com"}"#);
    let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    challenge.result(&mut chall_bytes);

    let mut application = Sha256::new();
    application.input_str("http://demo.yubico.com");
    let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    application.result(&mut app_bytes);

    let (tx, rx) = channel();
    let manager = open_u2f_manager().unwrap();

    manager.register(15, chall_bytes, app_bytes, move |result| {
        // Ship back to the main thread
        if let Err(e) = tx.send(result) {
            panic!("Could not send: {}", e);
        }
    });

    let thread_result = match rx.recv() {
        Ok(v) => v,
        Err(e) => panic!("Couldn't read data: {}", e),
    };

    let register_data = match thread_result {
        Ok(v) => v,
        Err(e) => panic!("Register failure: {}", e),
    };

    println!("Register result: {}", base64::encode(&register_data));

    // let key_handle = u2f_get_key_handle_from_register_response(&register_data).unwrap();

    // let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    // challenge.result(&mut chall_bytes);
    // let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    // application.result(&mut app_bytes);

    // manager.sign(15, chall_bytes, app_bytes, key_handle, move|result| {
    //     println!("Sign result: {}", base64::encode(&result.unwrap()));
    // });

    println!("Done.");
}
<commit_msg>Set a common API for the 'main' method<commit_after>#[macro_use]
extern crate crypto;
use crypto::digest::Digest;
use crypto::sha2::Sha256;
extern crate base64;
extern crate u2fhid;
use std::{io, thread, time};
use std::sync::mpsc::channel;
use std::time::Duration;
use u2fhid::U2FDevice;

const PARAMETER_SIZE : usize = 32;

pub struct U2FManager {
}

impl U2FManager {
    pub fn new() -> U2FManager {
        U2FManager{}
    }

    pub fn register<F>(&self, timeout_sec: u8, challenge: Vec<u8>, application: Vec<u8>, callback: F)
        where F: FnOnce(io::Result<Vec<u8>>), F: Send + 'static
    {
        if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
            callback(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid parameter sizes")));
            return;
        }

        let timeout = Duration::from_secs(timeout_sec as u64);

        if let Err(e) = thread::Builder::new().name("Register Runloop".to_string()).spawn(move || {
            let manager = u2fhid::platform::new();
            let result = manager.register(timeout, challenge, application);
            callback(result);
        }) {
            callback(Err(e));
        }
    }

    pub fn sign<F>(&self, timeout_sec: u8, challenge: Vec<u8>, application: Vec<u8>, key_handle: Vec<u8>, callback: F)
        where F: FnOnce(io::Result<Vec<u8>>), F: Send + 'static
    {
        if challenge.len() != PARAMETER_SIZE || application.len() != PARAMETER_SIZE {
            callback(Err(io::Error::new(io::ErrorKind::InvalidInput, "Invalid parameter sizes")));
            return;
        }

    }
}

fn u2f_get_key_handle_from_register_response(register_response: &Vec<u8>) -> io::Result<Vec<u8>>
{
    if register_response[0] != 0x05 {
        return Err(io::Error::new(io::ErrorKind::InvalidData, "Reserved byte not set correctly"));
    }

    let key_handle_len = register_response[66] as usize;
    let mut public_key = register_response.clone();
    let mut key_handle = public_key.split_off(67);
    // let attestation = key_handle.split_off(key_handle_len);

    Ok(key_handle)
}

fn main() {
    println!("Searching for keys...");

    let mut challenge = Sha256::new();
    challenge.input_str(r#"{"challenge": "1vQ9mxionq0ngCnjD-wTsv1zUSrGRtFqG2xP09SbZ70", "version": "U2F_V2", "appId": "http://demo.yubico.com"}"#);
    let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    challenge.result(&mut chall_bytes);

    let mut application = Sha256::new();
    application.input_str("http://demo.yubico.com");
    let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    application.result(&mut app_bytes);

    let (tx, rx) = channel();
    let manager = U2FManager::new();

    manager.register(15, chall_bytes, app_bytes, move |result| {
        // Ship back to the main thread
        if let Err(e) = tx.send(result) {
            panic!("Could not send: {}", e);
        }
    });

    let thread_result = match rx.recv() {
        Ok(v) => v,
        Err(e) => panic!("Couldn't read data: {}", e),
    };

    let register_data = match thread_result {
        Ok(v) => v,
        Err(e) => panic!("Register failure: {}", e),
    };

    println!("Register result: {}", base64::encode(&register_data));

    // let key_handle = u2f_get_key_handle_from_register_response(&register_data).unwrap();

    // let mut chall_bytes: Vec<u8> = vec![0; challenge.output_bytes()];
    // challenge.result(&mut chall_bytes);
    // let mut app_bytes: Vec<u8> = vec![0; application.output_bytes()];
    // application.result(&mut app_bytes);

    // manager.sign(15, chall_bytes, app_bytes, key_handle, move|result| {
    //     println!("Sign result: {}", base64::encode(&result.unwrap()));
    // });

    println!("Done.");
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

extern crate svgbob;
extern crate svg;

use svgbob::Grid;
use svgbob::Settings;

fn main() {
    use clap::{Arg, App};
    use std::io::Read;

    let args = App::new("svgbob")
        .version(crate_version!())
        .about("SvgBobRus is an ascii to svg converter")
        .arg(Arg::with_name("input").index(1).help("svgbob text file to parse [default: STDIN]"))
        .arg(Arg::with_name("output")
             .short("o").long("output")
             .takes_value(true)
             .help("where to write svg output [default: STDOUT]"))
        .get_matches();

    let mut bob = String::new();
    if let Some(file) = args.value_of("input") {
        use std::fs::File;
        match File::open(file) {
            Ok(mut f) => {
                f.read_to_string(&mut bob).unwrap();
            },
            Err(e) => {
                use std::io::Write;
                use std::process::exit;

                writeln!(&mut std::io::stderr(), "Failed to open input file {}: {}", file, e).unwrap();
                exit(1);
            }
        }
    } else {
        use std::io;
        io::stdin().read_to_string(&mut bob).unwrap();
    }

    let g = Grid::from_str(&*bob);
    let svg = g.get_svg(&Settings::compact());

    if let Some(file) = args.value_of("output") {
        if let Err(e) = svg::save(file, &svg) {
            use std::io::Write;
            use std::process::exit;

            writeln!(&mut std::io::stderr(), "Failed to write to output file {}: {}", file, e).unwrap();
            exit(2);
        }
    } else {
        println!("{}", svg);
    }
}
<commit_msg>add subCommand name is build<commit_after>#[macro_use]
extern crate clap;
// extern crate regex;

extern crate svgbob;
extern crate svg;

use svgbob::Grid;
use svgbob::Settings;

use clap::ArgMatches;
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::error::Error;
use std::io::Read;
use std::process::exit;

fn main() {
    use clap::{Arg, App, SubCommand};

    let args = App::new("svgbob")
        .version(crate_version!())
        .about("SvgBobRus is an ascii to svg converter")
        .arg(Arg::with_name("input").index(1).help("svgbob text file to parse [default: STDIN]"))
        .arg(Arg::with_name("output")
            .short("o")
            .long("output")
            .takes_value(true)
            .help("where to write svg output [default: STDOUT]"))
        .subcommand(SubCommand::with_name("build")
            .about("Batch convert files to svg.")
            .version("0.0.1")
            .arg(Arg::with_name("input")
                .short("i")
                .long("input")
                .takes_value(true)
                .help("set input file pattern like: *.bob or dir/*.bob"))
            .arg(Arg::with_name("outdir")
                .short("o")
                .long("outdir")
                .takes_value(true)
                .help("set dir of svg files")))
        .get_matches();

    if let Some(sub_build) = args.subcommand_matches("build") {
        match build(sub_build) {
            Ok(_) => {}
            Err(e) => println!("{}", e),
        };
        exit(1);
    }

    let mut bob = String::new();
    if let Some(file) = args.value_of("input") {
        match File::open(file) {
            Ok(mut f) => {
                f.read_to_string(&mut bob).unwrap();
            }
            Err(e) => {
                use std::io::Write;
                use std::process::exit;

                writeln!(&mut std::io::stderr(),
                         "Failed to open input file {}: {}",
                         file,
                         e)
                    .unwrap();
                exit(1);
            }
        }
    } else {
        use std::io;
        io::stdin().read_to_string(&mut bob).unwrap();
    }

    let g = Grid::from_str(&*bob);
    let svg = g.get_svg(&Settings::compact());

    if let Some(file) = args.value_of("output") {
        if let Err(e) = svg::save(file, &svg) {
            use std::io::Write;
            use std::process::exit;

            writeln!(&mut std::io::stderr(),
                     "Failed to write to output file {}: {}",
                     file,
                     e)
                .unwrap();
            exit(2);
        }
    } else {
        println!("{}", svg);
    }
}

// Batch convert files to svg
// use svgbob build -i inputdir/*.bob -o outdir/
fn build(args: &ArgMatches) -> Result<(), Box<Error>> {

    let files_pattern = args.value_of("input").unwrap_or("*.bob");
    let outdir = args.value_of("outdir").unwrap_or("");
    let input_path = Path::new(files_pattern);
    let ext = input_path.extension().unwrap_or(&"bob".as_ref()).to_str().unwrap();

    let input_dir = if input_path.is_dir() {
        input_path.clone()
    } else {
        input_path.parent().unwrap()
    };

    if !input_dir.is_dir() {
        return Err(Box::from(format!("[Error]: No such dir name is {} !",
                                     input_dir.to_string_lossy())));
    }

    let mut out_path = PathBuf::new();
    if outdir == "" {
        out_path = input_dir.to_path_buf();
    } else {
        out_path.push(outdir)
    }

    if !out_path.is_dir() {
        try!(fs::create_dir_all(out_path.clone()));
    }

    let paths = fs::read_dir(input_dir).unwrap();
    for path in paths {
        let tmp_path = path.unwrap().path();
        if tmp_path.is_file() {
            let tmp_ext = tmp_path.extension().unwrap_or(&"".as_ref()).to_str().unwrap();
            if tmp_ext == ext {
                let name = tmp_path.file_stem().unwrap().to_str().unwrap();
                let mut tmp = out_path.clone();
                tmp.push(format!("{}.svg", name));
                println!("{} => {}", tmp_path.display(), tmp.display());
                match convert_file(tmp_path.clone(), tmp) {
                    Ok(_) => {}
                    Err(e) => {
                        println!("{}", e);
                    }
                }
            }
        }
    }

    Ok(())
}

fn convert_file(input: PathBuf, output: PathBuf) -> Result<(), Box<Error>> {
    let mut bob = String::new();
    let mut f = try!(File::open(&input));
    f.read_to_string(&mut bob).unwrap();
    let g = Grid::from_str(&*bob);
    let svg = g.get_svg(&Settings::compact());
    try!(svg::save(&output, &svg));
    Ok(())
}<|endoftext|>