<commit_before>
struct CircularBuffer<T : Copy> {
  seqno : usize,
  data  : Vec<T>,
}

impl <T : Copy> CircularBuffer<T> {
  fn new(size : usize, default_value : T) -> CircularBuffer<T> {

    if size == 0 { panic!("size cannot be zero"); }

    let mut ret = CircularBuffer {
      seqno : 0,
      data  : vec![],
    };

    // make sure there is enough place and fill it with the
    // default value
    ret.data.resize(size, default_value);
    ret
  }

  fn put<F>(&mut self, setter: F) -> usize
    where F : FnMut(&mut T)
  {
    let mut setter = setter;

    // calculate where to put the data
    let pos = self.seqno % self.data.len();

    // get a reference to the data
    let mut opt : Option<&mut T> = self.data.get_mut(pos);

    // make sure the index worked
    match opt.as_mut() {
      Some(v) => setter(v),
      None    => { panic!("out of bounds {}", pos); }
    }

    // increase sequence number
    self.seqno += 1;
    self.seqno
  }

  fn get_range<F>(&self, from: &usize, to: &usize, getter: F) -> usize
    where F : FnMut(&T)
  {
    if from > to { panic!("from:{} > to:{}", from, to); }

    // figure out the minimum and maximum position
    let min_pos : usize = if self.seqno < self.data.len() {
      0
    } else {
      (self.seqno - self.data.len()) as usize
    };

    let max_pos : usize = self.seqno;

    // cannot return past (overwritten) elements
    if *to < min_pos { return min_pos; }

    // cannot return future elements
    if *from >= max_pos { return max_pos; }

    // constrain start to min_pos
    let start : usize = if *from > min_pos {
      *from
    } else {
      min_pos
    };

    // constrain end to max_pos
    let end : usize = if *to > max_pos {
      max_pos
    } else {
      *to
    };

    let start_pos   = start % self.data.len();
    let end_pos     = end % self.data.len();
    let mut getter  = getter;

    let mut get_range_fn = |from_pos: usize, to_pos: usize| {
      for i in from_pos..to_pos {
        let act_value : Option<&T> = self.data.get(i);
        match act_value {
          Some(v) => { getter(v); }
          None => { panic!("index is out of range i={}",i); }
        };
      }
    };

    if end_pos > start_pos {
      // one contigous range
      get_range_fn(start_pos, end_pos);
    } else {
      // range split into two
      get_range_fn(start_pos, self.data.len());
      get_range_fn(0, end_pos);
    }

    end
  }
}

pub fn tests() {
  let mut x = CircularBuffer::new(4, 0 as i32);
  x.put(|v| *v = 1);
  let mut y = 2;
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });

  let ret = x.get_range( &0, &100, |val : &i32| {
    println!("A: {}", *val);
  });

  println!("ret={}", ret);
}

#[test]
#[should_panic]
fn create_zero_sized() {
  let _x = CircularBuffer::new(0, 0 as i32);
}

#[test]
fn create_non_zero_sized() {
  let _x = CircularBuffer::new(1, 0 as i32);
}

#[test]
fn can_put() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  x.put(|v| *v = 1);
}

#[test]
fn can_put_with_env() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  let my_fn = |v : &mut i32| {
    *v = y;
    y += 1;
  };
  x.put(my_fn);
}

#[test]
fn can_put_with_env2() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  x.put(|v| { *v = y; y += 1; });
}
<commit_msg>first iterator<commit_after>
struct CircularBuffer<T : Copy> {
  seqno : usize,
  data  : Vec<T>,
}

struct CircularBufferIterator<'a, T: 'a + Copy> {
  buffer    : &'a CircularBuffer<T>,
  position  : usize,
  limit     : usize,
}

impl <T : Copy> CircularBuffer<T> {
  fn new(size : usize, default_value : T) -> CircularBuffer<T> {

    if size == 0 { panic!("size cannot be zero"); }

    let mut ret = CircularBuffer {
      seqno : 0,
      data  : vec![],
    };

    // make sure there is enough place and fill it with the
    // default value
    ret.data.resize(size, default_value);
    ret
  }

  fn min_pos(&self) -> usize {
    if self.seqno < self.data.len() {
      0
    } else {
      (self.seqno - self.data.len()) as usize
    }
  }

  fn iter(&self) -> CircularBufferIterator<T> {
    CircularBufferIterator{
      buffer: self,
      position: self.min_pos(),
      limit: self.seqno
     }
  }

  fn put<F>(&mut self, setter: F) -> usize
    where F : FnMut(&mut T)
  {
    // calculate where to put the data
    let pos = self.seqno % self.data.len();

    // get a reference to the data
    let mut opt : Option<&mut T> = self.data.get_mut(pos);

    let mut setter = setter;

    // make sure the index worked
    match opt.as_mut() {
      Some(v) => setter(v),
      None    => { panic!("out of bounds {}", pos); }
    }

    // increase sequence number
    self.seqno += 1;
    self.seqno
  }

  fn get(&self, at: &usize) -> (Option<&T>, usize) {

    let min_pos : usize = if self.seqno < self.data.len() {
      0
    } else {
      (self.seqno - self.data.len()) as usize
    };

    if *at < min_pos      { return (Option::None, min_pos);    }
    if *at >= self.seqno  { return (Option::None, self.seqno); }

    let pos = *at % self.data.len();

    (self.data.get(pos), *at+1)
  }

  fn get_range<F>(&self, from: &usize, to: &usize, getter: F) -> usize
    where F : FnMut(&T)
  {
    if from > to { panic!("from:{} > to:{}", from, to); }

    // figure out the minimum and maximum position
    let min_pos : usize = if self.seqno < self.data.len() {
      0
    } else {
      (self.seqno - self.data.len()) as usize
    };

    let max_pos : usize = self.seqno;

    // cannot return past (overwritten) elements
    if *to < min_pos { return min_pos; }

    // cannot return future elements
    if *from >= max_pos { return max_pos; }

    // constrain start to min_pos
    let start : usize = if *from > min_pos {
      *from
    } else {
      min_pos
    };

    // constrain end to max_pos
    let end : usize = if *to > max_pos {
      max_pos
    } else {
      *to
    };

    let start_pos   = start % self.data.len();
    let end_pos     = end % self.data.len();
    let mut getter  = getter;

    let mut get_range_fn = |from_pos: usize, to_pos: usize| {
      for i in from_pos..to_pos {
        let act_value : Option<&T> = self.data.get(i);
        match act_value {
          Some(v) => { getter(v); }
          None => { panic!("index is out of range i={}",i); }
        };
      }
    };

    if end_pos > start_pos {
      // one contigous range
      get_range_fn(start_pos, end_pos);
    } else {
      // range split into two
      get_range_fn(start_pos, self.data.len());
      get_range_fn(0, end_pos);
    }

    end
  }
}

impl <'_, T: '_ + Copy> Iterator for CircularBufferIterator<'_, T> {
  type Item = T;

  fn next(&mut self) -> Option<T> {
    if self.position >= self.limit {
      None
    } else {
      let at = self.position % self.buffer.data.len();
      match self.buffer.data.get(at) {
        Some(v) => Some(*v),
        None => None
      }
    }
  }
}

pub fn tests() {
  let mut x = CircularBuffer::new(4, 0 as i32);
  x.put(|v| *v = 1);
  let mut y : i32 = 2;
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });
  x.put(|v| { *v = y; y += 1; });

  let ret = x.get_range( &0, &100, |val : &i32| {
    println!("A: {}", *val);
  });
  println!("ret={} min_pos={}", ret,x.min_pos());

  let it = x.iter();
  for i in it {
    println!("B: {}", i);
  }

  let count  = x.iter().count();
  let max    = x.iter().max();
  let first  = x.iter().take(1).last();
  let last   = x.iter().last();

  println!("count={} max={} first={} last={}",
    count,
    max.unwrap(),
    first.unwrap(),
    last.unwrap());
}

#[test]
#[should_panic]
fn create_zero_sized() {
  let _x = CircularBuffer::new(0, 0 as i32);
}

#[test]
fn create_non_zero_sized() {
  let _x = CircularBuffer::new(1, 0 as i32);
}

#[test]
fn can_put() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  x.put(|v| *v = 1);
}

#[test]
fn can_put_with_env() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  let my_fn = |v : &mut i32| {
    *v = y;
    y += 1;
  };
  x.put(&my_fn);
  x.put(&my_fn);
  x.put(&my_fn);
}

#[test]
fn can_put_with_env2() {
  let mut x = CircularBuffer::new(1, 0 as i32);
  let mut y = 0;
  x.put(|v| { *v = y; y += 1; });
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test a foreign function that accepts empty struct.

// pretty-expanded FIXME #23616
// ignore-msvc
// ignore-emscripten

struct TwoU8s {
    one: u8,
    two: u8,
}

struct ManyInts {
    arg1: i8,
    arg2: i16,
    arg3: i32,
    arg4: i16,
    arg5: i8,
    arg6: TwoU8s,
}

struct Empty;

#[link(name = "rust_test_helpers", kind = "static")]
extern {
    fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
}

pub fn main() {
    unsafe {
        let x = ManyInts {
            arg1: 2,
            arg2: 3,
            arg3: 4,
            arg4: 5,
            arg5: 6,
            arg6: TwoU8s { one: 7, two: 8, }
        };
        let y = ManyInts {
            arg1: 1,
            arg2: 2,
            arg3: 3,
            arg4: 4,
            arg5: 5,
            arg6: TwoU8s { one: 6, two: 7, }
        };
        let empty = Empty;
        rust_dbg_extern_empty_struct(x, empty, y);
    }
}
<commit_msg>Fix extern-pass-empty test, which needed repr(C)<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test a foreign function that accepts empty struct.

// pretty-expanded FIXME #23616
// ignore-msvc
// ignore-emscripten

#[repr(C)]
struct TwoU8s {
    one: u8,
    two: u8,
}

#[repr(C)]
struct ManyInts {
    arg1: i8,
    arg2: i16,
    arg3: i32,
    arg4: i16,
    arg5: i8,
    arg6: TwoU8s,
}

#[repr(C)]
struct Empty;

#[link(name = "rust_test_helpers", kind = "static")]
extern {
    fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts);
}

pub fn main() {
    unsafe {
        let x = ManyInts {
            arg1: 2,
            arg2: 3,
            arg3: 4,
            arg4: 5,
            arg5: 6,
            arg6: TwoU8s { one: 7, two: 8, }
        };
        let y = ManyInts {
            arg1: 1,
            arg2: 2,
            arg3: 3,
            arg4: 4,
            arg5: 5,
            arg6: TwoU8s { one: 6, two: 7, }
        };
        let empty = Empty;
        rust_dbg_extern_empty_struct(x, empty, y);
    }
}
<|endoftext|>


<commit_before>//! This crate provides a framework for writing chess engines.
//!
//! # Why chess engines?
//!
//! Simple! Chess is the greatest thing humans have
//! invented. Computers follow closely ;)
//!
//! # Why a framework?
//!
//! There is lots of knowledge out there about how to write a chess
//! engine, and there is a lot of room for innovation also. Writing a
//! chess engine is fun, but even for the simplest engine there is a
//! lot of complex (and boring) things that have to be implemented
//! first: the UCI protocol communication, the rules, the static
//! exchange evaluator, and many more. Thousands of programmers have
//! been re-implementing those things over and over again.
//!
//! So, if you want to write your own chess engine, you face an
//! unpleasant choice: You either roll up your sleeves and implement
//! all the hard stuff from scratch, or you take someone else's chess
//! engine and struggle to understand its cryptic, undocumented source
//! code, hoping that it will be general enough to allow
//! modification. This unfortunate situation stifles innovation.
//!
//! # Usage
//!
//! Here is how simple it is to create a chess engine using this crate:
//!
//! ```rust,no_run
//! extern crate alcibiades;
//! use alcibiades::stock::*;
//! use alcibiades::engine::run_uci;
//!
//! fn main() {
//!     type SearchNode = StdSearchNode<StdQsearch<StdMoveGenerator<SimpleEvaluator>>>;
//!     type SearchExecutor = Deepening<StdSearchExecutor<StdHashTable, SearchNode>>;
//!     run_uci::<SearchExecutor, StdTimeManager>("My engine", "John Doe");
//! }
//! ```
//!
//! This engine is assembled from the "in stock" implementations of
//! the different framework traits.
//!
//! In reality, you will probably want to write your own
//! implementations of some of the framework traits. Thanks to Rust's
//! incredible generic programming capabilities, you are not limited
//! to implementing only the methods required by the traits. For
//! example you may write your own static position evaluator which
//! have a `consult_endgame_table` method. Then you will be able to
//! write a search algorithm that uses this method.
//!
//! # Speed and safety
//!
//! This crate tries to be fast *and* memory-safe.

#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate rand;

pub mod utils;
pub mod engine;
pub mod stock;
pub mod squares;
pub mod files;
pub mod ranks;
pub mod bitsets;
mod board;
mod moves;
mod value;
mod depth;
mod evaluator;
mod search_node;
mod search_executor;
mod hash_table;
mod move_generator;
mod qsearch;
mod time_manager;
mod uci;

pub use board::*;
pub use moves::*;
pub use value::*;
pub use depth::*;
pub use evaluator::*;
pub use search_node::*;
pub use search_executor::*;
pub use hash_table::*;
pub use move_generator::*;
pub use qsearch::*;
pub use time_manager::*;
pub use uci::{SetOption, OptionDescription};
<commit_msg>update the readme<commit_after>//! This crate provides a framework for writing chess engines.
//!
//! # Why chess engines?
//!
//! Simple! Chess is the greatest thing humans have
//! invented. Computers follow closely ;)
//!
//! # Why a framework?
//!
//! There is lots of knowledge out there about how to write a chess
//! engine, and there is a lot of room for innovation also. Writing a
//! chess engine is fun, but even for the simplest engine there is a
//! lot of complex (and boring) things that have to be implemented
//! first: the UCI protocol communication, the rules, the static
//! exchange evaluator, and many more. Thousands of programmers have
//! been re-implementing those things over and over again.
//!
//! So, if you want to write your own chess engine, you face an
//! unpleasant choice: You either roll up your sleeves and implement
//! all the hard stuff from scratch, or you take someone else's chess
//! engine and struggle to understand its cryptic, undocumented source
//! code, hoping that it will be general enough to allow
//! modification. This unfortunate situation stifles innovation.
//!
//! # Usage
//!
//! Here is how simple it is to create a chess engine using this the
//! framework:
//!
//! ```rust,no_run
//! extern crate alcibiades;
//! use alcibiades::stock::*;
//! use alcibiades::engine::run_uci;
//!
//! fn main() {
//!     type SearchNode = StdSearchNode<StdQsearch<StdMoveGenerator<SimpleEvaluator>>>;
//!     type SearchExecutor = Deepening<StdSearchExecutor<StdHashTable, SearchNode>>;
//!     run_uci::<SearchExecutor, StdTimeManager>("My engine", "John Doe");
//! }
//! ```
//!
//! This engine is assembled from the "in stock" implementations of
//! the different framework traits.
//!
//! In reality, you will probably want to write your own
//! implementations of some of the framework traits. Thanks to Rust's
//! incredible generic programming capabilities, you are not limited
//! to implementing only the methods required by the traits. For
//! example you may write your own static position evaluator which
//! have a `consult_endgame_table` method. Then you will be able to
//! write a search algorithm that uses this method.
//!
//! # Speed and safety
//!
//! This crate tries to be fast *and* memory-safe.

#[macro_use]
extern crate lazy_static;
extern crate regex;
extern crate rand;

pub mod utils;
pub mod engine;
pub mod stock;
pub mod squares;
pub mod files;
pub mod ranks;
pub mod bitsets;
mod board;
mod moves;
mod value;
mod depth;
mod evaluator;
mod search_node;
mod search_executor;
mod hash_table;
mod move_generator;
mod qsearch;
mod time_manager;
mod uci;

pub use board::*;
pub use moves::*;
pub use value::*;
pub use depth::*;
pub use evaluator::*;
pub use search_node::*;
pub use search_executor::*;
pub use hash_table::*;
pub use move_generator::*;
pub use qsearch::*;
pub use time_manager::*;
pub use uci::{SetOption, OptionDescription};
<|endoftext|>


<commit_before>use std::hash::{Hash, Hasher, SipHasher};
use std::any::Any;
use std::rc::Rc;
use std::cmp::Ordering;

// TODO check whether hashes in rust vary by CPU endianness?
// Answer: they do, so maybe stop using Hash for this sometime
// ( https://doc.rust-lang.org/std/hash/trait.Hasher.html
// "represents the ability to hash an arbitrary stream of bytes").
#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SiphashId {
  data: [u64; 2],
}
pub struct SiphashIdGenerator {
  data: [SipHasher; 2],
}
impl Hasher for SiphashIdGenerator {
  fn finish(&self) -> u64 {
    panic!()
  }//Hack: this is actually for generating SiphashId, not 64-bit
  fn write(&mut self, bytes: &[u8]) {
    self.data[0].write(bytes);
    self.data[1].write(bytes);
  }
  // TODO: should we implement the others for efficiency?
}
impl SiphashIdGenerator {
  fn generate(&self) -> SiphashId {
    SiphashId { data: [self.data[0].finish(), self.data[1].finish()] }
  }
  fn new() -> SiphashIdGenerator {
    SiphashIdGenerator { data: [
      SipHasher::new_with_keys(0xb82a9426fd1a574f, 0x9d9d5b703dcb1bcc),
      SipHasher::new_with_keys(0x03e0d6037ff980a4, 0x65b790a0825b83bd),
      ] }
  }
}
// other possible names: hash_up_a_siphash_id?
pub fn make_siphash_id <T: Hash>(data: &T) -> SiphashId {
  let mut s = SiphashIdGenerator::new();
  data.hash(&mut s);
  s.generate()
}

// TODO: Shouldn't "ordered type with minimum and maximum values" be a trait common to other situations as well? Find out if there's a standard name for that.
// pub trait BaseTime: Clone + Ord {
//   fn min_time() -> Self;
//   fn max_time() -> Self;
// }
// impl BaseTime for i64 {
//   fn min_time() -> i64 {
//     i64::min_value()
//   }
//   fn max_time() -> i64 {
//     i64::max_value()
//   }
// }

// Database analogy: time stewards kind of contain a database table.
// Rows' ids are special; there isn't an "id" column.
// Row ids are random 128 bit ids.
// Rows aren't explicitly inserted and deleted.
// Only the existence or nonexistence of a (row, column) pair
// -- a field -- is meaningful.
// Generally, space usage is proportional to the number of
// existent fields.  For example, a row with only one existent field
// only takes up the space of one field.

pub type RowId = SiphashId;

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ColumnId(u64);

pub trait Column {
  type FieldType: Any;// = Self;

  /**
  Returns a constant identifier for the type, which must be 64 bits of random data.

  Thanks to the [birthday problem](https://en.wikipedia.org/wiki/Birthday_problem), this would have a >1% chance of a collision with a mere 700 million Column implementors. I don't think we need to worry about this. 128 bit IDs are necessary for rows, because computers can generate billions of them easily, but this isn't the same situation.

  It might seem desirable to default to a hash of the TypeId of Self, for the convenience of some implementations. However, Rust does not guarantee that the TypeId remains the same across different compilations or different compiler versions. And it certainly doesn't remain the same when you add or remove types from your code, which would be desirable for compatibility between different versions of your program. Also, the Rust interface for getting the TypeId is currently unstable. Using an explicit constant is simply better.

  TODO: change this into an associated constant once associated constants become stable.
  */
  fn column_id() -> ColumnId;

  /**
  Implementors MAY return true if first and second are indistinguishable.

  This is labeled "unsafe" because imperfect implementations can easily cause nondeterminism in the TimeSteward. Using the default is fine, and implementing it is only an optimization. Don't implement this unless you know what you're doing.

  This is similar to requiring FieldType to be PartialEq, but with an important difference. PartialEq only requires the comparison to be an equivalence relation, but does NOT require that (first == second) guarantee that there is no observable difference between the values. Therefore, trusting arbitrary implementations of PartialEq would be unsafe (in the sense that it would allow the TimeSteward to behave non-deterministically).

  TODO: perhaps we can create default implementations of this for POD types.
  TODO: can we create automated tests for implementations of this function?
  */
  fn guaranteed_equal__unsafe(first: &Self::FieldType, second: &Self::FieldType) -> bool {
    false
  }
}

#[derive (Clone, PartialEq, Eq, Hash)]
struct FieldId {
  row_id: RowId,
  column_id: ColumnId,
}

type IterationType = u32;
#[derive (Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct GenericExtendedTime<Base: Ord> {
  base: Base,
  iteration: IterationType,
  id: SiphashId,
}

//fn beginning_of_moment<Base: Ord>(base_time: Base) -> GenericExtendedTime<Base> {
//  GenericExtendedTime {
//    base: base_time,
//    iteration: 0,
//    id: SiphashId { data: [0, 0] },
//  }
//}

fn time_id_for_predicted_event (predictor_id: u64, row_id: RowId, iteration: IterationType, time_id_of_latest_dependency_change: SiphashId)->SiphashId {
  make_siphash_id (& (predictor_id, row_id, iteration, time_id_of_latest_dependency_change))
}
fn next_extended_time_of_predicted_event<BaseTime: Ord>(
                                       predictor_id: u64,
                                       row_id: RowId,
                                       time_id_of_latest_dependency_change: SiphashId,
                                       event_base_time: BaseTime,
                                       from: &GenericExtendedTime<BaseTime>)
                                       -> Option<GenericExtendedTime<BaseTime>> {
  let (iteration, id) = match event_base_time.cmp(&from.base) {
    Ordering::Less => return None, // short-circuit
    Ordering::Greater => (0, time_id_for_predicted_event (predictor_id, row_id, 0, time_id_of_latest_dependency_change)),
    Ordering::Equal => {
      let mut id = time_id_for_predicted_event (predictor_id, row_id, from.iteration, time_id_of_latest_dependency_change);
      if id > from.id {
        (from.iteration, id)
      } else {
        if from.iteration == IterationType::max_value() {panic! ("Too many iterations at the same base time; probably an infinite loop")}
        (from.iteration + 1, time_id_for_predicted_event (predictor_id, row_id, from.iteration + 1, time_id_of_latest_dependency_change))
      }
    }
  };
  Some(GenericExtendedTime {
    base: event_base_time,
    id: id,
    iteration: iteration,
  })
}

/**
This is intended to be implemented on an empty struct. Requiring Clone is a hack to work around [a compiler weakness](https://github.com/rust-lang/rust/issues/26925).
*/
pub trait Basics: Clone {
  type Time: Clone + Ord;
  type Constants;
}
type ExtendedTime<B: Basics> = GenericExtendedTime<B::Time>;

// Note: in the future, we expect we might use a custom hash table type that knows it can rely on SiphashId to already be random, so we don't need to hash it again. This also applies to FieldId, although there may be some complications in that case.
// (for now, we need to be able to hash full siphash ids to create other siphash ids.)
// ( Also -- do we ever try to hash GenericExtendedTime with id of 0 from beginning_of_moment.... )
// impl Hash for SiphashId {
//  fn hash<H: Hasher>(&self, state: &mut H) {
//    self.data[0].hash(state);
//  }
// }
// impl<Base: BaseTime> Hash for GenericExtendedTime<Base> {
//  fn hash<H: Hasher>(&self, state: &mut H) {
//    self.id.hash(state);
//  }
// }

pub trait Accessor<B: Basics> {
  fn get<C: Column>(&mut self, id: RowId) -> Option<&C::FieldType>;
  fn constants(&self) -> &B::Constants;
}

pub trait MomentaryAccessor<B: Basics>: Accessor<B> {
  fn now(&self) -> &B::Time;
}

pub trait Mutator<B: Basics>: MomentaryAccessor<B> {
  //fn get_mut<C: Column>(&mut self, id: RowId) -> Option<&mut C::FieldType> where C::FieldType: Clone;
  fn set<C: Column>(&mut self, id: RowId, data: Option<C::FieldType>);
  fn random_bits(&mut self, num_bits: u32) -> u64;
  fn random_id(&mut self) -> SiphashId;
}
pub trait PredictorAccessor<B: Basics>: Accessor<B> {
  type Event;
  // it is unclear whether predict_immediately is sketchy
  fn predict_immediately(&mut self, event: Self::Event);
  fn predict_at_time(&mut self, time: &B::Time, event: Self::Event);
}
pub trait Snapshot<B: Basics>: MomentaryAccessor<B> {}

pub enum FiatEventOperationResult {
  Success,
  InvalidInput,
  InvalidTime,
}

pub enum ValidSince <BaseTime> {
TheBeginning,
Before (BaseTime),
After (BaseTime),
}

// This exists to support a variety of time stewards
// along with allowing BaseTime to be dense (e.g. a
// rational number rather than an integer).
// It is an acceptable peculiarity that even for integer times,
// After(2) < Before(3).
//#[derive (Copy, Clone, PartialEq, Eq, Hash)]
//pub enum TimeBoundary<BaseTime> {
//  Before(BaseTime),
//  After(BaseTime),
//}
// //impl PartialOrd

pub trait SnapshotHack<'a, B: Basics> {
  type Snapshot;
}
pub trait TimeSteward<B: Basics> {
  type Event;
  type Predictor;

  /**
  You are allowed to call snapshot_before(), insert_fiat_event(),
  and erase_fiat_event() for times >= valid_since().

  TimeSteward implementors are permitted, but not required, to discard old data in order to save memory. This may make the TimeSteward unusable at some points in its history.

  All implementors must obey certain restrictions on how other TimeSteward methods may change the result of valid_since(). Implementors may have their own methods that can alter this in customized ways, which should be documented with those individual methods.
  */
  fn valid_since (&self) -> ValidSince <B::Time>;

  /**
  Creates a new, empty TimeSteward.

  new_empty().valid_since() must equal TheBeginning.
  */
  fn new_empty(constants: B::Constants, predictors: Vec<Self::Predictor>)->Self;

  /**
  Inserts a fiat event at some point in the history.

  If time < valid_since(), this does nothing and returns InvalidTime. If there is already a fiat event with the same time and distinguisher, this does nothing and returns InvalidInput. Otherwise, it inserts the event and returns Success.

  steward.insert_fiat_event(time, _) must not return InvalidTime if time > steward.valid_since().
  steward.insert_fiat_event() may not change steward.valid_since().
  */
  fn insert_fiat_event(&mut self,
                       time: B::Time,
                       distinguisher: u64,
                       event: Self::Event)
                       -> FiatEventOperationResult;

  /**
  Erases a fiat event that has been inserted previously.

  If time < valid_since(), this does nothing and returns InvalidTime. If there is no fiat event with the specified time and distinguisher, this does nothing and returns InvalidInput. Otherwise, it erases the event and returns Success.

  steward.erase_fiat_event(time, _) must not return InvalidTime if time > steward.valid_since().
  steward.erase_fiat_event() may not change steward.valid_since().
  */
  fn erase_fiat_event(&mut self, time: B::Time, distinguisher: u64) -> FiatEventOperationResult;

  /**
  Returns a "snapshot" into the TimeSteward.

  The snapshot is guaranteed to be valid and unchanging for the full lifetime of the TimeSteward. It is specific to both the time argument, and the current collection of fiat events. Callers may freely call mutable methods of the same TimeSteward after taking a snapshot, without changing the contents of the snapshot.

  Each TimeSteward implementor determines exactly how to provide these guarantees. Implementors should provide individual guarantees about the processor-time bounds of snapshot operations.

  steward.snapshot_before(time) must return Some if time > steward.valid_since().
  steward.snapshot_before(time) may not increase steward.valid_since() beyond time.
  */
  // note: we implement "before" and not "after" because we might be banning events that happen during max_time
  fn snapshot_before<'a>(&'a mut self, time: B::Time) ->
  Option<<Self as SnapshotHack<'a, B>>::Snapshot>
  where Self: SnapshotHack<'a, B>;
}

// #[derive (Clone)]
// enum Prediction<B: Basics, E> {
//   Nothing,
//   Immediately(E),
//   At(B::Time, E),
// }
struct Predictor<PredictorFn> {
  predictor_id: u64,
  column_id: ColumnId,
  function: PredictorFn,
}

//type Event<M> = Rc<for<'d> Fn(&'d mut M)>;
//type PredictorFn<B: Basics, M: Mutator<B>, PA: PredictorAccessor<B>> =
//  Rc<for<'b, 'c> Fn(&'b mut PA, RowId) -> Prediction<B, Event<M>>>;

pub mod inefficient_flat_time_steward;
// pub mod simple_flat_time_steward;

#[test]
fn it_works() {}
<commit_msg>Changed obsolete name<commit_after>use std::hash::{Hash, Hasher, SipHasher};
use std::any::Any;
use std::rc::Rc;
use std::cmp::Ordering;

// TODO check whether hashes in rust vary by CPU endianness?
// Answer: they do, so maybe stop using Hash for this sometime
// ( https://doc.rust-lang.org/std/hash/trait.Hasher.html
// "represents the ability to hash an arbitrary stream of bytes").
#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SiphashId {
  data: [u64; 2],
}
pub struct SiphashIdGenerator {
  data: [SipHasher; 2],
}
impl Hasher for SiphashIdGenerator {
  fn finish(&self) -> u64 {
    panic!()
  }//Hack: this is actually for generating SiphashId, not 64-bit
  fn write(&mut self, bytes: &[u8]) {
    self.data[0].write(bytes);
    self.data[1].write(bytes);
  }
  // TODO: should we implement the others for efficiency?
}
impl SiphashIdGenerator {
  fn generate(&self) -> SiphashId {
    SiphashId { data: [self.data[0].finish(), self.data[1].finish()] }
  }
  fn new() -> SiphashIdGenerator {
    SiphashIdGenerator { data: [
      SipHasher::new_with_keys(0xb82a9426fd1a574f, 0x9d9d5b703dcb1bcc),
      SipHasher::new_with_keys(0x03e0d6037ff980a4, 0x65b790a0825b83bd),
      ] }
  }
}
// other possible names: hash_up_a_siphash_id?
pub fn make_siphash_id <T: Hash>(data: &T) -> SiphashId {
  let mut s = SiphashIdGenerator::new();
  data.hash(&mut s);
  s.generate()
}

// TODO: Shouldn't "ordered type with minimum and maximum values" be a trait common to other situations as well? Find out if there's a standard name for that.
// pub trait BaseTime: Clone + Ord {
//   fn min_time() -> Self;
//   fn max_time() -> Self;
// }
// impl BaseTime for i64 {
//   fn min_time() -> i64 {
//     i64::min_value()
//   }
//   fn max_time() -> i64 {
//     i64::max_value()
//   }
// }

// Database analogy: time stewards kind of contain a database table.
// Rows' ids are special; there isn't an "id" column.
// Row ids are random 128 bit ids.
// Rows aren't explicitly inserted and deleted.
// Only the existence or nonexistence of a (row, column) pair
// -- a field -- is meaningful.
// Generally, space usage is proportional to the number of
// existent fields.  For example, a row with only one existent field
// only takes up the space of one field.

pub type RowId = SiphashId;

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ColumnId(u64);

pub trait Column {
  type FieldType: Any;// = Self;

  /**
  Returns a constant identifier for the type, which must be 64 bits of random data.

  Thanks to the [birthday problem](https://en.wikipedia.org/wiki/Birthday_problem), this would have a >1% chance of a collision with a mere 700 million Column implementors. I don't think we need to worry about this. 128 bit IDs are necessary for rows, because computers can generate billions of them easily, but this isn't the same situation.

  It might seem desirable to default to a hash of the TypeId of Self, for the convenience of some implementations. However, Rust does not guarantee that the TypeId remains the same across different compilations or different compiler versions. And it certainly doesn't remain the same when you add or remove types from your code, which would be desirable for compatibility between different versions of your program. Also, the Rust interface for getting the TypeId is currently unstable. Using an explicit constant is simply better.

  TODO: change this into an associated constant once associated constants become stable.
  */
  fn column_id() -> ColumnId;

  /**
  Implementors MAY return true if first and second are indistinguishable.

  This is labeled "unsafe" because imperfect implementations can easily cause nondeterminism in the TimeSteward. Using the default is fine, and implementing it is only an optimization. Don't implement this unless you know what you're doing.

  This is similar to requiring FieldType to be PartialEq, but with an important difference. PartialEq only requires the comparison to be an equivalence relation, but does NOT require that (first == second) guarantee that there is no observable difference between the values. Therefore, trusting arbitrary implementations of PartialEq would be unsafe (in the sense that it would allow the TimeSteward to behave non-deterministically).

  TODO: perhaps we can create default implementations of this for POD types.
  TODO: can we create automated tests for implementations of this function?
  */
  fn guaranteed_equal__unsafe(first: &Self::FieldType, second: &Self::FieldType) -> bool {
    false
  }
}

#[derive (Clone, PartialEq, Eq, Hash)]
struct FieldId {
  row_id: RowId,
  column_id: ColumnId,
}

type IterationType = u32;
#[derive (Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
struct GenericExtendedTime<Base: Ord> {
  base: Base,
  iteration: IterationType,
  id: SiphashId,
}

//fn beginning_of_moment<Base: Ord>(base_time: Base) -> GenericExtendedTime<Base> {
//  GenericExtendedTime {
//    base: base_time,
//    iteration: 0,
//    id: SiphashId { data: [0, 0] },
//  }
//}

fn time_id_for_predicted_event (predictor_id: u64, row_id: RowId, iteration: IterationType, dependencies_hash: SiphashId)->SiphashId {
  make_siphash_id (& (predictor_id, row_id, iteration, dependencies_hash))
}
fn next_extended_time_of_predicted_event<BaseTime: Ord>(
                                       predictor_id: u64,
                                       row_id: RowId,
                                       dependencies_hash: SiphashId,
                                       event_base_time: BaseTime,
                                       from: &GenericExtendedTime<BaseTime>)
                                       -> Option<GenericExtendedTime<BaseTime>> {
  let (iteration, id) = match event_base_time.cmp(&from.base) {
    Ordering::Less => return None, // short-circuit
    Ordering::Greater => (0, time_id_for_predicted_event (predictor_id, row_id, 0, dependencies_hash)),
    Ordering::Equal => {
      let mut id = time_id_for_predicted_event (predictor_id, row_id, from.iteration, dependencies_hash);
      if id > from.id {
        (from.iteration, id)
      } else {
        if from.iteration == IterationType::max_value() {panic! ("Too many iterations at the same base time; probably an infinite loop")}
        (from.iteration + 1, time_id_for_predicted_event (predictor_id, row_id, from.iteration + 1, dependencies_hash))
      }
    }
  };
  Some(GenericExtendedTime {
    base: event_base_time,
    id: id,
    iteration: iteration,
  })
}

/**
This is intended to be implemented on an empty struct. Requiring Clone is a hack to work around [a compiler weakness](https://github.com/rust-lang/rust/issues/26925).
*/
pub trait Basics: Clone {
  type Time: Clone + Ord;
  type Constants;
}
type ExtendedTime<B: Basics> = GenericExtendedTime<B::Time>;

// Note: in the future, we expect we might use a custom hash table type that knows it can rely on SiphashId to already be random, so we don't need to hash it again. This also applies to FieldId, although there may be some complications in that case.
// (for now, we need to be able to hash full siphash ids to create other siphash ids.)
// ( Also -- do we ever try to hash GenericExtendedTime with id of 0 from beginning_of_moment.... )
// impl Hash for SiphashId {
//  fn hash<H: Hasher>(&self, state: &mut H) {
//    self.data[0].hash(state);
//  }
// }
// impl<Base: BaseTime> Hash for GenericExtendedTime<Base> {
//  fn hash<H: Hasher>(&self, state: &mut H) {
//    self.id.hash(state);
//  }
// }

pub trait Accessor<B: Basics> {
  fn get<C: Column>(&mut self, id: RowId) -> Option<&C::FieldType>;
  fn constants(&self) -> &B::Constants;
}

pub trait MomentaryAccessor<B: Basics>: Accessor<B> {
  fn now(&self) -> &B::Time;
}

pub trait Mutator<B: Basics>: MomentaryAccessor<B> {
  //fn get_mut<C: Column>(&mut self, id: RowId) -> Option<&mut C::FieldType> where C::FieldType: Clone;
  fn set<C: Column>(&mut self, id: RowId, data: Option<C::FieldType>);
  fn random_bits(&mut self, num_bits: u32) -> u64;
  fn random_id(&mut self) -> SiphashId;
}
pub trait PredictorAccessor<B: Basics>: Accessor<B> {
  type Event;
  // it is unclear whether predict_immediately is sketchy
  fn predict_immediately(&mut self, event: Self::Event);
  fn predict_at_time(&mut self, time: &B::Time, event: Self::Event);
}
pub trait Snapshot<B: Basics>: MomentaryAccessor<B> {}

pub enum FiatEventOperationResult {
  Success,
  InvalidInput,
  InvalidTime,
}

pub enum ValidSince <BaseTime> {
TheBeginning,
Before (BaseTime),
After (BaseTime),
}

// This exists to support a variety of time stewards
// along with allowing BaseTime to be dense (e.g. a
// rational number rather than an integer).
// It is an acceptable peculiarity that even for integer times,
// After(2) < Before(3).
//#[derive (Copy, Clone, PartialEq, Eq, Hash)]
//pub enum TimeBoundary<BaseTime> {
//  Before(BaseTime),
//  After(BaseTime),
//}
// //impl PartialOrd

pub trait SnapshotHack<'a, B: Basics> {
  type Snapshot;
}
pub trait TimeSteward<B: Basics> {
  type Event;
  type Predictor;

  /**
  You are allowed to call snapshot_before(), insert_fiat_event(),
  and erase_fiat_event() for times >= valid_since().

  TimeSteward implementors are permitted, but not required, to discard old data in order to save memory. This may make the TimeSteward unusable at some points in its history.

  All implementors must obey certain restrictions on how other TimeSteward methods may change the result of valid_since(). Implementors may have their own methods that can alter this in customized ways, which should be documented with those individual methods.
  */
  fn valid_since (&self) -> ValidSince <B::Time>;

  /**
  Creates a new, empty TimeSteward.

  new_empty().valid_since() must equal TheBeginning.
  */
  fn new_empty(constants: B::Constants, predictors: Vec<Self::Predictor>)->Self;

  /**
  Inserts a fiat event at some point in the history.

  If time < valid_since(), this does nothing and returns InvalidTime. If there is already a fiat event with the same time and distinguisher, this does nothing and returns InvalidInput. Otherwise, it inserts the event and returns Success.

  steward.insert_fiat_event(time, _) must not return InvalidTime if time > steward.valid_since().
  steward.insert_fiat_event() may not change steward.valid_since().
  */
  fn insert_fiat_event(&mut self,
                       time: B::Time,
                       distinguisher: u64,
                       event: Self::Event)
                       -> FiatEventOperationResult;

  /**
  Erases a fiat event that has been inserted previously.

  If time < valid_since(), this does nothing and returns InvalidTime. If there is no fiat event with the specified time and distinguisher, this does nothing and returns InvalidInput. Otherwise, it erases the event and returns Success.

  steward.erase_fiat_event(time, _) must not return InvalidTime if time > steward.valid_since().
  steward.erase_fiat_event() may not change steward.valid_since().
  */
  fn erase_fiat_event(&mut self, time: B::Time, distinguisher: u64) -> FiatEventOperationResult;

  /**
  Returns a "snapshot" into the TimeSteward.

  The snapshot is guaranteed to be valid and unchanging for the full lifetime of the TimeSteward. It is specific to both the time argument, and the current collection of fiat events. Callers may freely call mutable methods of the same TimeSteward after taking a snapshot, without changing the contents of the snapshot.

  Each TimeSteward implementor determines exactly how to provide these guarantees. Implementors should provide individual guarantees about the processor-time bounds of snapshot operations.

  steward.snapshot_before(time) must return Some if time > steward.valid_since().
  steward.snapshot_before(time) may not increase steward.valid_since() beyond time.
  */
  // note: we implement "before" and not "after" because we might be banning events that happen during max_time
  fn snapshot_before<'a>(&'a mut self, time: B::Time) ->
  Option<<Self as SnapshotHack<'a, B>>::Snapshot>
  where Self: SnapshotHack<'a, B>;
}

// #[derive (Clone)]
// enum Prediction<B: Basics, E> {
//   Nothing,
//   Immediately(E),
//   At(B::Time, E),
// }
struct Predictor<PredictorFn> {
  predictor_id: u64,
  column_id: ColumnId,
  function: PredictorFn,
}

//type Event<M> = Rc<for<'d> Fn(&'d mut M)>;
//type PredictorFn<B: Basics, M: Mutator<B>, PA: PredictorAccessor<B>> =
//  Rc<for<'b, 'c> Fn(&'b mut PA, RowId) -> Prediction<B, Event<M>>>;

pub mod inefficient_flat_time_steward;
// pub mod simple_flat_time_steward;

#[test]
fn it_works() {}
<|endoftext|>


<commit_before>#![crate_id = "typedopts"]
#![crate_type = "lib"]

extern crate getopts;
extern crate serialize;
use getopts::Matches;
use std::from_str::FromStr;
use std::str::StrSlice;
use serialize::Decodable;

#[deriving(PartialEq, Eq, Show)]
pub enum ErrorType {
  UnimplementedDecoder,
  MissingField(String),
  ExpectedType(String, String, String)
}

#[deriving(PartialEq, Eq, Show)]
pub struct Error {
  e: ErrorType
}

pub type DecodeResult<T> =  Result<T, ErrorType>;

pub struct Decoder {
  matches: Matches,
  cur: String,
  current_type: String
}

impl Decoder {
  pub fn new(matches: Matches) -> Decoder {
    Decoder {
      matches: matches,
      cur: "".to_string(),
      current_type: "".to_string()
    }
  }

  fn expected(&self, expected_type: String) -> ErrorType {
    ExpectedType(self.cur.to_string(),
                       expected_type.to_string(),
                       self.matches.opt_str(self.cur.as_slice()).unwrap())
  }

}

pub fn decode<T:Send+Decodable<Decoder, ErrorType>>(matches: Matches) -> DecodeResult<T> {
  let mut decoder = Decoder::new(matches);
  Decodable::decode(&mut decoder)
}

impl ErrorType {
  pub fn to_err_msg(self) -> String {
    match self {
      UnimplementedDecoder => format!("this function is not implemented"),
      MissingField(ref s)  => format!("the required field '{}' is not present", s),
      ExpectedType(ref field, ref expected, ref value) => {
        format!("Expected type '{}' for field '{}' but got value '{}'", expected, field, value)
      }
    }
  }
}
impl<T:FromStr> Decoder {
  fn get_field<T:FromStr>(&self, field: &str) -> Option<T> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => None,
      Some(s) => FromStr::from_str(s.as_slice())
    }
  }
}

impl serialize::Decoder<ErrorType> for Decoder {

  fn read_nil(&mut self) -> DecodeResult<()> {
    Err(UnimplementedDecoder)
  }

  fn read_u64(&mut self)  -> DecodeResult<u64>  {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match FromStr::from_str(s.as_slice()) {
        None     => Err(self.expected("u64".to_string())),
        Some(nb) => Ok(nb)
      }
    }
  }
  fn read_u32(&mut self)  -> DecodeResult<u32>  { Ok(try!(self.read_u64()) as u32) }
  fn read_u16(&mut self)  -> DecodeResult<u16>  { Ok(try!(self.read_u64()) as u16) }
  fn read_u8 (&mut self)  -> DecodeResult<u8>   { Ok(try!(self.read_u64()) as u8) }
  fn read_uint(&mut self) -> DecodeResult<uint> { Ok(try!(self.read_u64()) as uint) }

  fn read_i64(&mut self) -> DecodeResult<i64> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match FromStr::from_str(s.as_slice()) {
        None     => Err(self.expected("i64".to_string())),
        Some(nb) => Ok(nb)
      }
    }
  }
  fn read_i32(&mut self) -> DecodeResult<i32> { Ok(try!(self.read_i64()) as i32) }
  fn read_i16(&mut self) -> DecodeResult<i16> { Ok(try!(self.read_i64()) as i16) }
  fn read_i8 (&mut self) -> DecodeResult<i8>  { Ok(try!(self.read_i64()) as i8) }
  fn read_int(&mut self) -> DecodeResult<int> { Ok(try!(self.read_i64()) as int) }

  fn read_f32(&mut self) -> DecodeResult<f32> { Ok(try!(self.read_f64()) as f32) }
  fn read_f64(&mut self) -> DecodeResult<f64> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match FromStr::from_str(s.as_slice()) {
        None     => Err(self.expected("f64".to_string())),
        Some(nb) => Ok(nb)
      }
    }
  }

  fn read_bool(&mut self) -> DecodeResult<bool> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match FromStr::from_str(s.as_slice()) {
        None     => Err(self.expected("boolean".to_string())),
        Some(b) => Ok(b)
      }
    }
  }

  fn read_char(&mut self) -> DecodeResult<char> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => if s.as_slice().char_len() == 1 { Ok(s.as_slice().char_at(0)) } else { Err(self.expected("char".to_string())) }
    }
  }

  fn read_str(&mut self) -> DecodeResult<String> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => Ok(s)
    }
  }

  fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum: {}", name);
    self.current_type = name.to_string();
    f(self)
  }

  fn read_enum_variant<T>(&mut self, names: &[&str], f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum variant({}): {}", self.cur, names);
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match names.iter().position(|&e| e == s.as_slice()) {
        None    => Err(self.expected(self.current_type.clone().append(" enum"))),
        Some(i) => f(self, i)
      }
    }
  }

  fn read_enum_variant_arg<T>(&mut self, a_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum variant_arg: {}", a_idx);
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_enum_struct_variant<T>(&mut self, names: &[&str], f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum struct variant: {}", names);
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_enum_struct_variant_field<T>(&mut self, f_name: &str, f_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum struct variant field: {}, {}", f_name, f_idx);
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_struct<T>(&mut self, s_name: &str, len: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading struct: {} | len = {}", s_name, len);
    self.cur = s_name.to_string();
    f(self)
  }

  fn read_struct_field<T>(&mut self, f_name: &str, f_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading struct field: {} | idx = {}", f_name, f_idx);
    self.cur = f_name.to_string();
    let data = f(self);
    //println!("got struct field data: {}", data);
    data
  }

  fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("read_option");
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => {
        //println!("option not there");
        f(self, false)
      },
      Some(_) => {
        //println!("option is there");
        f(self, true)
      }
    }
  }

  fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_tuple_struct<T>(&mut self, s_name: &str, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_tuple_struct_arg<T>(&mut self, a_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_seq<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_map<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

}
<commit_msg>add error() implementation to Decoder<commit_after>#![crate_id = "typedopts"]
#![crate_type = "lib"]

extern crate getopts;
extern crate serialize;
use getopts::Matches;
use std::from_str::FromStr;
use std::str::StrSlice;
use serialize::Decodable;

#[deriving(PartialEq, Eq, Show)]
pub enum ErrorType {
  UnimplementedDecoder,
  MissingField(String),
  ExpectedType(String, String, String),
  GenericError(String)
}

#[deriving(PartialEq, Eq, Show)]
pub struct Error {
  e: ErrorType
}

pub type DecodeResult<T> =  Result<T, ErrorType>;

pub struct Decoder {
  matches: Matches,
  cur: String,
  current_type: String
}

impl Decoder {
  pub fn new(matches: Matches) -> Decoder {
    Decoder {
      matches: matches,
      cur: "".to_string(),
      current_type: "".to_string()
    }
  }

  fn expected(&self, expected_type: String) -> ErrorType {
    ExpectedType(self.cur.to_string(),
                       expected_type.to_string(),
                       self.matches.opt_str(self.cur.as_slice()).unwrap())
  }

}

pub fn decode<T:Send+Decodable<Decoder, ErrorType>>(matches: Matches) -> DecodeResult<T> {
  let mut decoder = Decoder::new(matches);
  Decodable::decode(&mut decoder)
}

impl ErrorType {
  pub fn to_err_msg(self) -> String {
    match self {
      UnimplementedDecoder => format!("this function is not implemented"),
      MissingField(ref s)  => format!("the required field '{}' is not present", s),
      ExpectedType(ref field, ref expected, ref value) => {
        format!("Expected type '{}' for field '{}' but got value '{}'", expected, field, value)
      },
      GenericError(ref s)  => format!("generic error: {}", s)
    }
  }
}
impl<T:FromStr> Decoder {
  fn get_field<T:FromStr>(&self, field: &str) -> Option<T> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => None,
      Some(s) => FromStr::from_str(s.as_slice())
    }
  }
}

impl serialize::Decoder<ErrorType> for Decoder {

  fn read_nil(&mut self) -> DecodeResult<()> {
    Err(UnimplementedDecoder)
  }

  fn read_u64(&mut self)  -> DecodeResult<u64>  {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match FromStr::from_str(s.as_slice()) {
        None     => Err(self.expected("u64".to_string())),
        Some(nb) => Ok(nb)
      }
    }
  }
  fn read_u32(&mut self)  -> DecodeResult<u32>  { Ok(try!(self.read_u64()) as u32) }
  fn read_u16(&mut self)  -> DecodeResult<u16>  { Ok(try!(self.read_u64()) as u16) }
  fn read_u8 (&mut self)  -> DecodeResult<u8>   { Ok(try!(self.read_u64()) as u8) }
  fn read_uint(&mut self) -> DecodeResult<uint> { Ok(try!(self.read_u64()) as uint) }

  fn read_i64(&mut self) -> DecodeResult<i64> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match FromStr::from_str(s.as_slice()) {
        None     => Err(self.expected("i64".to_string())),
        Some(nb) => Ok(nb)
      }
    }
  }
  fn read_i32(&mut self) -> DecodeResult<i32> { Ok(try!(self.read_i64()) as i32) }
  fn read_i16(&mut self) -> DecodeResult<i16> { Ok(try!(self.read_i64()) as i16) }
  fn read_i8 (&mut self) -> DecodeResult<i8>  { Ok(try!(self.read_i64()) as i8) }
  fn read_int(&mut self) -> DecodeResult<int> { Ok(try!(self.read_i64()) as int) }

  fn read_f32(&mut self) -> DecodeResult<f32> { Ok(try!(self.read_f64()) as f32) }
  fn read_f64(&mut self) -> DecodeResult<f64> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match FromStr::from_str(s.as_slice()) {
        None     => Err(self.expected("f64".to_string())),
        Some(nb) => Ok(nb)
      }
    }
  }

  fn read_bool(&mut self) -> DecodeResult<bool> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match FromStr::from_str(s.as_slice()) {
        None     => Err(self.expected("boolean".to_string())),
        Some(b) => Ok(b)
      }
    }
  }

  fn read_char(&mut self) -> DecodeResult<char> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => if s.as_slice().char_len() == 1 { Ok(s.as_slice().char_at(0)) } else { Err(self.expected("char".to_string())) }
    }
  }

  fn read_str(&mut self) -> DecodeResult<String> {
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => Ok(s)
    }
  }

  fn read_enum<T>(&mut self, name: &str, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum: {}", name);
    self.current_type = name.to_string();
    f(self)
  }

  fn read_enum_variant<T>(&mut self, names: &[&str], f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum variant({}): {}", self.cur, names);
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => Err(MissingField(self.cur.clone())),
      Some(s) => match names.iter().position(|&e| e == s.as_slice()) {
        None    => Err(self.expected(self.current_type.clone().append(" enum"))),
        Some(i) => f(self, i)
      }
    }
  }

  fn read_enum_variant_arg<T>(&mut self, a_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum variant_arg: {}", a_idx);
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_enum_struct_variant<T>(&mut self, names: &[&str], f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum struct variant: {}", names);
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_enum_struct_variant_field<T>(&mut self, f_name: &str, f_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading enum struct variant field: {}, {}", f_name, f_idx);
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_struct<T>(&mut self, s_name: &str, len: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading struct: {} | len = {}", s_name, len);
    self.cur = s_name.to_string();
    f(self)
  }

  fn read_struct_field<T>(&mut self, f_name: &str, f_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("reading struct field: {} | idx = {}", f_name, f_idx);
    self.cur = f_name.to_string();
    let data = f(self);
    //println!("got struct field data: {}", data);
    data
  }

  fn read_option<T>(&mut self, f: |&mut Decoder, bool| -> DecodeResult<T>) -> DecodeResult<T> {
    //println!("read_option");
    match self.matches.opt_str(self.cur.as_slice()) {
      None    => {
        //println!("option not there");
        f(self, false)
      },
      Some(_) => {
        //println!("option is there");
        f(self, true)
      }
    }
  }

  fn read_tuple<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_tuple_arg<T>(&mut self, a_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_tuple_struct<T>(&mut self, s_name: &str, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_tuple_struct_arg<T>(&mut self, a_idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_seq<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_seq_elt<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_map<T>(&mut self, f: |&mut Decoder, uint| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self, 0);
    Err(UnimplementedDecoder)
  }

  fn read_map_elt_key<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

  fn read_map_elt_val<T>(&mut self, idx: uint, f: |&mut Decoder| -> DecodeResult<T>) -> DecodeResult<T> {
    f(self);
    Err(UnimplementedDecoder)
  }

  fn error(&mut self, err: &str) -> ErrorType {
    GenericError(err.to_string())
  }
}
<|endoftext|>


<commit_before>//! Solvent is a dependency resolver library written in rust.
//!
//! Solvent helps you to resolve dependency orderings by building up a dependency graph and then
//! resolving the dependences of some target node in an order such that each output depends only
//! upon the previous outputs.
//!
//! It is currently quite simple, but is still useful.
//!
//! #Example
//!
//! ```rust
//! extern crate solvent;
//!
//! use solvent::DepGraph;
//!
//! fn main() {
//!     // Create a new empty DepGraph.
//!     let mut depgraph: DepGraph<&str> = DepGraph::new();
//!
//!     // You can register a dependency like this. Solvent will automatically create nodes for
//!     // any term it has not seen before. This means 'b' depends on 'd'
//!     depgraph.register_dependency("b","d");
//!
//!     // You can also register multiple dependencies at once
//!     depgraph.register_dependencies("a",vec!["b","c","d"]);
//!     depgraph.register_dependencies("c",vec!["e"]);
//!
//!     // Iterate through each dependency of "a". The dependencies will be returned in an order
//!     // such that each output only depends on the previous outputs (or nothing). The target
//!     // itself will be output last.
//!     for node in depgraph.dependencies_of(&"a").unwrap() {
//!         match node {
//!             Ok(n) => print!("{} ", n),
//!             Err(e) => panic!("Solvent error detected: {:?}", e),
//!         }
//!     }
//! }
//! ```
//!
//! The above will output:  `d b e c a` or `e c d b a` or some other valid dependency order.
//!
//! The algorithm is not deterministic, and may give a different answer each time it is run. Beware.
//!
//! The iterator dependencies_of() returns an `Option<Result<T ,SolventError>>`.  The for loop
//! handles the `Option` part for you, but you may want to check the result for `SolventError`s.
//! Once an error is returned, all subsequent calls to the iterator `next()` will yield `None`.
//!
//! You can also mark some nodes as already satisfied, and the iterator will take that into
//! account
//!
//! ```ignore
//! depgraph.mark_as_satisfied(["e","c"]).unwrap();
//! ```
//!
//! Dependency cycles are detected and will return `SolventError::CycleDetected`.

pub mod error;
use error::SolventError;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::Entry;
use std::iter::{Iterator};

/// This is the dependency graph. The type `T` is intended to be a small type, or a
/// reference to a larger type that implements `Eq` (you will need to supply the type
/// and vectors of the type to functions).
#[derive(Debug,Clone)]
pub struct DepGraph<T: Eq> {
    // The nodes in the graph.  Each one is assigned a unique number.
    nodes: Vec<T>,

    // List of dependencies. The first node depends on the set of additional nodes.
    // We store indices into the nodes array.  This way we can have Eq + Copy + Hash
    // without any requirements on type T.
    dependencies: HashMap<usize, HashSet<usize>>,

    // The set of nodes already satisfied (by index into the nodes array).
    satisfied: HashSet<usize>,
}

impl<T: Eq> DepGraph<T> {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph<T> {
        DepGraph {
            nodes: Vec::new(),
            dependencies: HashMap::new(),
            satisfied: HashSet::new(),
        }
    }

    fn _pos(&self, node: &T) -> Option<usize> {
        self.nodes.iter().position(|x| x==node)
    }

    fn _register_node(&mut self, node: T) -> usize {
        match self._pos(&node) {
            Some(pos) => pos,
            None => {
                self.nodes.push(node);
                self.nodes.len() - 1
            }
        }
    }

    /// Register nodes in the graph. The `nodes` are added to any existing nodes,
    /// after checking to avoid duplicates.
    pub fn register_nodes(&mut self, mut nodes: Vec<T>) {
        for node in nodes.drain(..) {
            self.register_node(node);
        }
    }

    /// Register a node in the graph. The `node` is added to any existing nodes,
    /// after checking to avoid duplicates.
    pub fn register_node(&mut self, node: T) {
        self._register_node(node);
    }

    /// Add a dependency to a DepGraph. The node does not need to pre-exist, nor does the
    /// dependency node. If the node does pre-exist, the depends_on will be added to
    /// its existing dependency list. Otherwise it will be created.
    pub fn register_dependency(&mut self, node: T, depends_on: T) {

        let node_pos = self._register_node(node);
        let dep_pos = self._register_node(depends_on);

        match self.dependencies.entry( node_pos ) {
            Entry::Vacant(entry) => {
                let mut deps = HashSet::with_capacity(1);
                deps.insert( dep_pos );
                entry.insert( deps );
            },
            Entry::Occupied(mut entry) => {
                (*entry.get_mut()).insert( dep_pos );
            },
        }
    }

    /// Add multiple dependencies of one node to a DepGraph. The node does not need to
    /// pre-exist, nor does the dependency node. If the node does pre-exist, the
    /// depends_on will be added to its existing dependency list. Otherwise it will
    /// be created.
    pub fn register_dependencies(&mut self, node: T, mut depends_on: Vec<T>)
    {
        let node_pos = self._register_node(node);

        let mut dep_poses: Vec<usize> = Vec::new();
        for dp in depends_on.drain(..) {
            let pos = self._register_node(dp);
            dep_poses.push(pos);
        }

        match self.dependencies.entry( node_pos ) {
            Entry::Vacant(entry) => {
                let mut deps: HashSet<usize> = HashSet::with_capacity( dep_poses.len() );
                for pos in dep_poses.iter() {
                    deps.insert( *pos );
                }
                entry.insert( deps );
            },
            Entry::Occupied(mut entry) => {
                for pos in dep_poses.iter() {
                    (*entry.get_mut()).insert( *pos );
                }
            },
        }
    }

    /// This marks a node as satisfied. Iterators will not output such nodes. Nodes
    /// must exist.
    pub fn mark_as_satisfied(&mut self, nodes: &[T]) -> Result<(), SolventError>
    {
        for node in nodes.iter() {
            let node_pos = match self._pos(node) {
                None => return Err(SolventError::NoSuchNode),
                Some(pos) => pos
            };

            self.satisfied.insert( node_pos );
        }

        Ok(())
    }

    /// Get an iterator to iterate through the dependencies of the target node. Target
    /// node must exist.
    pub fn dependencies_of<'a>(&'a self, target: &T) -> Result<DepGraphIterator<'a, T>,
                                                               SolventError>
    {
        let pos = match self._pos(target) {
            None => return Err(SolventError::NoSuchNode),
            Some(p) => p
        };

        Ok(DepGraphIterator {
            depgraph: self,
            target: pos,
            satisfied: self.satisfied.clone(),
            curpath: HashSet::new(),
            halted: false,
        })
    }
}

/// This iterates through the dependencies of the DepGraph's target
pub struct DepGraphIterator<'a, T: Eq + 'a> {
    depgraph: &'a DepGraph<T>,

    // Target we are trying to satisfy
    target: usize,

    // Node positions already satisfied during this iterator's walk
    satisfied: HashSet<usize>,

    // Current path, for cycle detection
    curpath: HashSet<usize>,

    // Halted.  Used so that it can return None after an Err is returned.
    halted: bool,
}

impl<'a, T: Eq> DepGraphIterator<'a, T> {

    fn get_next_dependency(&mut self, pos: usize) -> Result<usize, SolventError>
    {
        if self.curpath.contains(&pos) {
            return Err(SolventError::CycleDetected);
        }
        self.curpath.insert(pos);

        let deplist = match self.depgraph.dependencies.get(&pos) {
            None => return Ok(pos),
            Some(deplist) => deplist
        };

        for n in deplist.iter() {
            // Prune satisfied nodes
            if self.satisfied.contains(n) {
                continue;
            }

            return self.get_next_dependency(*n);
        }

        // nodes dependencies are satisfied
        Ok(pos)
    }
}

impl<'a, T: Eq> Iterator for DepGraphIterator<'a, T> {
    type Item = Result<&'a T, SolventError>;

    // Get next dependency.  Returns None when finished.  If Some(Err(SolventError)) occurs,
    // all subsequent calls will return None.
    fn next(&mut self) -> Option<Result<&'a T, SolventError>>
    {
        if self.halted {
            return None;
        }

        let npos = self.target;
        if self.satisfied.contains(&npos) {
            self.halted = true;
            return None;
        }

        self.curpath.clear();
        let next = match self.get_next_dependency(npos) {
            Ok(d) => d,
            Err(e) => {
                self.halted = true;
                return Some(Err(e));
            }
        };
        self.satisfied.insert(next);
        Some(Ok(&self.depgraph.nodes[next]))
    }
}

#[cfg(test)]
mod test {
    use std::collections::HashSet;
    use super::DepGraph;
    use super::SolventError;

    #[test]
    fn solvent_test_branching() {
        let mut depgraph: DepGraph<&str> = DepGraph::new();

        depgraph.register_nodes(vec!["a","b","c","d","e","f","g","h","i","j","k","l","m","n"]);

        depgraph.register_dependencies("a", vec!["b","c","d"]);
        depgraph.register_dependency("b","d");
        depgraph.register_dependencies("c", vec!["e","m","g"]);
        depgraph.register_dependency("e","f");
        depgraph.register_dependency("g","h");
        depgraph.register_dependency("h","i");
        depgraph.register_dependencies("i", vec!["j","k"]);
        depgraph.register_dependencies("k", vec!["l","m"]);
        depgraph.register_dependency("m","n");

        let mut results: Vec<&str> = Vec::new();

        for node in depgraph.dependencies_of(&"a").unwrap() {
            // detect infinite looping bugs
            assert!(results.len() < 30);

            let n = match node {
                Err(e) => panic!("Solvent error detected: {:?}", e),
                Ok(n) => n,
            };

            // Check that all of that nodes dependencies have already been output
            let pos = depgraph._pos(&n).unwrap();
            let deps: Option<&HashSet<usize>> = depgraph.dependencies.get(&pos);
            if deps.is_some() {
                for dep in deps.unwrap().iter() {
                    assert!( results.contains(&depgraph.nodes[*dep]) );
                }
            }

            results.push(n.clone());
        }

        // Be sure we actually output enough stuff
        assert!(results.len() == 14);

        // Be sure each output is unique
        for result in results.iter() {
            let mut count: usize = 0;
            for result2 in results.iter() {
                if result == result2 { count = count + 1; }
            }
            assert!(count == 1);
        }
    }

    #[test]
    fn solvent_test_updating_dependencies() {
        let mut depgraph: DepGraph<&str> = DepGraph::new();

        depgraph.register_dependencies("a",vec!["b","c"]);
        depgraph.register_dependency("a","d");
        assert!(depgraph.dependencies.get(&0).unwrap().contains(&1));
        assert!(depgraph.dependencies.get(&0).unwrap().contains(&2));
        assert!(depgraph.dependencies.get(&0).unwrap().contains(&3));
    }

    #[test]
    fn solvent_test_circular() {

        let mut depgraph: DepGraph<&str> = DepGraph::new();
        depgraph.register_dependency("a","b");
        depgraph.register_dependency("b","c");
        depgraph.register_dependency("c","a");

        for node in depgraph.dependencies_of(&"a").unwrap() {
            assert!(node.is_err());
            assert!(node.unwrap_err() == SolventError::CycleDetected);
        }
    }

    #[test]
    fn solvent_test_satisfied_stoppage() {

        let mut depgraph: DepGraph<&str> = DepGraph::new();
        depgraph.register_dependencies("superconn", vec![]);
        depgraph.register_dependencies("owneruser", vec!["superconn"]);
        depgraph.register_dependencies("appuser", vec!["superconn"]);
        depgraph.register_dependencies("database", vec!["owneruser"]);
        depgraph.register_dependencies("ownerconn", vec!["database","owneruser"]);
        depgraph.register_dependencies("adminconn", vec!["database"]);
        depgraph.register_dependencies("extensions", vec!["database","adminconn"]);
        depgraph.register_dependencies("schema_table", vec!["database","ownerconn"]);
        depgraph.register_dependencies("schemas", vec!["ownerconn","extensions","schema_table","appuser"]);
        depgraph.register_dependencies("appconn", vec!["database","appuser","schemas"]);

        depgraph.mark_as_satisfied(&["owneruser","appuser"]).unwrap();
        assert_eq!( depgraph.satisfied.len() , 2 );

        let mut results: Vec<&str> = Vec::new();

        for node in depgraph.dependencies_of(&"appconn").unwrap() {
            assert!(results.len() < 30);
            match node {
                Ok(n) => results.push(n),
                Err(e) => panic!("Solvent error detected: {:?}",e),
            };
        }

        // Be sure we did not depend on these
        assert!( !results.contains( &"appuser") );
        assert!( !results.contains( &"owneruser") );
        assert!( !results.contains( &"superconn") );

        // Be sure we actually output enough stuff
        assert!(results.len() == 7);

        // Be sure each output is unique
        for result in results.iter() {
            let mut count: usize = 0;
            for result2 in results.iter() {
                if result == result2 { count = count + 1; }
            }
            assert!(count == 1);
        }
    }
}
<commit_msg>pub use SolventError in root of crate<commit_after>//! Solvent is a dependency resolver library written in rust.
//!
//! Solvent helps you to resolve dependency orderings by building up a dependency graph and then
//! resolving the dependences of some target node in an order such that each output depends only
//! upon the previous outputs.
//!
//! It is currently quite simple, but is still useful.
//!
//! #Example
//!
//! ```rust
//! extern crate solvent;
//!
//! use solvent::DepGraph;
//!
//! fn main() {
//!     // Create a new empty DepGraph.
//!     let mut depgraph: DepGraph<&str> = DepGraph::new();
//!
//!     // You can register a dependency like this. Solvent will automatically create nodes for
//!     // any term it has not seen before. This means 'b' depends on 'd'
//!     depgraph.register_dependency("b","d");
//!
//!     // You can also register multiple dependencies at once
//!     depgraph.register_dependencies("a",vec!["b","c","d"]);
//!     depgraph.register_dependencies("c",vec!["e"]);
//!
//!     // Iterate through each dependency of "a". The dependencies will be returned in an order
//!     // such that each output only depends on the previous outputs (or nothing). The target
//!     // itself will be output last.
//!     for node in depgraph.dependencies_of(&"a").unwrap() {
//!         match node {
//!             Ok(n) => print!("{} ", n),
//!             Err(e) => panic!("Solvent error detected: {:?}", e),
//!         }
//!     }
//! }
//! ```
//!
//! The above will output:  `d b e c a` or `e c d b a` or some other valid dependency order.
//!
//! The algorithm is not deterministic, and may give a different answer each time it is run. Beware.
//!
//! The iterator dependencies_of() returns an `Option<Result<T ,SolventError>>`.  The for loop
//! handles the `Option` part for you, but you may want to check the result for `SolventError`s.
//! Once an error is returned, all subsequent calls to the iterator `next()` will yield `None`.
//!
//! You can also mark some nodes as already satisfied, and the iterator will take that into
//! account
//!
//! ```ignore
//! depgraph.mark_as_satisfied(["e","c"]).unwrap();
//! ```
//!
//! Dependency cycles are detected and will return `SolventError::CycleDetected`.

pub mod error;
pub use error::SolventError;

use std::collections::{HashMap,HashSet};
use std::collections::hash_map::Entry;
use std::iter::{Iterator};

/// This is the dependency graph. The type `T` is intended to be a small type, or a
/// reference to a larger type that implements `Eq` (you will need to supply the type
/// and vectors of the type to functions).
#[derive(Debug,Clone)]
pub struct DepGraph<T: Eq> {
    // The nodes in the graph.  Each one is assigned a unique number.
    nodes: Vec<T>,

    // List of dependencies. The first node depends on the set of additional nodes.
    // We store indices into the nodes array.  This way we can have Eq + Copy + Hash
    // without any requirements on type T.
    dependencies: HashMap<usize, HashSet<usize>>,

    // The set of nodes already satisfied (by index into the nodes array).
    satisfied: HashSet<usize>,
}

impl<T: Eq> DepGraph<T> {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph<T> {
        DepGraph {
            nodes: Vec::new(),
            dependencies: HashMap::new(),
            satisfied: HashSet::new(),
        }
    }

    fn _pos(&self, node: &T) -> Option<usize> {
        self.nodes.iter().position(|x| x==node)
    }

    fn _register_node(&mut self, node: T) -> usize {
        match self._pos(&node) {
            Some(pos) => pos,
            None => {
                self.nodes.push(node);
                self.nodes.len() - 1
            }
        }
    }

    /// Register nodes in the graph. The `nodes` are added to any existing nodes,
    /// after checking to avoid duplicates.
    pub fn register_nodes(&mut self, mut nodes: Vec<T>) {
        for node in nodes.drain(..) {
            self.register_node(node);
        }
    }

    /// Register a node in the graph. The `node` is added to any existing nodes,
    /// after checking to avoid duplicates.
    pub fn register_node(&mut self, node: T) {
        self._register_node(node);
    }

    /// Add a dependency to a DepGraph. The node does not need to pre-exist, nor does the
    /// dependency node. If the node does pre-exist, the depends_on will be added to
    /// its existing dependency list. Otherwise it will be created.
    pub fn register_dependency(&mut self, node: T, depends_on: T) {

        let node_pos = self._register_node(node);
        let dep_pos = self._register_node(depends_on);

        match self.dependencies.entry( node_pos ) {
            Entry::Vacant(entry) => {
                let mut deps = HashSet::with_capacity(1);
                deps.insert( dep_pos );
                entry.insert( deps );
            },
            Entry::Occupied(mut entry) => {
                (*entry.get_mut()).insert( dep_pos );
            },
        }
    }

    /// Add multiple dependencies of one node to a DepGraph. The node does not need to
    /// pre-exist, nor does the dependency node. If the node does pre-exist, the
    /// depends_on will be added to its existing dependency list. Otherwise it will
    /// be created.
    pub fn register_dependencies(&mut self, node: T, mut depends_on: Vec<T>)
    {
        let node_pos = self._register_node(node);

        let mut dep_poses: Vec<usize> = Vec::new();
        for dp in depends_on.drain(..) {
            let pos = self._register_node(dp);
            dep_poses.push(pos);
        }

        match self.dependencies.entry( node_pos ) {
            Entry::Vacant(entry) => {
                let mut deps: HashSet<usize> = HashSet::with_capacity( dep_poses.len() );
                for pos in dep_poses.iter() {
                    deps.insert( *pos );
                }
                entry.insert( deps );
            },
            Entry::Occupied(mut entry) => {
                for pos in dep_poses.iter() {
                    (*entry.get_mut()).insert( *pos );
                }
            },
        }
    }

    /// This marks a node as satisfied. Iterators will not output such nodes. Nodes
    /// must exist.
    pub fn mark_as_satisfied(&mut self, nodes: &[T]) -> Result<(), SolventError>
    {
        for node in nodes.iter() {
            let node_pos = match self._pos(node) {
                None => return Err(SolventError::NoSuchNode),
                Some(pos) => pos
            };

            self.satisfied.insert( node_pos );
        }

        Ok(())
    }

    /// Get an iterator to iterate through the dependencies of the target node. Target
    /// node must exist.
    pub fn dependencies_of<'a>(&'a self, target: &T) -> Result<DepGraphIterator<'a, T>,
                                                               SolventError>
    {
        let pos = match self._pos(target) {
            None => return Err(SolventError::NoSuchNode),
            Some(p) => p
        };

        Ok(DepGraphIterator {
            depgraph: self,
            target: pos,
            satisfied: self.satisfied.clone(),
            curpath: HashSet::new(),
            halted: false,
        })
    }
}

/// This iterates through the dependencies of the DepGraph's target
pub struct DepGraphIterator<'a, T: Eq + 'a> {
    depgraph: &'a DepGraph<T>,

    // Target we are trying to satisfy
    target: usize,

    // Node positions already satisfied during this iterator's walk
    satisfied: HashSet<usize>,

    // Current path, for cycle detection
    curpath: HashSet<usize>,

    // Halted.  Used so that it can return None after an Err is returned.
    halted: bool,
}

impl<'a, T: Eq> DepGraphIterator<'a, T> {

    fn get_next_dependency(&mut self, pos: usize) -> Result<usize, SolventError>
    {
        if self.curpath.contains(&pos) {
            return Err(SolventError::CycleDetected);
        }
        self.curpath.insert(pos);

        let deplist = match self.depgraph.dependencies.get(&pos) {
            None => return Ok(pos),
            Some(deplist) => deplist
        };

        for n in deplist.iter() {
            // Prune satisfied nodes
            if self.satisfied.contains(n) {
                continue;
            }

            return self.get_next_dependency(*n);
        }

        // nodes dependencies are satisfied
        Ok(pos)
    }
}

impl<'a, T: Eq> Iterator for DepGraphIterator<'a, T> {
    type Item = Result<&'a T, SolventError>;

    // Get next dependency.  Returns None when finished.  If Some(Err(SolventError)) occurs,
    // all subsequent calls will return None.
    fn next(&mut self) -> Option<Result<&'a T, SolventError>>
    {
        if self.halted {
            return None;
        }

        let npos = self.target;
        if self.satisfied.contains(&npos) {
            self.halted = true;
            return None;
        }

        self.curpath.clear();
        let next = match self.get_next_dependency(npos) {
            Ok(d) => d,
            Err(e) => {
                self.halted = true;
                return Some(Err(e));
            }
        };
        self.satisfied.insert(next);
        Some(Ok(&self.depgraph.nodes[next]))
    }
}

#[cfg(test)]
mod test {
    use std::collections::HashSet;
    use super::DepGraph;
    use super::SolventError;

    #[test]
    fn solvent_test_branching() {
        let mut depgraph: DepGraph<&str> = DepGraph::new();

        depgraph.register_nodes(vec!["a","b","c","d","e","f","g","h","i","j","k","l","m","n"]);

        depgraph.register_dependencies("a", vec!["b","c","d"]);
        depgraph.register_dependency("b","d");
        depgraph.register_dependencies("c", vec!["e","m","g"]);
        depgraph.register_dependency("e","f");
        depgraph.register_dependency("g","h");
        depgraph.register_dependency("h","i");
        depgraph.register_dependencies("i", vec!["j","k"]);
        depgraph.register_dependencies("k", vec!["l","m"]);
        depgraph.register_dependency("m","n");

        let mut results: Vec<&str> = Vec::new();

        for node in depgraph.dependencies_of(&"a").unwrap() {
            // detect infinite looping bugs
            assert!(results.len() < 30);

            let n = match node {
                Err(e) => panic!("Solvent error detected: {:?}", e),
                Ok(n) => n,
            };

            // Check that all of that nodes dependencies have already been output
            let pos = depgraph._pos(&n).unwrap();
            let deps: Option<&HashSet<usize>> = depgraph.dependencies.get(&pos);
            if deps.is_some() {
                for dep in deps.unwrap().iter() {
                    assert!( results.contains(&depgraph.nodes[*dep]) );
                }
            }

            results.push(n.clone());
        }

        // Be sure we actually output enough stuff
        assert!(results.len() == 14);

        // Be sure each output is unique
        for result in results.iter() {
            let mut count: usize = 0;
            for result2 in results.iter() {
                if result == result2 { count = count + 1; }
            }
            assert!(count == 1);
        }
    }

    #[test]
    fn solvent_test_updating_dependencies() {
        let mut depgraph: DepGraph<&str> = DepGraph::new();

        depgraph.register_dependencies("a",vec!["b","c"]);
        depgraph.register_dependency("a","d");
        assert!(depgraph.dependencies.get(&0).unwrap().contains(&1));
        assert!(depgraph.dependencies.get(&0).unwrap().contains(&2));
        assert!(depgraph.dependencies.get(&0).unwrap().contains(&3));
    }

    #[test]
    fn solvent_test_circular() {

        let mut depgraph: DepGraph<&str> = DepGraph::new();
        depgraph.register_dependency("a","b");
        depgraph.register_dependency("b","c");
        depgraph.register_dependency("c","a");

        for node in depgraph.dependencies_of(&"a").unwrap() {
            assert!(node.is_err());
            assert!(node.unwrap_err() == SolventError::CycleDetected);
        }
    }

    #[test]
    fn solvent_test_satisfied_stoppage() {

        let mut depgraph: DepGraph<&str> = DepGraph::new();
        depgraph.register_dependencies("superconn", vec![]);
        depgraph.register_dependencies("owneruser", vec!["superconn"]);
        depgraph.register_dependencies("appuser", vec!["superconn"]);
        depgraph.register_dependencies("database", vec!["owneruser"]);
        depgraph.register_dependencies("ownerconn", vec!["database","owneruser"]);
        depgraph.register_dependencies("adminconn", vec!["database"]);
        depgraph.register_dependencies("extensions", vec!["database","adminconn"]);
        depgraph.register_dependencies("schema_table", vec!["database","ownerconn"]);
        depgraph.register_dependencies("schemas", vec!["ownerconn","extensions","schema_table","appuser"]);
        depgraph.register_dependencies("appconn", vec!["database","appuser","schemas"]);

        depgraph.mark_as_satisfied(&["owneruser","appuser"]).unwrap();
        assert_eq!( depgraph.satisfied.len() , 2 );

        let mut results: Vec<&str> = Vec::new();

        for node in depgraph.dependencies_of(&"appconn").unwrap() {
            assert!(results.len() < 30);
            match node {
                Ok(n) => results.push(n),
                Err(e) => panic!("Solvent error detected: {:?}",e),
            };
        }

        // Be sure we did not depend on these
        assert!( !results.contains( &"appuser") );
        assert!( !results.contains( &"owneruser") );
        assert!( !results.contains( &"superconn") );

        // Be sure we actually output enough stuff
        assert!(results.len() == 7);

        // Be sure each output is unique
        for result in results.iter() {
            let mut count: usize = 0;
            for result2 in results.iter() {
                if result == result2 { count = count + 1; }
            }
            assert!(count == 1);
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate error_chain;
extern crate xcb;

#[macro_use] pub mod error;

use std::thread;
use xcb::{ Connection, Window, Atom };

pub struct Atoms {
    pub primary: Atom,
    pub clipboard: Atom,
    pub property: Atom,
    pub targets: Atom,
    pub string: Atom,
    pub utf8_string: Atom,
    pub incr: Atom
}

pub struct Clipboard {
    pub connection: Connection,
    pub window: Window,
    pub atoms: Atoms
}

impl Clipboard {
    pub fn new<'a, D>(displayname: D) -> error::Result<Self>
        where D: Into<Option<&'a str>>
    {
        let (connection, screen) = Connection::connect(displayname.into())
            .map_err(|err| err!(XcbConn, err))?;
        let window = connection.generate_id();

        {
            let screen = connection.get_setup().roots().nth(screen as usize)
                .ok_or(err!(XcbConn, ::xcb::ConnError::ClosedInvalidScreen))?;
            xcb::create_window(
                &connection,
                xcb::COPY_FROM_PARENT as u8,
                window, screen.root(),
                0, 0, 1, 1,
                0,
                xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                screen.root_visual(),
                &[(
                    xcb::CW_EVENT_MASK,
                    xcb::EVENT_MASK_STRUCTURE_NOTIFY | xcb::EVENT_MASK_PROPERTY_CHANGE
                )]
            );
            connection.flush();
        }

        Self::from_connection(connection, window)
    }

    pub fn from_connection(connection: Connection, window: Window) -> error::Result<Self> {
        macro_rules! intern_atom {
            ( $name:expr ) => {
                xcb::intern_atom(&connection, false, $name)
                    .get_reply()
                    .map_err(|err| err!(XcbGeneric, err))?.atom()
            }
        }

        let atoms = Atoms {
            primary: xcb::ATOM_PRIMARY,
            clipboard: intern_atom!("CLIPBOARD"),
            property: intern_atom!("THIS_CLIPBOARD_OUT"),
            targets: intern_atom!("TARGETS"),
            string: xcb::ATOM_STRING,
            utf8_string: intern_atom!("UTF8_STRING"),
            incr: intern_atom!("INCR")
        };

        Ok(Clipboard { connection, window, atoms })
    }

    pub fn load(&self, selection: Atom, target: Atom, property: Atom) -> error::Result<Vec<u8>> {
        let mut buff = Vec::new();
        let mut is_incr = false;

        xcb::convert_selection(
            &self.connection, self.window,
            selection, target, property,
            xcb::CURRENT_TIME
                // FIXME Clients should not use CurrentTime for the time argument of a ConvertSelection request.
                // Instead, they should use the timestamp of the event that caused the request to be made.
        );
        self.connection.flush();

        while let Some(event) = self.connection.wait_for_event() {
            match (event.response_type() & !0x80) {
                xcb::SELECTION_NOTIFY => {
                    let event = xcb::cast_event::<xcb::SelectionNotifyEvent>(&event);

                    if event.selection() != selection || event.property() != property {
                        continue
                    }

                    let reply = xcb::get_property(
                        &self.connection,
                        false, self.window,
                        event.property(), xcb::ATOM_ANY,
                        buff.len() as u32, ::std::u32::MAX // FIXME reasonable buffer size
                    )
                        .get_reply()
                        .map_err(|err| err!(XcbGeneric, err))?;

                    if reply.type_() == self.atoms.incr {
                        buff.reserve(reply.value::<i32>()[0] as usize);
                        xcb::delete_property(&self.connection, self.window, property);
                        self.connection.flush();
                        is_incr = true;
                        continue
                    }

                    if reply.type_() != self.atoms.string
                        && reply.type_() != self.atoms.utf8_string
                    {
                        let name = xcb::get_atom_name(&self.connection, reply.type_())
                            .get_reply()
                            .map(|reply| reply.name().to_string())
                            .unwrap_or(format!("Unknown({})", reply.type_()));
                        return Err(err!(NotSupportType, name));
                    }

                    buff.extend_from_slice(reply.value());
                    break
                },
                xcb::PROPERTY_NOTIFY if is_incr => {
                    let event = xcb::cast_event::<xcb::PropertyNotifyEvent>(&event);

                    if event.state() != xcb::PROPERTY_NEW_VALUE as u8 {
                        continue
                    }

                    let length = xcb::get_property(
                        &self.connection,
                        false, self.window,
                        property, xcb::ATOM_ANY,
                        0, 0
                    )
                        .get_reply()
                        .map(|reply| reply.bytes_after())
                        .map_err(|err| err!(XcbGeneric, err))?;

                    let reply = xcb::get_property(
                        &self.connection,
                        true, self.window,
                        property, xcb::ATOM_ANY,
                        0, length
                    )
                        .get_reply()
                        .map_err(|err| err!(XcbGeneric, err))?;

                    if reply.type_() != self.atoms.string
                        && reply.type_() != self.atoms.utf8_string
                    {
                        continue
                    }

                    buff.extend_from_slice(reply.value());

                    if reply.value_len() == 0 {
                        break
                    }
                },
                _ => ()
            }
        }

        xcb::delete_property(&self.connection, self.window, property);
        self.connection.flush();
        Ok(buff)
    }

    fn store(&self, selection: Atom, target: Atom, property: Atom, value: &[u8]) -> error::Result<()> {
        unimplemented!()
    }
}
<commit_msg>[Fixed] check type<commit_after>#[macro_use] extern crate error_chain;
extern crate xcb;

#[macro_use] pub mod error;

use std::thread;
use xcb::{ Connection, Window, Atom };

pub struct Atoms {
    pub primary: Atom,
    pub clipboard: Atom,
    pub property: Atom,
    pub targets: Atom,
    pub string: Atom,
    pub utf8_string: Atom,
    pub incr: Atom
}

pub struct Clipboard {
    pub connection: Connection,
    pub window: Window,
    pub atoms: Atoms
}

impl Clipboard {
    pub fn new<'a, D>(displayname: D) -> error::Result<Self>
        where D: Into<Option<&'a str>>
    {
        let (connection, screen) = Connection::connect(displayname.into())
            .map_err(|err| err!(XcbConn, err))?;
        let window = connection.generate_id();

        {
            let screen = connection.get_setup().roots().nth(screen as usize)
                .ok_or(err!(XcbConn, ::xcb::ConnError::ClosedInvalidScreen))?;
            xcb::create_window(
                &connection,
                xcb::COPY_FROM_PARENT as u8,
                window, screen.root(),
                0, 0, 1, 1,
                0,
                xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                screen.root_visual(),
                &[(
                    xcb::CW_EVENT_MASK,
                    xcb::EVENT_MASK_STRUCTURE_NOTIFY | xcb::EVENT_MASK_PROPERTY_CHANGE
                )]
            );
            connection.flush();
        }

        Self::from_connection(connection, window)
    }

    pub fn from_connection(connection: Connection, window: Window) -> error::Result<Self> {
        macro_rules! intern_atom {
            ( $name:expr ) => {
                xcb::intern_atom(&connection, false, $name)
                    .get_reply()
                    .map_err(|err| err!(XcbGeneric, err))?.atom()
            }
        }

        let atoms = Atoms {
            primary: xcb::ATOM_PRIMARY,
            clipboard: intern_atom!("CLIPBOARD"),
            property: intern_atom!("THIS_CLIPBOARD_OUT"),
            targets: intern_atom!("TARGETS"),
            string: xcb::ATOM_STRING,
            utf8_string: intern_atom!("UTF8_STRING"),
            incr: intern_atom!("INCR")
        };

        Ok(Clipboard { connection, window, atoms })
    }

    pub fn load(&self, selection: Atom, target: Atom, property: Atom) -> error::Result<Vec<u8>> {
        let mut buff = Vec::new();
        let mut is_incr = false;

        xcb::convert_selection(
            &self.connection, self.window,
            selection, target, property,
            xcb::CURRENT_TIME
                // FIXME ^
                // Clients should not use CurrentTime for the time argument of a ConvertSelection request.
                // Instead, they should use the timestamp of the event that caused the request to be made.
        );
        self.connection.flush();

        while let Some(event) = self.connection.wait_for_event() {
            match (event.response_type() & !0x80) {
                xcb::SELECTION_NOTIFY => {
                    let event = xcb::cast_event::<xcb::SelectionNotifyEvent>(&event);

                    if event.selection() != selection || event.property() != property {
                        continue
                    }

                    let reply = xcb::get_property(
                        &self.connection,
                        false, self.window,
                        event.property(), xcb::ATOM_ANY,
                        buff.len() as u32, ::std::u32::MAX // FIXME reasonable buffer size
                    )
                        .get_reply()
                        .map_err(|err| err!(XcbGeneric, err))?;

                    if reply.type_() == self.atoms.incr {
                        buff.reserve(reply.value::<i32>()[0] as usize);
                        xcb::delete_property(&self.connection, self.window, property);
                        self.connection.flush();
                        is_incr = true;
                        continue
                    }

                    if reply.type_() != target {
                        let name = xcb::get_atom_name(&self.connection, reply.type_())
                            .get_reply()
                            .map(|reply| reply.name().to_string())
                            .unwrap_or(format!("Unknown({})", reply.type_()));
                        return Err(err!(NotSupportType, name));
                    }

                    buff.extend_from_slice(reply.value());
                    break
                },
                xcb::PROPERTY_NOTIFY if is_incr => {
                    let event = xcb::cast_event::<xcb::PropertyNotifyEvent>(&event);

                    if event.state() != xcb::PROPERTY_NEW_VALUE as u8 {
                        continue
                    }

                    let length = xcb::get_property(
                        &self.connection,
                        false, self.window,
                        property, xcb::ATOM_ANY,
                        0, 0
                    )
                        .get_reply()
                        .map(|reply| reply.bytes_after())
                        .map_err(|err| err!(XcbGeneric, err))?;

                    let reply = xcb::get_property(
                        &self.connection,
                        true, self.window,
                        property, xcb::ATOM_ANY,
                        0, length
                    )
                        .get_reply()
                        .map_err(|err| err!(XcbGeneric, err))?;

                    if reply.type_() != target {
                        continue
                    }

                    buff.extend_from_slice(reply.value());

                    if reply.value_len() == 0 {
                        break
                    }
                },
                _ => ()
            }
        }

        xcb::delete_property(&self.connection, self.window, property);
        self.connection.flush();
        Ok(buff)
    }

    fn store(&self, selection: Atom, target: Atom, property: Atom, value: &[u8]) -> error::Result<()> {
        unimplemented!()
    }
}
<|endoftext|>