<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 super::{DeterministicRandomId, SiphashIdGenerator, RowId, FieldId, Column, ExtendedTime,
            EventRng, Basics, TimeSteward, FiatEventOperationError, ValidSince,
            StewardRc, FieldRc,
            GenericMutator, Accessor};
use std::collections::{HashMap, BTreeMap};
use std::hash::Hash;
// use std::collections::Bound::{Included, Excluded, Unbounded};
use std::cell::RefCell;
use rand::Rng;
use std::cmp::max;
use std::marker::PhantomData;
use serde::{Serialize, Deserialize};

#[derive (Clone)]
struct Field<B: Basics> {
  data: FieldRc,
  last_change: ExtendedTime<B>,
}

#[derive (Clone)]
struct StewardState<B: Basics> {
  last_event: Option<ExtendedTime<B>>,
  invalid_before: ValidSince<B::Time>,
  field_states: HashMap<FieldId, Field<B>>,
  fiat_events: BTreeMap<ExtendedTime<B>, Event<B>>,
}

struct StewardSettings<B: Basics> {
  settings: Settings <B>,
  constants: B::Constants,
}
#[derive (Clone)]
pub struct Steward<B: Basics> {
  state: StewardState<B>,
  settings: StewardRc<StewardSettings<B>>,
}
type StewardImpl<B> = Steward<B>;
pub struct Snapshot<B: Basics> {
  now: B::Time,
  state: StewardState<B>,
  settings: StewardRc<StewardSettings<B>>,
}
pub struct Mutator<'a, B: Basics> {
  generic: GenericMutator<B>,
  steward: &'a mut StewardImpl<B>,
}
pub struct PredictorAccessor<'a, B: Basics> {
  generic: super::GenericPredictorAccessor <B, Event <B>>,
  steward: &'a StewardImpl<B>,
}
pub type EventFn<B> = for<'d, 'e> Fn(&'d mut Mutator<'e, B>);
pub type Event<B> = StewardRc<EventFn<B>>;
//pub type Predictor<B> = super::Predictor<PredictorFn<B>>;
//pub type PredictorFn<B> = for<'b, 'c> Fn(&'b mut PredictorAccessor<'c, B>, RowId);

make_dynamic_callbacks! (Mutator, PredictorAccessor, DynamicEventFn, DynamicPredictorFn, DynamicPredictor, Settings);

impl<B: Basics> super::Accessor<B> for Snapshot<B> {
  fn generic_data_and_extended_last_change(&self,
                                           id: FieldId)
                                           -> Option<(&FieldRc, &ExtendedTime<B>)> {
    self.state.get(id)
  }
  fn constants(&self) -> &B::Constants {
    &self.settings.constants
  }
  fn unsafe_now(&self) -> &B::Time {
    &self.now
  }
}
impl<'a, B: Basics> super::Accessor<B> for Mutator<'a, B> {
  fn generic_data_and_extended_last_change(&self,
                                           id: FieldId)
                                           -> Option<(&FieldRc, &ExtendedTime<B>)> {
    self.steward.state.get(id)
  }
  fn constants(&self) -> &B::Constants {
    &self.steward.settings.constants
  }
  mutator_common_accessor_methods!(B);
}
impl<'a, B: Basics>  PredictorAccessor<'a, B> {
  fn get_impl (&self, id: FieldId) -> Option<(&FieldRc, &ExtendedTime<B>)> {
    self.steward.state.get(id)
  }
}
impl<'a, B: Basics> super::Accessor<B> for PredictorAccessor<'a, B> {
  predictor_accessor_common_accessor_methods! (B, get_impl);
  fn constants(&self) -> &B::Constants {
    &self.steward.settings.constants
  }
  fn unsafe_now(&self) -> &B::Time {
    &self.internal_now().base
  }
}

impl<B: Basics> super::MomentaryAccessor<B> for Snapshot<B> {}
impl<'a, B: Basics> super::MomentaryAccessor<B> for Mutator<'a, B> {}
impl<'a, B: Basics> PredictorAccessor<'a, B> {
  fn internal_now<'b>(&'b self) -> &'a ExtendedTime<B> {
    self.steward
        .state
        .last_event
        .as_ref()
        .expect("how can we be calling a predictor when there are no fields yet?")
  }
}
impl<'a, B: Basics> super::PredictorAccessor<B> for PredictorAccessor<'a, B> {
  predictor_accessor_common_methods!(B, DynamicEventFn);
}
impl<B: Basics> super::Snapshot<B> for Snapshot<B> {
  fn num_fields(&self) -> usize {
    self.state.field_states.len()
  }
}
use std::collections::hash_map;
pub struct SnapshotIter <'a, B: Basics> (hash_map::Iter <'a, FieldId, Field <B>>);
impl <'a, B: Basics> Iterator for SnapshotIter <'a, B> {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  fn next (&mut self)->Option <Self::Item> {
    (self.0).next().map (| (id, stuff) | (id.clone(), (& stuff.data, & stuff.last_change)))
  }
  fn size_hint (&self)->(usize, Option <usize>) {self.0.size_hint()}
}
impl <'a, B: Basics> IntoIterator for & 'a Snapshot <B> {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  type IntoIter = SnapshotIter <'a, B>;
  fn into_iter (self)->Self::IntoIter {SnapshotIter (self.state.field_states.iter())}
}

impl<'a, B: Basics> super::Mutator<B> for Mutator<'a, B> {
  fn set<C: Column>(&mut self, id: RowId, data: Option<C::FieldType>) {
    self.steward.state.set_opt::<C>(id, data, &self.generic.now);
  }
  mutator_common_methods!(B);
}
impl<'a, B: Basics> Rng for Mutator<'a, B> {
  mutator_rng_methods!();
}

// https://github.com/rust-lang/rfcs/issues/1485
trait Filter<T> {
  fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self;
}
impl<T> Filter<T> for Option<T> {
  fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
    self.and_then(|x| {
      if predicate(&x) {
        Some(x)
      } else {
        None
      }
    })
  }
}

impl<B: Basics> StewardState<B> {
  fn get(&self, id: FieldId) -> Option<(&FieldRc, &ExtendedTime<B>)> {
    self.field_states
        .get(&id)
        .map(|something| (&something.data, &something.last_change))
  }
  fn set<C: Column>(&mut self, id: RowId, value: C::FieldType, time: &ExtendedTime<B>) {
    self.field_states
        .insert(FieldId {
                  row_id: id,
                  column_id: C::column_id(),
                },
                Field {
                  data: StewardRc::new(value),
                  last_change: time.clone(),
                });
  }
  fn remove<C: Column>(&mut self, id: RowId) {
    self.field_states
        .remove(&FieldId {
          row_id: id,
          column_id: C::column_id(),
        });
  }
  fn set_opt<C: Column>(&mut self,
                        id: RowId,
                        value_opt: Option<C::FieldType>,
                        time: &ExtendedTime<B>) {
    if let Some(value) = value_opt {
      self.set::<C>(id, value, time);
    } else {
      self.remove::<C>(id);
    }
  }
}
impl<B: Basics> StewardImpl<B> {
  fn next_event(&self) -> Option<(ExtendedTime<B>, Event<B>)> {
    unimplemented!()/*let first_fiat_event_iter = self.state
                                    .fiat_events
                                    .iter()
                                    .map(|ev| (ev.0.clone(), ev.1.clone()));
    let predicted_events_iter = self.state.field_states.keys().flat_map(|field_id| {
        self.settings.settings.predictors_by_column.get(& field_id.column_id).unwrap_or (& Vec::new()).iter().filter_map (| predictor | {
                let generic;
                {
                  let mut pa = PredictorAccessor {
                    generic: super::GenericPredictorAccessor::new(),
                    steward: self,
                  };
                  (predictor.function)(&mut pa, field_id.row_id);
                  generic = pa.generic;
                }
                let dependencies_hash = generic.dependencies.borrow().1.generate();
                generic.soonest_prediction.map(|(event_base_time, event)| {
                  let extended = super::next_extended_time_of_predicted_event(predictor.predictor_id,
                                                               field_id.row_id,
                                                               dependencies_hash,
                                                               event_base_time,
                                                               &self.state
                                                                    .last_event
                                                                    .as_ref()
                                                                    .expect("how can we be \
                                                                             calling a predictor \
                                                                             when there are no \
                                                                             fields yet?")).expect("this should only fail if the time was in the past, a case that was already ruled out");
                  (extended, event)
                })
          }
        )
    });
    let events_iter = first_fiat_event_iter.chain(predicted_events_iter);
    events_iter.min_by_key(|ev| ev.0.clone())*/
  }

  fn execute_event(&mut self, event_time: ExtendedTime<B>, event: Event<B>) {
    event(&mut Mutator {
      generic: GenericMutator::new(event_time.clone()),
      steward: &mut *self,
    });
    // if it was a fiat event, clean it up:
    self.state.fiat_events.remove(&event_time);
    self.state.last_event = Some(event_time);
  }

  fn update_until_beginning_of(&mut self, target_time: &B::Time) {
    while let Some(ev) = self.next_event().filter(|ev| ev.0.base < *target_time) {
      let (event_time, event) = ev;
      self.execute_event(event_time, event);
    }
  }
}

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

  fn valid_since(&self) -> ValidSince<B::Time> {
    max(self.state.invalid_before.clone(),
        match self.state.last_event {
          None => ValidSince::TheBeginning,
          Some(ref time) => ValidSince::After(time.base.clone()),
        })
  }

  fn new_empty(constants: B::Constants,
               settings: Self::Settings)
               -> Self {
    StewardImpl {
      state: StewardState {
        last_event: None,
        invalid_before: ValidSince::TheBeginning,
        field_states: HashMap::new(),
        fiat_events: BTreeMap::new(),
      },
      settings: StewardRc::new(StewardSettings {
        settings: settings,
        constants: constants,
      }),
    }
  }

  fn from_snapshot<'a, S: super::Snapshot<B>>(snapshot: & 'a S,
                                              settings: Self::Settings)
                                              -> Self
                                          where & 'a S: IntoIterator <Item = super::SnapshotEntry <'a, B>> {
    let mut result = StewardImpl {
      state: StewardState {
        last_event: None,
        invalid_before: ValidSince::Before (snapshot.now().clone()),
        field_states: HashMap::new(),
        fiat_events: BTreeMap::new(),
      },
      settings: StewardRc::new(StewardSettings {
        settings: settings,
        constants: snapshot.constants().clone(),
      }),
    };
    result.state.field_states = snapshot.into_iter().map (| (id, stuff) | {
      if match result.state.last_event {
        None => true,
        Some (ref time) => stuff.1 > time,
      } {result.state.last_event = Some (stuff.1.clone());}
      (id, Field {data: stuff.0.clone(), last_change: stuff.1.clone()})
    }).collect();
    result
  }

  fn insert_fiat_event <E: super::EventFn <B> + Serialize + Deserialize> (&mut self,
                       time: B::Time,
                       id: DeterministicRandomId,
                       event: E)
                       -> Result<(), FiatEventOperationError> {
    if self.valid_since() > time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match self.state.fiat_events.insert(super::extended_time_of_fiat_event(time, id), StewardRc::new (DynamicEventFn ::new (event))) {
      None => Ok(()),
      Some(_) => Err(FiatEventOperationError::InvalidInput),
    }
  }

  fn erase_fiat_event(&mut self,
                      time: &B::Time,
                      id: DeterministicRandomId)
                      -> Result<(), FiatEventOperationError> {
    if self.valid_since() > *time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match self.state.fiat_events.remove(&super::extended_time_of_fiat_event(time.clone(), id)) {
      None => Err(FiatEventOperationError::InvalidInput),
      Some(_) => Ok(()),
    }
  }

  fn snapshot_before<'b>(&'b mut self, time: &'b B::Time) -> Option<Self::Snapshot> {
    if let Some(ref change) = self.state.last_event {
      if change.base >= *time {
        return None;
      }
    }
    self.update_until_beginning_of(time);
    Some(Snapshot {
      now: time.clone(),
      state: self.state.clone(),
      settings: self.settings.clone(),
    })
  }
}
<commit_msg>Fixed next_event lifetime issue<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 super::{DeterministicRandomId, SiphashIdGenerator, RowId, FieldId, Column, ExtendedTime,
            EventRng, Basics, TimeSteward, FiatEventOperationError, ValidSince,
            StewardRc, FieldRc,
            GenericMutator, Accessor};
use std::collections::{HashMap, BTreeMap};
use std::hash::Hash;
// use std::collections::Bound::{Included, Excluded, Unbounded};
use std::cell::RefCell;
use rand::Rng;
use std::cmp::max;
use std::marker::PhantomData;
use serde::{Serialize, Deserialize};

#[derive (Clone)]
struct Field<B: Basics> {
  data: FieldRc,
  last_change: ExtendedTime<B>,
}

#[derive (Clone)]
struct StewardState<B: Basics> {
  last_event: Option<ExtendedTime<B>>,
  invalid_before: ValidSince<B::Time>,
  field_states: HashMap<FieldId, Field<B>>,
  fiat_events: BTreeMap<ExtendedTime<B>, Event<B>>,
}

struct StewardSettings<B: Basics> {
  settings: Settings <B>,
  constants: B::Constants,
}
#[derive (Clone)]
pub struct Steward<B: Basics> {
  state: StewardState<B>,
  settings: StewardRc<StewardSettings<B>>,
}
type StewardImpl<B> = Steward<B>;
pub struct Snapshot<B: Basics> {
  now: B::Time,
  state: StewardState<B>,
  settings: StewardRc<StewardSettings<B>>,
}
pub struct Mutator<'a, B: Basics> {
  generic: GenericMutator<B>,
  steward: &'a mut StewardImpl<B>,
}
pub struct PredictorAccessor<'a, B: Basics> {
  generic: super::GenericPredictorAccessor <B, Event <B>>,
  steward: &'a StewardImpl<B>,
}
pub type EventFn<B> = for<'d, 'e> Fn(&'d mut Mutator<'e, B>);
pub type Event<B> = StewardRc<EventFn<B>>;
//pub type Predictor<B> = super::Predictor<PredictorFn<B>>;
//pub type PredictorFn<B> = for<'b, 'c> Fn(&'b mut PredictorAccessor<'c, B>, RowId);

make_dynamic_callbacks! (Mutator, PredictorAccessor, DynamicEventFn, DynamicPredictorFn, DynamicPredictor, Settings);

impl<B: Basics> super::Accessor<B> for Snapshot<B> {
  fn generic_data_and_extended_last_change(&self,
                                           id: FieldId)
                                           -> Option<(&FieldRc, &ExtendedTime<B>)> {
    self.state.get(id)
  }
  fn constants(&self) -> &B::Constants {
    &self.settings.constants
  }
  fn unsafe_now(&self) -> &B::Time {
    &self.now
  }
}
impl<'a, B: Basics> super::Accessor<B> for Mutator<'a, B> {
  fn generic_data_and_extended_last_change(&self,
                                           id: FieldId)
                                           -> Option<(&FieldRc, &ExtendedTime<B>)> {
    self.steward.state.get(id)
  }
  fn constants(&self) -> &B::Constants {
    &self.steward.settings.constants
  }
  mutator_common_accessor_methods!(B);
}
impl<'a, B: Basics>  PredictorAccessor<'a, B> {
  fn get_impl (&self, id: FieldId) -> Option<(&FieldRc, &ExtendedTime<B>)> {
    self.steward.state.get(id)
  }
}
impl<'a, B: Basics> super::Accessor<B> for PredictorAccessor<'a, B> {
  predictor_accessor_common_accessor_methods! (B, get_impl);
  fn constants(&self) -> &B::Constants {
    &self.steward.settings.constants
  }
  fn unsafe_now(&self) -> &B::Time {
    &self.internal_now().base
  }
}

impl<B: Basics> super::MomentaryAccessor<B> for Snapshot<B> {}
impl<'a, B: Basics> super::MomentaryAccessor<B> for Mutator<'a, B> {}
impl<'a, B: Basics> PredictorAccessor<'a, B> {
  fn internal_now<'b>(&'b self) -> &'a ExtendedTime<B> {
    self.steward
        .state
        .last_event
        .as_ref()
        .expect("how can we be calling a predictor when there are no fields yet?")
  }
}
impl<'a, B: Basics> super::PredictorAccessor<B> for PredictorAccessor<'a, B> {
  predictor_accessor_common_methods!(B, DynamicEventFn);
}
impl<B: Basics> super::Snapshot<B> for Snapshot<B> {
  fn num_fields(&self) -> usize {
    self.state.field_states.len()
  }
}
use std::collections::hash_map;
pub struct SnapshotIter <'a, B: Basics> (hash_map::Iter <'a, FieldId, Field <B>>);
impl <'a, B: Basics> Iterator for SnapshotIter <'a, B> {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  fn next (&mut self)->Option <Self::Item> {
    (self.0).next().map (| (id, stuff) | (id.clone(), (& stuff.data, & stuff.last_change)))
  }
  fn size_hint (&self)->(usize, Option <usize>) {self.0.size_hint()}
}
impl <'a, B: Basics> IntoIterator for & 'a Snapshot <B> {
  type Item = (FieldId, (& 'a FieldRc, & 'a ExtendedTime <B>));
  type IntoIter = SnapshotIter <'a, B>;
  fn into_iter (self)->Self::IntoIter {SnapshotIter (self.state.field_states.iter())}
}

impl<'a, B: Basics> super::Mutator<B> for Mutator<'a, B> {
  fn set<C: Column>(&mut self, id: RowId, data: Option<C::FieldType>) {
    self.steward.state.set_opt::<C>(id, data, &self.generic.now);
  }
  mutator_common_methods!(B);
}
impl<'a, B: Basics> Rng for Mutator<'a, B> {
  mutator_rng_methods!();
}

// https://github.com/rust-lang/rfcs/issues/1485
trait Filter<T> {
  fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self;
}
impl<T> Filter<T> for Option<T> {
  fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
    self.and_then(|x| {
      if predicate(&x) {
        Some(x)
      } else {
        None
      }
    })
  }
}

impl<B: Basics> StewardState<B> {
  fn get(&self, id: FieldId) -> Option<(&FieldRc, &ExtendedTime<B>)> {
    self.field_states
        .get(&id)
        .map(|something| (&something.data, &something.last_change))
  }
  fn set<C: Column>(&mut self, id: RowId, value: C::FieldType, time: &ExtendedTime<B>) {
    self.field_states
        .insert(FieldId {
                  row_id: id,
                  column_id: C::column_id(),
                },
                Field {
                  data: StewardRc::new(value),
                  last_change: time.clone(),
                });
  }
  fn remove<C: Column>(&mut self, id: RowId) {
    self.field_states
        .remove(&FieldId {
          row_id: id,
          column_id: C::column_id(),
        });
  }
  fn set_opt<C: Column>(&mut self,
                        id: RowId,
                        value_opt: Option<C::FieldType>,
                        time: &ExtendedTime<B>) {
    if let Some(value) = value_opt {
      self.set::<C>(id, value, time);
    } else {
      self.remove::<C>(id);
    }
  }
}
impl<B: Basics> StewardImpl<B> {
  fn next_event(&self) -> Option<(ExtendedTime<B>, Event<B>)> {
    let first_fiat_event_iter = self.state
                                    .fiat_events
                                    .iter()
                                    .map(|ev| (ev.0.clone(), ev.1.clone()));
    let empty = Vec::new();
    let predicted_events_iter = self.state.field_states.keys().flat_map(|field_id| {
      let column = field_id.column_id;      self.settings.settings.predictors_by_column.get(&column).unwrap_or(&empty).iter().filter_map (move | predictor | {
        let generic;
        {
          let mut pa = PredictorAccessor {
            generic: super::GenericPredictorAccessor::new(),
            steward: self,
          };
          (predictor.function)(&mut pa, field_id.row_id);
          generic = pa.generic;
        }
        let dependencies_hash = generic.dependencies.borrow().1.generate();
        generic.soonest_prediction.map(|(event_base_time, event)| {
                  let extended = super::next_extended_time_of_predicted_event(predictor.predictor_id,
                                                               field_id.row_id,
                                                               dependencies_hash,
                                                               event_base_time,
                                                               &self.state
                                                                    .last_event
                                                                    .as_ref()
                                                                    .expect("how can we be \
                                                                             calling a predictor \
                                                                             when there are no \
                                                                             fields yet?")).expect("this should only fail if the time was in the past, a case that was already ruled out");
                  (extended, event)
        })
      })
    });
    let events_iter = first_fiat_event_iter;//.chain(predicted_events_iter);
    events_iter.min_by_key(|ev| ev.0.clone())
  }

  fn execute_event(&mut self, event_time: ExtendedTime<B>, event: Event<B>) {
    event(&mut Mutator {
      generic: GenericMutator::new(event_time.clone()),
      steward: &mut *self,
    });
    // if it was a fiat event, clean it up:
    self.state.fiat_events.remove(&event_time);
    self.state.last_event = Some(event_time);
  }

  fn update_until_beginning_of(&mut self, target_time: &B::Time) {
    while let Some(ev) = self.next_event().filter(|ev| ev.0.base < *target_time) {
      let (event_time, event) = ev;
      self.execute_event(event_time, event);
    }
  }
}

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

  fn valid_since(&self) -> ValidSince<B::Time> {
    max(self.state.invalid_before.clone(),
        match self.state.last_event {
          None => ValidSince::TheBeginning,
          Some(ref time) => ValidSince::After(time.base.clone()),
        })
  }

  fn new_empty(constants: B::Constants,
               settings: Self::Settings)
               -> Self {
    StewardImpl {
      state: StewardState {
        last_event: None,
        invalid_before: ValidSince::TheBeginning,
        field_states: HashMap::new(),
        fiat_events: BTreeMap::new(),
      },
      settings: StewardRc::new(StewardSettings {
        settings: settings,
        constants: constants,
      }),
    }
  }

  fn from_snapshot<'a, S: super::Snapshot<B>>(snapshot: & 'a S,
                                              settings: Self::Settings)
                                              -> Self
                                          where & 'a S: IntoIterator <Item = super::SnapshotEntry <'a, B>> {
    let mut result = StewardImpl {
      state: StewardState {
        last_event: None,
        invalid_before: ValidSince::Before (snapshot.now().clone()),
        field_states: HashMap::new(),
        fiat_events: BTreeMap::new(),
      },
      settings: StewardRc::new(StewardSettings {
        settings: settings,
        constants: snapshot.constants().clone(),
      }),
    };
    result.state.field_states = snapshot.into_iter().map (| (id, stuff) | {
      if match result.state.last_event {
        None => true,
        Some (ref time) => stuff.1 > time,
      } {result.state.last_event = Some (stuff.1.clone());}
      (id, Field {data: stuff.0.clone(), last_change: stuff.1.clone()})
    }).collect();
    result
  }

  fn insert_fiat_event <E: super::EventFn <B> + Serialize + Deserialize> (&mut self,
                       time: B::Time,
                       id: DeterministicRandomId,
                       event: E)
                       -> Result<(), FiatEventOperationError> {
    if self.valid_since() > time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match self.state.fiat_events.insert(super::extended_time_of_fiat_event(time, id), StewardRc::new (DynamicEventFn ::new (event))) {
      None => Ok(()),
      Some(_) => Err(FiatEventOperationError::InvalidInput),
    }
  }

  fn erase_fiat_event(&mut self,
                      time: &B::Time,
                      id: DeterministicRandomId)
                      -> Result<(), FiatEventOperationError> {
    if self.valid_since() > *time {
      return Err(FiatEventOperationError::InvalidTime);
    }
    match self.state.fiat_events.remove(&super::extended_time_of_fiat_event(time.clone(), id)) {
      None => Err(FiatEventOperationError::InvalidInput),
      Some(_) => Ok(()),
    }
  }

  fn snapshot_before<'b>(&'b mut self, time: &'b B::Time) -> Option<Self::Snapshot> {
    if let Some(ref change) = self.state.last_event {
      if change.base >= *time {
        return None;
      }
    }
    self.update_until_beginning_of(time);
    Some(Snapshot {
      now: time.clone(),
      state: self.state.clone(),
      settings: self.settings.clone(),
    })
  }
}
<|endoftext|>


<commit_before>use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::str::FromStr;

use libc;

use glib::translate::*;
use glib_sys;

use attributes::Attribute;
use state::State;
use util::utf8_cstr;

pub enum RsvgCssStyles {}

struct Declaration {
    prop_value: String,
    important: bool,
}

// Maps property_name -> Declaration
type DeclarationList = HashMap<String, Declaration>;

pub struct CssStyles {
    selectors_to_declarations: HashMap<String, DeclarationList>,
}

impl CssStyles {
    fn new() -> CssStyles {
        CssStyles {
            selectors_to_declarations: HashMap::new(),
        }
    }

    fn define(&mut self, selector: &str, prop_name: &str, prop_value: &str, important: bool) {
        let decl_list = self
            .selectors_to_declarations
            .entry(selector.to_string())
            .or_insert_with(|| DeclarationList::new());

        match decl_list.entry(prop_name.to_string()) {
            Entry::Occupied(mut e) => {
                let decl = e.get_mut();

                if !decl.important {
                    decl.prop_value = prop_value.to_string();
                    decl.important = important;
                }
            }

            Entry::Vacant(v) => {
                v.insert(Declaration {
                    prop_value: prop_value.to_string(),
                    important,
                });
            }
        }
    }

    pub fn lookup_apply(&self, selector: &str, state: &mut State) -> bool {
        if let Some(decl_list) = self.selectors_to_declarations.get(selector) {
            for (prop_name, declaration) in decl_list.iter() {
                if let Ok(attr) = Attribute::from_str(prop_name) {
                    // FIXME: this is ignoring errors
                    let _ = state.parse_style_pair(
                        attr,
                        &declaration.prop_value,
                        declaration.important,
                    );
                }
            }

            true
        } else {
            false
        }
    }
}

#[no_mangle]
pub extern "C" fn rsvg_css_styles_new() -> *mut RsvgCssStyles {
    Box::into_raw(Box::new(CssStyles::new())) as *mut RsvgCssStyles
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_css_styles_free(raw_styles: *mut RsvgCssStyles) {
    assert!(!raw_styles.is_null());

    Box::from_raw(raw_styles as *mut CssStyles);
}

#[no_mangle]
pub extern "C" fn rsvg_css_styles_define(
    raw_styles: *mut RsvgCssStyles,
    selector: *const libc::c_char,
    prop_name: *const libc::c_char,
    prop_value: *const libc::c_char,
    important: glib_sys::gboolean,
) {
    assert!(!raw_styles.is_null());
    assert!(!selector.is_null());
    assert!(!prop_name.is_null());
    assert!(!prop_value.is_null());

    let styles = unsafe { &mut *(raw_styles as *mut CssStyles) };
    let selector = unsafe { utf8_cstr(selector) };
    let prop_name = unsafe { utf8_cstr(prop_name) };
    let prop_value = unsafe { utf8_cstr(prop_value) };

    styles.define(selector, prop_name, prop_value, from_glib(important));
}
<commit_msg>css.rs: Basic skeleton for the CRDocHandler vtable<commit_after>use std::collections::hash_map::Entry;
use std::collections::HashMap;
use std::str::FromStr;

use libc;

use glib::translate::*;
use glib_sys::{self, gboolean, GList};

use attributes::Attribute;
use croco::*;
use state::State;
use util::utf8_cstr;

pub enum RsvgCssStyles {}

struct Declaration {
    prop_value: String,
    important: bool,
}

// Maps property_name -> Declaration
type DeclarationList = HashMap<String, Declaration>;

pub struct CssStyles {
    selectors_to_declarations: HashMap<String, DeclarationList>,
}

impl CssStyles {
    fn new() -> CssStyles {
        CssStyles {
            selectors_to_declarations: HashMap::new(),
        }
    }

    fn define(&mut self, selector: &str, prop_name: &str, prop_value: &str, important: bool) {
        let decl_list = self
            .selectors_to_declarations
            .entry(selector.to_string())
            .or_insert_with(|| DeclarationList::new());

        match decl_list.entry(prop_name.to_string()) {
            Entry::Occupied(mut e) => {
                let decl = e.get_mut();

                if !decl.important {
                    decl.prop_value = prop_value.to_string();
                    decl.important = important;
                }
            }

            Entry::Vacant(v) => {
                v.insert(Declaration {
                    prop_value: prop_value.to_string(),
                    important,
                });
            }
        }
    }

    pub fn lookup_apply(&self, selector: &str, state: &mut State) -> bool {
        if let Some(decl_list) = self.selectors_to_declarations.get(selector) {
            for (prop_name, declaration) in decl_list.iter() {
                if let Ok(attr) = Attribute::from_str(prop_name) {
                    // FIXME: this is ignoring errors
                    let _ = state.parse_style_pair(
                        attr,
                        &declaration.prop_value,
                        declaration.important,
                    );
                }
            }

            true
        } else {
            false
        }
    }
}

fn init_cr_doc_handler(handler: &mut CRDocHandler) {
    handler.import_style = Some(css_import_style);
    handler.start_selector = Some(css_start_selector);
    handler.end_selector = Some(css_end_selector);
    handler.property = Some(css_property);
    handler.error = Some(css_error);
    handler.unrecoverable_error = Some(css_unrecoverable_error);
}

unsafe extern "C" fn css_import_style(
    a_this: *mut CRDocHandler,
    a_media_list: *mut GList,
    a_uri: CRString,
    a_uri_default_ns: CRString,
    a_location: CRParsingLocation,
) {
    unimplemented!();
}

unsafe extern "C" fn css_start_selector(
    a_this: *mut CRDocHandler,
    a_selector_list: *mut CRSelector,
) {
    unimplemented!();
}

unsafe extern "C" fn css_end_selector(a_this: *mut CRDocHandler, a_selector_list: *mut CRSelector) {
    unimplemented!();
}

unsafe extern "C" fn css_property(
    a_this: *mut CRDocHandler,
    a_name: CRString,
    a_expression: CRTerm,
    a_is_important: gboolean,
) {
    unimplemented!();
}

unsafe extern "C" fn css_error(a_this: *mut CRDocHandler) {
    unimplemented!();
}

unsafe extern "C" fn css_unrecoverable_error(a_this: *mut CRDocHandler) {
    unimplemented!();
}

#[no_mangle]
pub extern "C" fn rsvg_css_styles_new() -> *mut RsvgCssStyles {
    Box::into_raw(Box::new(CssStyles::new())) as *mut RsvgCssStyles
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_css_styles_free(raw_styles: *mut RsvgCssStyles) {
    assert!(!raw_styles.is_null());

    Box::from_raw(raw_styles as *mut CssStyles);
}

#[no_mangle]
pub extern "C" fn rsvg_css_styles_define(
    raw_styles: *mut RsvgCssStyles,
    selector: *const libc::c_char,
    prop_name: *const libc::c_char,
    prop_value: *const libc::c_char,
    important: glib_sys::gboolean,
) {
    assert!(!raw_styles.is_null());
    assert!(!selector.is_null());
    assert!(!prop_name.is_null());
    assert!(!prop_value.is_null());

    let styles = unsafe { &mut *(raw_styles as *mut CssStyles) };
    let selector = unsafe { utf8_cstr(selector) };
    let prop_name = unsafe { utf8_cstr(prop_name) };
    let prop_value = unsafe { utf8_cstr(prop_value) };

    styles.define(selector, prop_name, prop_value, from_glib(important));
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;

use antidote::RwLock;
use irc::client::data::User;
use irc::client::prelude::*;

use chrono::NaiveDateTime;
use humantime::format_duration;
use std::time::Duration;
use time;

use plugin::*;
use FrippyClient;

use self::error::*;
use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::Fail;
use failure::ResultExt;

pub mod database;
use self::database::Database;

#[derive(PluginName)]
pub struct Tell<T: Database, C> {
    tells: RwLock<T>,
    phantom: PhantomData<C>,
}

impl<T: Database, C: FrippyClient> Tell<T, C> {
    pub fn new(db: T) -> Self {
        Tell {
            tells: RwLock::new(db),
            phantom: PhantomData,
        }
    }

    fn tell_command(&self, client: &C, command: PluginCommand) -> Result<String, TellError> {
        if command.tokens.len() < 2 {
            return Ok(self.invalid_command().to_owned());
        }

        let mut online = Vec::new();

        let receivers = command.tokens[0].split(',').filter(|&s| !s.is_empty());
        let sender = command.source;

        let mut no_receiver = true;
        for receiver in receivers {
            if receiver.eq_ignore_ascii_case(client.current_nickname())
                || receiver.eq_ignore_ascii_case(&sender)
            {
                if !online.contains(&receiver) {
                    online.push(receiver);
                }
                continue;
            }

            let channels = client
                .list_channels()
                .expect("The irc crate should not be compiled with the \"nochanlists\" feature");

            let find_receiver = |option: Option<Vec<User>>| {
                option.and_then(|users| {
                    users
                        .into_iter()
                        .find(|user| user.get_nickname().eq_ignore_ascii_case(&receiver))
                })
            };

            if channels
                .iter()
                .map(|channel| client.list_users(&channel))
                .map(find_receiver)
                .any(|option| option.is_some())
            {
                if !online.contains(&receiver) {
                    // online.push(receiver);
                }
                // TODO Change this when https://github.com/aatxe/irc/issues/136 gets resolved
                //continue;
            }

            let tm = time::now().to_timespec();
            let message = command.tokens[1..].join(" ");
            let tell = database::NewTellMessage {
                sender: &sender,
                receiver: &receiver.to_lowercase(),
                time: NaiveDateTime::from_timestamp(tm.sec, 0u32),
                message: &message,
            };

            debug!("Saving tell for {:?}", receiver);
            self.tells.write().insert_tell(&tell)?;
            no_receiver = false;
        }

        Ok(if no_receiver && online.is_empty() {
            String::from("Invalid receiver.")
        } else {
            match online.len() {
                0 => format!("Got it!"),
                1 => format!("{} is currently online.", online[0]),
                _ => format!("{} are currently online.", online.join(", ")),
            }
        })
    }

    fn on_namelist(&self, client: &C, channel: &str) -> Result<(), FrippyError> {
        let receivers = self.tells
            .read()
            .get_receivers()
            .context(FrippyErrorKind::Tell)?;

        if let Some(users) = client.list_users(channel) {
            debug!("Outstanding tells for {:?}", receivers);

            for receiver in users
                .iter()
                .map(|u| u.get_nickname())
                .filter(|u| receivers.iter().any(|r| r == &u.to_lowercase()))
            {
                self.send_tells(client, receiver)?;
            }

            Ok(())
        } else {
            Ok(())
        }
    }

    fn send_tells(&self, client: &C, receiver: &str) -> Result<(), FrippyError> {
        if client.current_nickname() == receiver {
            return Ok(());
        }

        let mut tells = self.tells.write();

        let tell_messages = match tells.get_tells(&receiver.to_lowercase()) {
            Ok(t) => t,
            Err(e) => {
                // This warning only occurs if frippy is built without a database
                #[allow(unreachable_patterns)]
                return match e.kind() {
                    ErrorKind::NotFound => Ok(()),
                    _ => Err(e.context(FrippyErrorKind::Tell))?,
                };
            }
        };

        for tell in tell_messages {
            let now = Duration::new(time::now().to_timespec().sec as u64, 0);
            let dur = now - Duration::new(tell.time.timestamp() as u64, 0);
            let human_dur = format_duration(dur);

            client
                .send_notice(
                    receiver,
                    &format!(
                        "Tell from {} {} ago: {}",
                        tell.sender, human_dur, tell.message
                    ),
                )
                .context(FrippyErrorKind::Connection)?;

            debug!(
                "Sent {:?} from {:?} to {:?}",
                tell.message, tell.sender, receiver
            );
        }

        tells
            .delete_tells(&receiver.to_lowercase())
            .context(FrippyErrorKind::Tell)?;

        Ok(())
    }

    fn invalid_command(&self) -> &str {
        "Incorrect Command. \
         Send \"tell help\" for help."
    }

    fn help(&self) -> &str {
        "Used to send messages to offline users which they will receive when they come online.\r\n
         usage: tell user message\r\n\
         example: tell Foobar Hello!"
    }
}

impl<T: Database, C: FrippyClient> Plugin for Tell<T, C> {
    type Client = C;
    fn execute(&self, client: &Self::Client, message: &Message) -> ExecutionStatus {
        let res = match message.command {
            Command::JOIN(_, _, _) => self.send_tells(client, message.source_nickname().unwrap()),
            Command::NICK(ref nick) => self.send_tells(client, nick),
            Command::PRIVMSG(ref nick, _) => self.send_tells(client, nick),
            Command::Response(resp, ref chan_info, _) => {
                if resp == Response::RPL_NAMREPLY {
                    debug!("NAMREPLY info: {:?}", chan_info);

                    self.on_namelist(client, &chan_info[chan_info.len() - 1])
                } else {
                    Ok(())
                }
            }
            _ => Ok(()),
        };

        match res {
            Ok(_) => ExecutionStatus::Done,
            Err(e) => ExecutionStatus::Err(e),
        }
    }

    fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
        panic!("Tell should not use threading")
    }

    fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
        if command.tokens.is_empty() {
            client
                .send_notice(&command.source, &self.invalid_command())
                .context(FrippyErrorKind::Connection)?;
            return Ok(());
        }

        let sender = command.source.to_owned();

        match command.tokens[0].as_ref() {
            "help" => client
                .send_notice(&command.source, &self.help())
                .context(FrippyErrorKind::Connection),
            _ => match self.tell_command(client, command) {
                Ok(msg) => client
                    .send_notice(&sender, &msg)
                    .context(FrippyErrorKind::Connection),
                Err(e) => client
                    .send_notice(&sender, &e.to_string())
                    .context(FrippyErrorKind::Connection),
            },
        }?;

        Ok(())
    }

    fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
        Err(String::from("This Plugin does not implement any commands."))
    }
}

use std::fmt;
impl<T: Database, C: FrippyClient> fmt::Debug for Tell<T, C> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Tell {{ ... }}")
    }
}

pub mod error {
    #[derive(Copy, Clone, Eq, PartialEq, Debug, Fail, Error)]
    #[error = "TellError"]
    pub enum ErrorKind {
        /// Not found command error
        #[fail(display = "Tell was not found")]
        NotFound,

        /// MySQL error
        #[cfg(feature = "mysql")]
        #[fail(display = "Failed to execute MySQL Query")]
        MysqlError,

        /// No connection error
        #[cfg(feature = "mysql")]
        #[fail(display = "No connection to the database")]
        NoConnection,
    }
}
<commit_msg>Tell: Fix unsent tell on PRIVMSG<commit_after>use std::marker::PhantomData;

use antidote::RwLock;
use irc::client::data::User;
use irc::client::prelude::*;

use chrono::NaiveDateTime;
use humantime::format_duration;
use std::time::Duration;
use time;

use plugin::*;
use FrippyClient;

use self::error::*;
use error::ErrorKind as FrippyErrorKind;
use error::FrippyError;
use failure::Fail;
use failure::ResultExt;
use log::{debug, trace};

pub mod database;
use self::database::Database;

#[derive(PluginName)]
pub struct Tell<T: Database, C> {
    tells: RwLock<T>,
    phantom: PhantomData<C>,
}

impl<T: Database, C: FrippyClient> Tell<T, C> {
    pub fn new(db: T) -> Self {
        Tell {
            tells: RwLock::new(db),
            phantom: PhantomData,
        }
    }

    fn tell_command(&self, client: &C, command: PluginCommand) -> Result<String, TellError> {
        if command.tokens.len() < 2 {
            return Ok(self.invalid_command().to_owned());
        }

        let mut online = Vec::new();

        let receivers = command.tokens[0].split(',').filter(|&s| !s.is_empty());
        let sender = command.source;

        let mut no_receiver = true;
        for receiver in receivers {
            if receiver.eq_ignore_ascii_case(client.current_nickname())
                || receiver.eq_ignore_ascii_case(&sender)
            {
                if !online.contains(&receiver) {
                    online.push(receiver);
                }
                continue;
            }

            let channels = client
                .list_channels()
                .expect("The irc crate should not be compiled with the \"nochanlists\" feature");

            let find_receiver = |option: Option<Vec<User>>| {
                option.and_then(|users| {
                    users
                        .into_iter()
                        .find(|user| user.get_nickname().eq_ignore_ascii_case(&receiver))
                })
            };

            if channels
                .iter()
                .map(|channel| client.list_users(&channel))
                .map(find_receiver)
                .any(|option| option.is_some())
            {
                if !online.contains(&receiver) {
                    // online.push(receiver);
                }
                // TODO Change this when https://github.com/aatxe/irc/issues/136 gets resolved
                //continue;
            }

            let tm = time::now().to_timespec();
            let message = command.tokens[1..].join(" ");
            let tell = database::NewTellMessage {
                sender: &sender,
                receiver: &receiver.to_lowercase(),
                time: NaiveDateTime::from_timestamp(tm.sec, 0u32),
                message: &message,
            };

            debug!("Saving tell for {:?}", receiver);
            self.tells.write().insert_tell(&tell)?;
            no_receiver = false;
        }

        Ok(if no_receiver && online.is_empty() {
            String::from("Invalid receiver.")
        } else {
            match online.len() {
                0 => format!("Got it!"),
                1 => format!("{} is currently online.", online[0]),
                _ => format!("{} are currently online.", online.join(", ")),
            }
        })
    }

    fn on_namelist(&self, client: &C, channel: &str) -> Result<(), FrippyError> {
        let receivers = self
            .tells
            .read()
            .get_receivers()
            .context(FrippyErrorKind::Tell)?;

        if let Some(users) = client.list_users(channel) {
            debug!("Outstanding tells for {:?}", receivers);

            for receiver in users
                .iter()
                .map(|u| u.get_nickname())
                .filter(|u| receivers.iter().any(|r| r == &u.to_lowercase()))
            {
                self.send_tells(client, receiver)?;
            }

            Ok(())
        } else {
            Ok(())
        }
    }

    fn send_tells(&self, client: &C, receiver: &str) -> Result<(), FrippyError> {
        trace!("Checking {} for tells", receiver);

        if client.current_nickname() == receiver {
            return Ok(());
        }

        let mut tells = self.tells.write();

        let tell_messages = match tells.get_tells(&receiver.to_lowercase()) {
            Ok(t) => t,
            Err(e) => {
                // This warning only occurs if frippy is built without a database
                #[allow(unreachable_patterns)]
                return match e.kind() {
                    ErrorKind::NotFound => Ok(()),
                    _ => Err(e.context(FrippyErrorKind::Tell))?,
                };
            }
        };

        for tell in tell_messages {
            let now = Duration::new(time::now().to_timespec().sec as u64, 0);
            let dur = now - Duration::new(tell.time.timestamp() as u64, 0);
            let human_dur = format_duration(dur);

            let message = format!(
                "Tell from {} {} ago: {}",
                tell.sender, human_dur, tell.message
            );

            client
                .send_notice(receiver, &message)
                .context(FrippyErrorKind::Connection)?;

            debug!(
                "Sent {:?} from {:?} to {:?}",
                tell.message, tell.sender, receiver
            );
        }

        tells
            .delete_tells(&receiver.to_lowercase())
            .context(FrippyErrorKind::Tell)?;

        Ok(())
    }

    fn invalid_command(&self) -> &str {
        "Incorrect Command. \
         Send \"tell help\" for help."
    }

    fn help(&self) -> &str {
        "Used to send messages to offline users which they will receive when they come online.\r\n
         usage: tell user message\r\n\
         example: tell Foobar Hello!"
    }
}

impl<T: Database, C: FrippyClient> Plugin for Tell<T, C> {
    type Client = C;
    fn execute(&self, client: &Self::Client, message: &Message) -> ExecutionStatus {
        let res = match message.command {
            Command::JOIN(_, _, _) => self.send_tells(client, message.source_nickname().unwrap()),
            Command::NICK(ref nick) => self.send_tells(client, nick),
            Command::PRIVMSG(_, _) => self.send_tells(client, message.source_nickname().unwrap()),
            Command::Response(resp, ref chan_info, _) => {
                if resp == Response::RPL_NAMREPLY {
                    debug!("NAMREPLY info: {:?}", chan_info);

                    self.on_namelist(client, &chan_info[chan_info.len() - 1])
                } else {
                    Ok(())
                }
            }
            _ => Ok(()),
        };

        match res {
            Ok(_) => ExecutionStatus::Done,
            Err(e) => ExecutionStatus::Err(e),
        }
    }

    fn execute_threaded(&self, _: &Self::Client, _: &Message) -> Result<(), FrippyError> {
        panic!("Tell should not use threading")
    }

    fn command(&self, client: &Self::Client, command: PluginCommand) -> Result<(), FrippyError> {
        if command.tokens.is_empty() {
            client
                .send_notice(&command.source, &self.invalid_command())
                .context(FrippyErrorKind::Connection)?;
            return Ok(());
        }

        let sender = command.source.to_owned();

        match command.tokens[0].as_ref() {
            "help" => client
                .send_notice(&command.source, &self.help())
                .context(FrippyErrorKind::Connection),
            _ => match self.tell_command(client, command) {
                Ok(msg) => client
                    .send_notice(&sender, &msg)
                    .context(FrippyErrorKind::Connection),
                Err(e) => client
                    .send_notice(&sender, &e.to_string())
                    .context(FrippyErrorKind::Connection),
            },
        }?;

        Ok(())
    }

    fn evaluate(&self, _: &Self::Client, _: PluginCommand) -> Result<String, String> {
        Err(String::from("This Plugin does not implement any commands."))
    }
}

use std::fmt;
impl<T: Database, C: FrippyClient> fmt::Debug for Tell<T, C> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Tell {{ ... }}")
    }
}

pub mod error {
    #[derive(Copy, Clone, Eq, PartialEq, Debug, Fail, Error)]
    #[error = "TellError"]
    pub enum ErrorKind {
        /// Not found command error
        #[fail(display = "Tell was not found")]
        NotFound,

        /// MySQL error
        #[cfg(feature = "mysql")]
        #[fail(display = "Failed to execute MySQL Query")]
        MysqlError,

        /// No connection error
        #[cfg(feature = "mysql")]
        #[fail(display = "No connection to the database")]
        NoConnection,
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{ffi::OsString,
          io,
          path::PathBuf,
          process::{self,
                    Command},
          ptr};

use winapi::{shared::minwindef::{DWORD,
                                 FALSE,
                                 LPDWORD},
             um::{handleapi,
                  processthreadsapi,
                  winnt::{HANDLE,
                          PROCESS_QUERY_LIMITED_INFORMATION,
                          PROCESS_TERMINATE}}};

use super::Signal;
use crate::error::{Error,
                   Result};

const STILL_ACTIVE: u32 = 259;

pub type Pid = DWORD;

pub fn become_command(command: PathBuf, args: &[OsString]) -> Result<()> {
    become_child_command(command, args)
}

/// Get process identifier of calling process.
pub fn current_pid() -> u32 { unsafe { processthreadsapi::GetCurrentProcessId() as u32 } }

pub fn handle_from_pid(pid: Pid) -> Option<HANDLE> {
    unsafe {
        let proc_handle = processthreadsapi::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION
                                                         | PROCESS_TERMINATE,
                                                         FALSE,
                                                         pid);

        // we expect this to happen if the process died
        // before OpenProcess completes
        if proc_handle == ptr::null_mut() {
            return None;
        } else {
            return Some(proc_handle);
        }
    }
}

/// Determines if a process is running with the given process identifier.
pub fn is_alive(pid: Pid) -> bool {
    match handle_from_pid(pid) {
        Some(handle) => {
            let exit_status = exit_status(handle).expect("Failed to get exit status");
            unsafe {
                let _ = handleapi::CloseHandle(handle);
            }
            exit_status == STILL_ACTIVE
        }
        None => false,
    }
}

/// Executes a command as a child process and exits with the child's exit code.
///
/// Note that if successful, this function will not return.
///
/// # Failures
///
/// * If the child process cannot be created
fn become_child_command(command: PathBuf, args: &[OsString]) -> Result<()> {
    debug!("Calling child process: ({:?}) {:?}",
           command.display(),
           &args);
    let status = Command::new(command).args(args).status()?;
    // Let's honor the exit codes from the child process we finished running
    process::exit(status.code().unwrap())
}

fn exit_status(handle: HANDLE) -> Result<u32> {
    let mut exit_status: u32 = 0;

    unsafe {
        let ret = processthreadsapi::GetExitCodeProcess(handle, &mut exit_status as LPDWORD);
        if ret == 0 {
            return Err(Error::GetExitCodeProcessFailed(format!(
                "Failed to retrieve Exit Code: {}",
                io::Error::last_os_error()
            )));
        }
    }

    Ok(exit_status)
}
<commit_msg>[PR Feedback] Remove Signal usage from Windows module<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::error::{Error,
                   Result};
use std::{ffi::OsString,
          io,
          path::PathBuf,
          process::{self,
                    Command},
          ptr};
use winapi::{shared::minwindef::{DWORD,
                                 FALSE,
                                 LPDWORD},
             um::{handleapi,
                  processthreadsapi,
                  winnt::{HANDLE,
                          PROCESS_QUERY_LIMITED_INFORMATION,
                          PROCESS_TERMINATE}}};

const STILL_ACTIVE: u32 = 259;

pub type Pid = DWORD;

pub fn become_command(command: PathBuf, args: &[OsString]) -> Result<()> {
    become_child_command(command, args)
}

/// Get process identifier of calling process.
pub fn current_pid() -> u32 { unsafe { processthreadsapi::GetCurrentProcessId() as u32 } }

pub fn handle_from_pid(pid: Pid) -> Option<HANDLE> {
    unsafe {
        let proc_handle = processthreadsapi::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION
                                                         | PROCESS_TERMINATE,
                                                         FALSE,
                                                         pid);

        // we expect this to happen if the process died
        // before OpenProcess completes
        if proc_handle == ptr::null_mut() {
            return None;
        } else {
            return Some(proc_handle);
        }
    }
}

/// Determines if a process is running with the given process identifier.
pub fn is_alive(pid: Pid) -> bool {
    match handle_from_pid(pid) {
        Some(handle) => {
            let exit_status = exit_status(handle).expect("Failed to get exit status");
            unsafe {
                let _ = handleapi::CloseHandle(handle);
            }
            exit_status == STILL_ACTIVE
        }
        None => false,
    }
}

/// Executes a command as a child process and exits with the child's exit code.
///
/// Note that if successful, this function will not return.
///
/// # Failures
///
/// * If the child process cannot be created
fn become_child_command(command: PathBuf, args: &[OsString]) -> Result<()> {
    debug!("Calling child process: ({:?}) {:?}",
           command.display(),
           &args);
    let status = Command::new(command).args(args).status()?;
    // Let's honor the exit codes from the child process we finished running
    process::exit(status.code().unwrap())
}

fn exit_status(handle: HANDLE) -> Result<u32> {
    let mut exit_status: u32 = 0;

    unsafe {
        let ret = processthreadsapi::GetExitCodeProcess(handle, &mut exit_status as LPDWORD);
        if ret == 0 {
            return Err(Error::GetExitCodeProcessFailed(format!(
                "Failed to retrieve Exit Code: {}",
                io::Error::last_os_error()
            )));
        }
    }

    Ok(exit_status)
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{ffi::OsString,
          io,
          path::PathBuf,
          process::{self,
                    Command},
          ptr};

use winapi::{shared::minwindef::{DWORD,
                                 FALSE,
                                 LPDWORD},
             um::{handleapi,
                  processthreadsapi,
                  winnt::{HANDLE,
                          PROCESS_QUERY_LIMITED_INFORMATION,
                          PROCESS_TERMINATE}}};

use super::Signal;
use crate::error::{Error,
                   Result};

const STILL_ACTIVE: u32 = 259;

pub type Pid = DWORD;
pub type SignalCode = DWORD;

pub fn become_command(command: PathBuf, args: &[OsString]) -> Result<()> {
    become_child_command(command, args)
}

/// Get process identifier of calling process.
pub fn current_pid() -> u32 { unsafe { processthreadsapi::GetCurrentProcessId() as u32 } }

pub fn handle_from_pid(pid: Pid) -> Option<HANDLE> {
    unsafe {
        let proc_handle = processthreadsapi::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION
                                                         | PROCESS_TERMINATE,
                                                         FALSE,
                                                         pid);

        // we expect this to happen if the process died
        // before OpenProcess completes
        if proc_handle == ptr::null_mut() {
            return None;
        } else {
            return Some(proc_handle);
        }
    }
}

/// Determines if a process is running with the given process identifier.
pub fn is_alive(pid: Pid) -> bool {
    match handle_from_pid(pid) {
        Some(handle) => {
            let exit_status = exit_status(handle).expect("Failed to get exit status");
            unsafe {
                let _ = handleapi::CloseHandle(handle);
            }
            exit_status == STILL_ACTIVE
        }
        None => false,
    }
}

pub fn signal(pid: Pid, signal: Signal) -> Result<()> { Ok(()) }

/// Executes a command as a child process and exits with the child's exit code.
///
/// Note that if successful, this function will not return.
///
/// # Failures
///
/// * If the child process cannot be created
fn become_child_command(command: PathBuf, args: &[OsString]) -> Result<()> {
    debug!("Calling child process: ({:?}) {:?}",
           command.display(),
           &args);
    let status = Command::new(command).args(args).status()?;
    // Let's honor the exit codes from the child process we finished running
    process::exit(status.code().unwrap())
}

fn exit_status(handle: HANDLE) -> Result<u32> {
    let mut exit_status: u32 = 0;

    unsafe {
        let ret = processthreadsapi::GetExitCodeProcess(handle, &mut exit_status as LPDWORD);
        if ret == 0 {
            return Err(Error::GetExitCodeProcessFailed(format!(
                "Failed to retrieve Exit Code: {}",
                io::Error::last_os_error()
            )));
        }
    }

    Ok(exit_status)
}
<commit_msg>Remove `signal` function from Windows<commit_after>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{ffi::OsString,
          io,
          path::PathBuf,
          process::{self,
                    Command},
          ptr};

use winapi::{shared::minwindef::{DWORD,
                                 FALSE,
                                 LPDWORD},
             um::{handleapi,
                  processthreadsapi,
                  winnt::{HANDLE,
                          PROCESS_QUERY_LIMITED_INFORMATION,
                          PROCESS_TERMINATE}}};

use super::Signal;
use crate::error::{Error,
                   Result};

const STILL_ACTIVE: u32 = 259;

pub type Pid = DWORD;
pub type SignalCode = DWORD;

pub fn become_command(command: PathBuf, args: &[OsString]) -> Result<()> {
    become_child_command(command, args)
}

/// Get process identifier of calling process.
pub fn current_pid() -> u32 { unsafe { processthreadsapi::GetCurrentProcessId() as u32 } }

pub fn handle_from_pid(pid: Pid) -> Option<HANDLE> {
    unsafe {
        let proc_handle = processthreadsapi::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION
                                                         | PROCESS_TERMINATE,
                                                         FALSE,
                                                         pid);

        // we expect this to happen if the process died
        // before OpenProcess completes
        if proc_handle == ptr::null_mut() {
            return None;
        } else {
            return Some(proc_handle);
        }
    }
}

/// Determines if a process is running with the given process identifier.
pub fn is_alive(pid: Pid) -> bool {
    match handle_from_pid(pid) {
        Some(handle) => {
            let exit_status = exit_status(handle).expect("Failed to get exit status");
            unsafe {
                let _ = handleapi::CloseHandle(handle);
            }
            exit_status == STILL_ACTIVE
        }
        None => false,
    }
}

/// Executes a command as a child process and exits with the child's exit code.
///
/// Note that if successful, this function will not return.
///
/// # Failures
///
/// * If the child process cannot be created
fn become_child_command(command: PathBuf, args: &[OsString]) -> Result<()> {
    debug!("Calling child process: ({:?}) {:?}",
           command.display(),
           &args);
    let status = Command::new(command).args(args).status()?;
    // Let's honor the exit codes from the child process we finished running
    process::exit(status.code().unwrap())
}

fn exit_status(handle: HANDLE) -> Result<u32> {
    let mut exit_status: u32 = 0;

    unsafe {
        let ret = processthreadsapi::GetExitCodeProcess(handle, &mut exit_status as LPDWORD);
        if ret == 0 {
            return Err(Error::GetExitCodeProcessFailed(format!(
                "Failed to retrieve Exit Code: {}",
                io::Error::last_os_error()
            )));
        }
    }

    Ok(exit_status)
}
<|endoftext|>


<commit_before>use osmpbfreader::objects::{NodeId, WayId};
use categorize::*;
use models::*;
use std;
use std::collections::{HashMap, HashSet};

// Way as represented in OpenStreetMap
struct Way {
    id: WayId,
    nodes: Vec<NodeId>,
    properties: EdgeProperties,
}

struct Reader {
    nodes: HashMap<NodeId, Node>,
    ways: Vec<Way>,
    nodes_to_keep: HashSet<NodeId>,
}

impl Reader {
    fn new() -> Reader {
        Reader {
            nodes: HashMap::new(),
            ways: Vec::new(),
            nodes_to_keep: HashSet::new(),
        }
    }

    fn count_nodes_uses(&mut self) {
        for way in &self.ways {
            for (i, node_id) in way.nodes.iter().enumerate() {
                if let Some(node) = self.nodes.get_mut(node_id) {
                    // Count double extremities nodes
                    if i == 0 || i == way.nodes.len() - 1 {
                        node.uses += 2;
                    } else {
                        node.uses += 1;
                    }
                } else {
                    panic!("Missing node, id: {:?}", node_id)
                }
            }
        }
    }

    fn split_way(&self, way: &Way) -> Vec<Edge> {
        let mut result = Vec::new();

        let mut source = NodeId(0);
        let mut geometry = Vec::new();
        for (i, &node_id) in way.nodes.iter().enumerate() {
            let node = self.nodes[&node_id];
            if i == 0 {
                source = node_id;
                geometry.push(node.coord);
            } else {
                geometry.push(node.coord);

                if node.uses > 1 {
                    result.push(Edge {
                        id: way.id,
                        source,
                        target: node_id,
                        geometry,
                        properties: way.properties,
                    });

                    source = node_id;
                    geometry = vec![node.coord];
                }
            }
        }
        result
    }

    fn read_ways(&mut self, file: std::fs::File) {
        let mut pbf = osmpbfreader::OsmPbfReader::new(file);
        for obj in pbf.iter() {
            if let Ok(osmpbfreader::OsmObj::Way(way)) = obj {
                let mut properties = EdgeProperties::default();
                for (key, val) in way.tags.iter() {
                    properties.update(key.to_string(), val.to_string());
                }
                properties.normalize();
                if properties.accessible() {
                    for node in &way.nodes {
                        self.nodes_to_keep.insert(node.clone());
                    }
                    self.ways.push(Way {
                        id: way.id,
                        nodes: way.nodes,
                        properties,
                    });
                }
            }
        }
    }

    fn read_nodes(&mut self, file: std::fs::File) {
        let mut pbf = osmpbfreader::OsmPbfReader::new(file);
        self.nodes.reserve(self.nodes_to_keep.len());
        for obj in pbf.iter() {
            if let Ok(osmpbfreader::OsmObj::Node(node)) = obj {
                if self.nodes_to_keep.contains(&node.id) {
                    self.nodes_to_keep.remove(&node.id);
                    let mut n = Node::default();
                    n.id = node.id;
                    n.coord = Coord {
                        lon: node.lon(),
                        lat: node.lat(),
                    };
                    self.nodes.insert(node.id, n);
                }
            }
        }
    }

    fn nodes(self) -> Vec<Node> {
        self.nodes
            .into_iter()
            .map(|(_, node)| node)
            .filter(|node| node.uses > 1)
            .collect()
    }

    fn edges(&self) -> Vec<Edge> {
        self.ways
            .iter()
            .flat_map(|way| self.split_way(way))
            .collect()
    }
}

// Read all the nodes and ways of the osm.pbf file
pub fn read(filename: &str) -> Result<(Vec<Node>, Vec<Edge>), String> {
    let mut r = Reader::new();
    let path = std::path::Path::new(filename);
    let file = std::fs::File::open(&path).map_err(|e| e.to_string())?;
    r.read_ways(file);
    let file_nodes = std::fs::File::open(&path).map_err(|e| e.to_string())?;
    r.read_nodes(file_nodes);
    r.count_nodes_uses();
    let edges = r.edges();
    Ok((r.nodes(), edges))
}

#[test]
fn test_real_all() {
    let (nodes, ways) = read("src/osm4routing/test_data/minimal.osm.pbf").unwrap();
    assert_eq!(2, nodes.len());
    assert_eq!(1, ways.len());
}

#[test]
fn test_count_nodes() {
    let ways = vec![Way {
        id: WayId(0),
        nodes: vec![NodeId(1), NodeId(2), NodeId(3)],
        properties: EdgeProperties::default(),
    }];
    let mut nodes = HashMap::new();
    nodes.insert(NodeId(1), Node::default());
    nodes.insert(NodeId(2), Node::default());
    nodes.insert(NodeId(3), Node::default());
    let mut r = Reader {
        ways,
        nodes,
        nodes_to_keep: HashSet::new(),
    };
    r.count_nodes_uses();
    assert_eq!(2, r.nodes[&NodeId(1)].uses);
    assert_eq!(1, r.nodes[&NodeId(2)].uses);
    assert_eq!(2, r.nodes[&NodeId(3)].uses);

    assert_eq!(2, r.nodes().len());
}

#[test]
fn test_split() {
    let mut nodes = HashMap::new();
    nodes.insert(NodeId(1), Node::default());
    nodes.insert(NodeId(2), Node::default());
    nodes.insert(NodeId(3), Node::default());
    nodes.insert(NodeId(4), Node::default());
    nodes.insert(NodeId(5), Node::default());
    let ways = vec![
        Way {
            id: WayId(0),
            nodes: vec![NodeId(1), NodeId(2), NodeId(3)],
            properties: EdgeProperties::default(),
        },
        Way {
            id: WayId(0),
            nodes: vec![NodeId(4), NodeId(5), NodeId(2)],
            properties: EdgeProperties::default(),
        },
    ];
    let mut r = Reader {
        nodes,
        ways,
        nodes_to_keep: HashSet::new(),
    };
    r.count_nodes_uses();
    let edges = r.edges();
    assert_eq!(3, edges.len());
}

#[test]
fn test_wrong_file() {
    let r = read("i hope you have no file name like this one");
    assert!(r.is_err());
}
<commit_msg>Clippy<commit_after>use categorize::*;
use models::*;
use osmpbfreader::objects::{NodeId, WayId};
use std;
use std::collections::{HashMap, HashSet};

// Way as represented in OpenStreetMap
struct Way {
    id: WayId,
    nodes: Vec<NodeId>,
    properties: EdgeProperties,
}

struct Reader {
    nodes: HashMap<NodeId, Node>,
    ways: Vec<Way>,
    nodes_to_keep: HashSet<NodeId>,
}

impl Reader {
    fn new() -> Reader {
        Reader {
            nodes: HashMap::new(),
            ways: Vec::new(),
            nodes_to_keep: HashSet::new(),
        }
    }

    fn count_nodes_uses(&mut self) {
        for way in &self.ways {
            for (i, node_id) in way.nodes.iter().enumerate() {
                if let Some(node) = self.nodes.get_mut(node_id) {
                    // Count double extremities nodes
                    if i == 0 || i == way.nodes.len() - 1 {
                        node.uses += 2;
                    } else {
                        node.uses += 1;
                    }
                } else {
                    panic!("Missing node, id: {:?}", node_id)
                }
            }
        }
    }

    fn split_way(&self, way: &Way) -> Vec<Edge> {
        let mut result = Vec::new();

        let mut source = NodeId(0);
        let mut geometry = Vec::new();
        for (i, &node_id) in way.nodes.iter().enumerate() {
            let node = self.nodes[&node_id];
            if i == 0 {
                source = node_id;
                geometry.push(node.coord);
            } else {
                geometry.push(node.coord);

                if node.uses > 1 {
                    result.push(Edge {
                        id: way.id,
                        source,
                        target: node_id,
                        geometry,
                        properties: way.properties,
                    });

                    source = node_id;
                    geometry = vec![node.coord];
                }
            }
        }
        result
    }

    fn read_ways(&mut self, file: std::fs::File) {
        let mut pbf = osmpbfreader::OsmPbfReader::new(file);
        for obj in pbf.iter() {
            if let Ok(osmpbfreader::OsmObj::Way(way)) = obj {
                let mut properties = EdgeProperties::default();
                for (key, val) in way.tags.iter() {
                    properties.update(key.to_string(), val.to_string());
                }
                properties.normalize();
                if properties.accessible() {
                    for node in &way.nodes {
                        self.nodes_to_keep.insert(*node);
                    }
                    self.ways.push(Way {
                        id: way.id,
                        nodes: way.nodes,
                        properties,
                    });
                }
            }
        }
    }

    fn read_nodes(&mut self, file: std::fs::File) {
        let mut pbf = osmpbfreader::OsmPbfReader::new(file);
        self.nodes.reserve(self.nodes_to_keep.len());
        for obj in pbf.iter() {
            if let Ok(osmpbfreader::OsmObj::Node(node)) = obj {
                if self.nodes_to_keep.contains(&node.id) {
                    self.nodes_to_keep.remove(&node.id);
                    self.nodes.insert(
                        node.id,
                        Node {
                            id: node.id,
                            coord: Coord {
                                lon: node.lon(),
                                lat: node.lat(),
                            },
                            uses: 0,
                        },
                    );
                }
            }
        }
    }

    fn nodes(self) -> Vec<Node> {
        self.nodes
            .into_iter()
            .map(|(_, node)| node)
            .filter(|node| node.uses > 1)
            .collect()
    }

    fn edges(&self) -> Vec<Edge> {
        self.ways
            .iter()
            .flat_map(|way| self.split_way(way))
            .collect()
    }
}

// Read all the nodes and ways of the osm.pbf file
pub fn read(filename: &str) -> Result<(Vec<Node>, Vec<Edge>), String> {
    let mut r = Reader::new();
    let path = std::path::Path::new(filename);
    let file = std::fs::File::open(&path).map_err(|e| e.to_string())?;
    r.read_ways(file);
    let file_nodes = std::fs::File::open(&path).map_err(|e| e.to_string())?;
    r.read_nodes(file_nodes);
    r.count_nodes_uses();
    let edges = r.edges();
    Ok((r.nodes(), edges))
}

#[test]
fn test_real_all() {
    let (nodes, ways) = read("src/osm4routing/test_data/minimal.osm.pbf").unwrap();
    assert_eq!(2, nodes.len());
    assert_eq!(1, ways.len());
}

#[test]
fn test_count_nodes() {
    let ways = vec![Way {
        id: WayId(0),
        nodes: vec![NodeId(1), NodeId(2), NodeId(3)],
        properties: EdgeProperties::default(),
    }];
    let mut nodes = HashMap::new();
    nodes.insert(NodeId(1), Node::default());
    nodes.insert(NodeId(2), Node::default());
    nodes.insert(NodeId(3), Node::default());
    let mut r = Reader {
        ways,
        nodes,
        nodes_to_keep: HashSet::new(),
    };
    r.count_nodes_uses();
    assert_eq!(2, r.nodes[&NodeId(1)].uses);
    assert_eq!(1, r.nodes[&NodeId(2)].uses);
    assert_eq!(2, r.nodes[&NodeId(3)].uses);

    assert_eq!(2, r.nodes().len());
}

#[test]
fn test_split() {
    let mut nodes = HashMap::new();
    nodes.insert(NodeId(1), Node::default());
    nodes.insert(NodeId(2), Node::default());
    nodes.insert(NodeId(3), Node::default());
    nodes.insert(NodeId(4), Node::default());
    nodes.insert(NodeId(5), Node::default());
    let ways = vec![
        Way {
            id: WayId(0),
            nodes: vec![NodeId(1), NodeId(2), NodeId(3)],
            properties: EdgeProperties::default(),
        },
        Way {
            id: WayId(0),
            nodes: vec![NodeId(4), NodeId(5), NodeId(2)],
            properties: EdgeProperties::default(),
        },
    ];
    let mut r = Reader {
        nodes,
        ways,
        nodes_to_keep: HashSet::new(),
    };
    r.count_nodes_uses();
    let edges = r.edges();
    assert_eq!(3, edges.len());
}

#[test]
fn test_wrong_file() {
    let r = read("i hope you have no file name like this one");
    assert!(r.is_err());
}
<|endoftext|>


<commit_before>use std::mem;

use self::BufferedParserState::{Beginning, Middle, EndMatch, EndFail};
use self::MatchResult::{Undecided, Committed, Matched, Failed};
use self::ConstantParserState::{AtOffset, AtEnd};

use std::marker::PhantomData;

// ----------- Types with lifetimes -------------

// Borrowing encoding of paramaterized types from
// https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md#encoding-higher-kinded-types

pub trait TypeWithLifetime<'a> {
    type Type;
}

pub type At<'a,T> where T: TypeWithLifetime<'a> = T::Type;

pub struct Always<T> (T);

impl<'a,T> TypeWithLifetime<'a> for Always<T> {
    type Type = T;
}

pub type Unit = Always<()>;

// ----------- Types for consumers ------------

pub trait Consumer<T> where T: for<'a> TypeWithLifetime<'a> {
    fn accept<'a>(&mut self, arg: At<'a,T>);
}

struct DiscardConsumer<T> (PhantomData<T>);

impl<T> Consumer<T> for DiscardConsumer<T> where T: for<'a> TypeWithLifetime<'a> {
    fn accept<'a>(&mut self, _: At<'a,T>) {}
}

impl<T> DiscardConsumer<T> {
    fn new() -> DiscardConsumer<T> {
        DiscardConsumer(PhantomData)
    }
}

// ----------- Types for parsers ------------

// State machine transitions are:
//
// init -Undecided->  init
// init -Committed->  committed
// init -Matched(s)-> matched
// init -Failed(b)->  failed(b)
//
// committed -Committed->     committed
// committed -Matched(s)->    matched
// committed -Failed(false)-> failed(false)
//
// matched -Matched(s)-> matched
//
// failed(b) -Failed(b)-> failed(b)
//
// The Failed(b) action carries a boolean indicating if backtracking is allowed.
// Note that there is no transition . -Committed-> . -Failed(true)-> . so
// once a parser has committed, we can clean up space associated with backtracking.

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum MatchResult<T> {
    Undecided,
    Committed,
    Matched(T),
    Failed(bool),
}

pub trait Parser<S,T> where S: for<'a> TypeWithLifetime<'a>, T: for<'a> TypeWithLifetime<'a> {
    // If push_to returns Undecided or Failed(true), it is side-effect-free
    // In the case where T is "list-like" (e.g. &str or &[T])
    // push_to(nil) is a no-op
    // push_to(a ++ b) is the same as push_to(a); push_to(b)
    fn push_to<'a>(&mut self, value: At<'a,S>, downstream: &mut Consumer<T>) -> MatchResult<At<'a,S>>;
    // Resets the parser state back to its initial state
    // Returns true if there was a match.
    fn done_to(&mut self, downstream: &mut Consumer<T>) -> bool;
    // Helper methods
    fn push<'a>(&mut self, value: At<'a,S>) -> MatchResult<At<'a,S>> {
        self.push_to(value, &mut DiscardConsumer::new())
    }
    fn done(&mut self) -> bool {
        self.done_to(&mut DiscardConsumer::new())
    }
}

pub trait BufferableMatcher<S,T> where S: for<'a> TypeWithLifetime<'a>, T: Parser<S,S> {
    fn buffer(self) -> T;
}

// ----------- Always commit ---------------

pub struct CommittedParser<P> {
    parser: P,
}

impl<S,T,P> Parser<S,T> for CommittedParser<P> where P: Parser<S,T>, S: for<'a> TypeWithLifetime<'a>, T: for<'a> TypeWithLifetime<'a>  {
    fn push_to<'a>(&mut self, value: At<'a,S>, downstream: &mut Consumer<T>) -> MatchResult<At<'a,S>> {
        match self.parser.push_to(value, downstream) {
            Undecided     => Committed,
            Committed     => Committed,
            Matched(rest) => Matched(rest),
            Failed(_)     => Failed(false),
        }
    }
    fn done_to(&mut self, downstream: &mut Consumer<T>) -> bool {
        self.parser.done_to(downstream)
    }
}

// ----------- Sequencing ---------------

pub struct AndThenParser<L,R> {
    lhs: L,
    rhs: CommittedParser<R>,
    in_lhs: bool,
}

impl<S,T,L,R> Parser<S,T> for AndThenParser<L,R> where L: Parser<S,T>, R: Parser<S,T>, S: for<'a> TypeWithLifetime<'a>, T: for<'a> TypeWithLifetime<'a>  {
    fn push_to<'a>(&mut self, value: At<'a,S>, downstream: &mut Consumer<T>) -> MatchResult<At<'a,S>> {
        if self.in_lhs {
            match self.lhs.push_to(value, downstream) {
                Undecided     => Undecided,
                Committed     => Committed,
                Matched(rest) => { self.in_lhs = false; self.rhs.push_to(rest, downstream) },
                Failed(b)     => Failed(b),
            }
        } else {
            self.rhs.push_to(value, downstream)
        }
    }
    fn done_to(&mut self, downstream: &mut Consumer<T>) -> bool {
        self.lhs.done_to(downstream) && self.rhs.done_to(downstream)
    }
}

// ----------- Matching strings -------------

pub struct Str;

impl<'a> TypeWithLifetime<'a> for Str {
    type Type = &'a str;
}

// ----------- Constant parsers -------------

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum ConstantParserState {
    AtOffset(usize),
    AtEnd(bool),
}

pub struct ConstantParser {
    constant: String,
    state: ConstantParserState,
}

impl Parser<Str,Unit> for ConstantParser {
    fn push_to<'a>(&mut self, string: &'a str, downstream: &mut Consumer<Unit>) -> MatchResult<&'a str> {
        match self.state {
            AtOffset(index) if string.starts_with(&self.constant[index..]) => { downstream.accept(()); self.state = AtEnd(true); Matched(&string[(self.constant.len() - index)..]) },
            AtOffset(index) if self.constant[index..].starts_with(string)  => { self.state = AtOffset(index + string.len()); Undecided },
            AtOffset(_)                                                    => { self.state = AtEnd(false); Failed(true) },
            AtEnd(true)                                                    => { Matched(string) },
            AtEnd(false)                                                   => { Failed(true) },
        }
    }
    fn done_to(&mut self, _: &mut Consumer<Unit>) -> bool {
        let result = self.state == AtEnd(true);
        self.state = AtOffset(0);
        result
    }
}

pub fn constant(string: String) -> ConstantParser {
    ConstantParser{ constant: string, state: AtOffset(0) }
}

// If m is a Parser<Str,Unit> then m.buffer() is a Parser<Str,Str>.
// It does as little buffering as it can, but it does allocate as buffer for the case
// where the boundary marker of the input is misaligned with that of the parser.
// For example, m is matching string literals, and the input is '"abc' followed by 'def"'
// we have to buffer up '"abc'.

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
enum BufferedParserState {
    Beginning,
    Middle(String),
    EndMatch,
    EndFail(bool),
}

pub struct BufferedParser<P> {
    parser: P,
    state: BufferedParserState,
}

impl<P> Parser<Str,Str> for BufferedParser<P> where P: Parser<Str,Unit> {
    fn push_to<'a>(&mut self, string: &'a str, downstream: &mut Consumer<Str>) -> MatchResult<&'a str> {
        match mem::replace(&mut self.state, EndMatch) {
            Beginning => {
                let result = self.parser.push(string);
                match result {
                    Undecided     => self.state = Middle(String::from(string)),
                    Committed     => self.state = Middle(String::from(string)),
                    Failed(b)     => self.state = EndFail(b),
                    Matched(rest) => downstream.accept(&string[..(string.len()-rest.len())]),
                }
                result
            },
            Middle(mut buffer) => {
                let result = self.parser.push(string);
                match result {
                    Undecided     => { buffer.push_str(string); self.state = Middle(buffer); },
                    Committed     => { buffer.push_str(string); self.state = Middle(buffer); },
                    Failed(b)     => { self.state = EndFail(b); },
                    Matched(rest) => { buffer.push_str(&string[..(string.len()-rest.len())]); downstream.accept(&*buffer); },
                }
                result
            }
            EndMatch => Matched(string),
            EndFail(b) => Failed(b),
        }
    }
    fn done_to(&mut self, downstream: &mut Consumer<Str>) -> bool {
        let result = self.parser.done();
        if result { if let Middle(ref buffer) = self.state { downstream.accept(&*buffer) } }
        self.state = Beginning;
        result
    }
}

#[test]
fn test_constant() {
    let mut parser = constant(String::from("abc"));
    assert_eq!(parser.done(), false);
    assert_eq!(parser.push("fred"), Failed(true));
    assert_eq!(parser.done(), false);
    assert_eq!(parser.push("abcdef"), Matched("def"));
    assert_eq!(parser.done(), true);
    assert_eq!(parser.push("a"), Undecided);
    assert_eq!(parser.done(), false);
    assert_eq!(parser.push("ab"), Undecided);
    assert_eq!(parser.push("cd"), Matched("d"));
    assert_eq!(parser.done(), true);
}
<commit_msg>Fixed comment.<commit_after>use std::mem;

use self::BufferedParserState::{Beginning, Middle, EndMatch, EndFail};
use self::MatchResult::{Undecided, Committed, Matched, Failed};
use self::ConstantParserState::{AtOffset, AtEnd};

use std::marker::PhantomData;

// ----------- Types with lifetimes -------------

// Borrowing encoding of paramaterized types from
// https://github.com/rust-lang/rfcs/blob/master/text/0195-associated-items.md#encoding-higher-kinded-types

pub trait TypeWithLifetime<'a> {
    type Type;
}

pub type At<'a,T> where T: TypeWithLifetime<'a> = T::Type;

pub struct Always<T> (T);

impl<'a,T> TypeWithLifetime<'a> for Always<T> {
    type Type = T;
}

pub type Unit = Always<()>;

// ----------- Types for consumers ------------

pub trait Consumer<T> where T: for<'a> TypeWithLifetime<'a> {
    fn accept<'a>(&mut self, arg: At<'a,T>);
}

struct DiscardConsumer<T> (PhantomData<T>);

impl<T> Consumer<T> for DiscardConsumer<T> where T: for<'a> TypeWithLifetime<'a> {
    fn accept<'a>(&mut self, _: At<'a,T>) {}
}

impl<T> DiscardConsumer<T> {
    fn new() -> DiscardConsumer<T> {
        DiscardConsumer(PhantomData)
    }
}

// ----------- Types for parsers ------------

// State machine transitions are:
//
// init -Undecided->  init
// init -Committed->  committed
// init -Matched(s)-> matched
// init -Failed(b)->  failed(b)
//
// committed -Committed->     committed
// committed -Matched(s)->    matched
// committed -Failed(false)-> failed(false)
//
// matched -Matched(s)-> matched
//
// failed(b) -Failed(b)-> failed(b)
//
// The Failed(b) action carries a boolean indicating if backtracking is allowed.
// Note that there is no transition . -Committed-> . -Failed(true)-> . so
// once a parser has committed, we can clean up space associated with backtracking.

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum MatchResult<T> {
    Undecided,
    Committed,
    Matched(T),
    Failed(bool),
}

pub trait Parser<S,T> where S: for<'a> TypeWithLifetime<'a>, T: for<'a> TypeWithLifetime<'a> {
    // If push_to returns Undecided or Failed(true), it is side-effect-free
    // In the case where T is "list-like" (e.g. &str or &[T])
    // push_to(nil,d) is a no-op
    // push_to(a ++ b, d) is the same as push_to(a,d); push_to(b,d)
    fn push_to<'a>(&mut self, value: At<'a,S>, downstream: &mut Consumer<T>) -> MatchResult<At<'a,S>>;
    // Resets the parser state back to its initial state
    // Returns true if there was a match.
    fn done_to(&mut self, downstream: &mut Consumer<T>) -> bool;
    // Helper methods
    fn push<'a>(&mut self, value: At<'a,S>) -> MatchResult<At<'a,S>> {
        self.push_to(value, &mut DiscardConsumer::new())
    }
    fn done(&mut self) -> bool {
        self.done_to(&mut DiscardConsumer::new())
    }
}

pub trait BufferableMatcher<S,T> where S: for<'a> TypeWithLifetime<'a>, T: Parser<S,S> {
    fn buffer(self) -> T;
}

// ----------- Always commit ---------------

pub struct CommittedParser<P> {
    parser: P,
}

impl<S,T,P> Parser<S,T> for CommittedParser<P> where P: Parser<S,T>, S: for<'a> TypeWithLifetime<'a>, T: for<'a> TypeWithLifetime<'a>  {
    fn push_to<'a>(&mut self, value: At<'a,S>, downstream: &mut Consumer<T>) -> MatchResult<At<'a,S>> {
        match self.parser.push_to(value, downstream) {
            Undecided     => Committed,
            Committed     => Committed,
            Matched(rest) => Matched(rest),
            Failed(_)     => Failed(false),
        }
    }
    fn done_to(&mut self, downstream: &mut Consumer<T>) -> bool {
        self.parser.done_to(downstream)
    }
}

// ----------- Sequencing ---------------

pub struct AndThenParser<L,R> {
    lhs: L,
    rhs: CommittedParser<R>,
    in_lhs: bool,
}

impl<S,T,L,R> Parser<S,T> for AndThenParser<L,R> where L: Parser<S,T>, R: Parser<S,T>, S: for<'a> TypeWithLifetime<'a>, T: for<'a> TypeWithLifetime<'a>  {
    fn push_to<'a>(&mut self, value: At<'a,S>, downstream: &mut Consumer<T>) -> MatchResult<At<'a,S>> {
        if self.in_lhs {
            match self.lhs.push_to(value, downstream) {
                Undecided     => Undecided,
                Committed     => Committed,
                Matched(rest) => { self.in_lhs = false; self.rhs.push_to(rest, downstream) },
                Failed(b)     => Failed(b),
            }
        } else {
            self.rhs.push_to(value, downstream)
        }
    }
    fn done_to(&mut self, downstream: &mut Consumer<T>) -> bool {
        self.lhs.done_to(downstream) && self.rhs.done_to(downstream)
    }
}

// ----------- Matching strings -------------

pub struct Str;

impl<'a> TypeWithLifetime<'a> for Str {
    type Type = &'a str;
}

// ----------- Constant parsers -------------

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
pub enum ConstantParserState {
    AtOffset(usize),
    AtEnd(bool),
}

pub struct ConstantParser {
    constant: String,
    state: ConstantParserState,
}

impl Parser<Str,Unit> for ConstantParser {
    fn push_to<'a>(&mut self, string: &'a str, downstream: &mut Consumer<Unit>) -> MatchResult<&'a str> {
        match self.state {
            AtOffset(index) if string.starts_with(&self.constant[index..]) => { downstream.accept(()); self.state = AtEnd(true); Matched(&string[(self.constant.len() - index)..]) },
            AtOffset(index) if self.constant[index..].starts_with(string)  => { self.state = AtOffset(index + string.len()); Undecided },
            AtOffset(_)                                                    => { self.state = AtEnd(false); Failed(true) },
            AtEnd(true)                                                    => { Matched(string) },
            AtEnd(false)                                                   => { Failed(true) },
        }
    }
    fn done_to(&mut self, _: &mut Consumer<Unit>) -> bool {
        let result = self.state == AtEnd(true);
        self.state = AtOffset(0);
        result
    }
}

pub fn constant(string: String) -> ConstantParser {
    ConstantParser{ constant: string, state: AtOffset(0) }
}

// If m is a Parser<Str,Unit> then m.buffer() is a Parser<Str,Str>.
// It does as little buffering as it can, but it does allocate as buffer for the case
// where the boundary marker of the input is misaligned with that of the parser.
// For example, m is matching string literals, and the input is '"abc' followed by 'def"'
// we have to buffer up '"abc'.

#[derive(Clone, Eq, PartialEq, Hash, Ord, PartialOrd, Debug)]
enum BufferedParserState {
    Beginning,
    Middle(String),
    EndMatch,
    EndFail(bool),
}

pub struct BufferedParser<P> {
    parser: P,
    state: BufferedParserState,
}

impl<P> Parser<Str,Str> for BufferedParser<P> where P: Parser<Str,Unit> {
    fn push_to<'a>(&mut self, string: &'a str, downstream: &mut Consumer<Str>) -> MatchResult<&'a str> {
        match mem::replace(&mut self.state, EndMatch) {
            Beginning => {
                let result = self.parser.push(string);
                match result {
                    Undecided     => self.state = Middle(String::from(string)),
                    Committed     => self.state = Middle(String::from(string)),
                    Failed(b)     => self.state = EndFail(b),
                    Matched(rest) => downstream.accept(&string[..(string.len()-rest.len())]),
                }
                result
            },
            Middle(mut buffer) => {
                let result = self.parser.push(string);
                match result {
                    Undecided     => { buffer.push_str(string); self.state = Middle(buffer); },
                    Committed     => { buffer.push_str(string); self.state = Middle(buffer); },
                    Failed(b)     => { self.state = EndFail(b); },
                    Matched(rest) => { buffer.push_str(&string[..(string.len()-rest.len())]); downstream.accept(&*buffer); },
                }
                result
            }
            EndMatch => Matched(string),
            EndFail(b) => Failed(b),
        }
    }
    fn done_to(&mut self, downstream: &mut Consumer<Str>) -> bool {
        let result = self.parser.done();
        if result { if let Middle(ref buffer) = self.state { downstream.accept(&*buffer) } }
        self.state = Beginning;
        result
    }
}

#[test]
fn test_constant() {
    let mut parser = constant(String::from("abc"));
    assert_eq!(parser.done(), false);
    assert_eq!(parser.push("fred"), Failed(true));
    assert_eq!(parser.done(), false);
    assert_eq!(parser.push("abcdef"), Matched("def"));
    assert_eq!(parser.done(), true);
    assert_eq!(parser.push("a"), Undecided);
    assert_eq!(parser.done(), false);
    assert_eq!(parser.push("ab"), Undecided);
    assert_eq!(parser.push("cd"), Matched("d"));
    assert_eq!(parser.done(), true);
}
<|endoftext|>