<commit_before>use nom::{IResult};
use nom::{le_u64,le_u32,le_u16};
// FIXME(richo) Flesh this out properly with it's own discrete parser.
#[derive(Debug)]
pub struct Options<'a> {
    pub options: Vec<Opt<'a>>,
}

#[derive(Debug)]
pub struct Opt<'a> {
    code: u16,
    length: u16,
    value: &'a [u8],
}

//  0                   1                   2                   3
//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |      Option Code              |         Option Length         |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// /                       Option Value                            /
// /          /* variable length, aligned to 32 bits */            /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// /                                                               /
// /                 . . . other options . . .                     /
// /                                                               /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |   Option Code == opt_endofopt  |  Option Length == 0          |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

#[inline(Always)]
// Debug helper, since at various points being able to dump how much it's planning to read has been
// really handy
fn expand(i: u16) -> usize {
    i as usize
}

named!(option<&[u8],Opt>,
       chain!(
           code: le_u16 ~
           length: le_u16 ~
           value: take!(expand(length)) ,
           ||{
               Opt {
                   code: code,
                   length: length,
                   value: value,
               }
           }
           )
      );

// It's not abundantly clear to me that this is actually safe.
// My belief is that because we're operating on a &[u8] that was carved out of the high level
// buffer, and that *it* is a fat pointer with a length, the runtime will stop us from running off
// the end, but it needs to be actually proven.
named!(pub parse_options< &[u8],Options >,
       chain!(
           opts: many1!(option),
           ||{
               // It's also not super clear to me that we actually want to include the final option
               // in the vector
               if let Some(last) = opts.last() {
                   assert_eq!(last.code, 0x0);
                   assert_eq!(last.length, 0x0);
               }
               Options {
                   options: opts
               }
           }
           )
      );

#[test]
fn test_parse_options() {
    let input = b"\x12\x42\x08\x00asdfasdf\x00\x00\x00\x00";
    match parse_options(input) {
        IResult::Done(left, opts) => {
            assert_eq!(opts.options.len(), 2);
            let o = &opts.options[0];
            assert_eq!(o.code, 0x4212);
            assert_eq!(o.length, 0x08);
            assert_eq!(o.value, b"asdfasdf");

        },
        _ => {
            panic!("Hit a codepath we shouldn't have");
        },
    }
}

<commit_msg>Fix case<commit_after>use nom::{IResult};
use nom::{le_u64,le_u32,le_u16};
// FIXME(richo) Flesh this out properly with it's own discrete parser.
#[derive(Debug)]
pub struct Options<'a> {
    pub options: Vec<Opt<'a>>,
}

#[derive(Debug)]
pub struct Opt<'a> {
    code: u16,
    length: u16,
    value: &'a [u8],
}

//  0                   1                   2                   3
//  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |      Option Code              |         Option Length         |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// /                       Option Value                            /
// /          /* variable length, aligned to 32 bits */            /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// /                                                               /
// /                 . . . other options . . .                     /
// /                                                               /
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// |   Option Code == opt_endofopt  |  Option Length == 0          |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

#[inline(always)]
// Debug helper, since at various points being able to dump how much it's planning to read has been
// really handy
fn expand(i: u16) -> usize {
    i as usize
}

named!(option<&[u8],Opt>,
       chain!(
           code: le_u16 ~
           length: le_u16 ~
           value: take!(expand(length)) ,
           ||{
               Opt {
                   code: code,
                   length: length,
                   value: value,
               }
           }
           )
      );

// It's not abundantly clear to me that this is actually safe.
// My belief is that because we're operating on a &[u8] that was carved out of the high level
// buffer, and that *it* is a fat pointer with a length, the runtime will stop us from running off
// the end, but it needs to be actually proven.
named!(pub parse_options< &[u8],Options >,
       chain!(
           opts: many1!(option),
           ||{
               // It's also not super clear to me that we actually want to include the final option
               // in the vector
               if let Some(last) = opts.last() {
                   assert_eq!(last.code, 0x0);
                   assert_eq!(last.length, 0x0);
               }
               Options {
                   options: opts
               }
           }
           )
      );

#[test]
fn test_parse_options() {
    let input = b"\x12\x42\x08\x00asdfasdf\x00\x00\x00\x00";
    match parse_options(input) {
        IResult::Done(left, opts) => {
            assert_eq!(opts.options.len(), 2);
            let o = &opts.options[0];
            assert_eq!(o.code, 0x4212);
            assert_eq!(o.length, 0x08);
            assert_eq!(o.value, b"asdfasdf");

        },
        _ => {
            panic!("Hit a codepath we shouldn't have");
        },
    }
}

<|endoftext|>


<commit_before>use std::sync::{Arc, RwLock};
use std::option::Option;

use uuid::Uuid;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

pub struct CellFormat {
    name: String,
    type_: CellType
}

pub struct RecFormat {
    cols: Vec<CellFormat>
}

trait Metaformat<T> {
    fn construct(format_: CellFormat) -> T;
}

pub struct Cell {
    value: CellType
}

impl Metaformat<Cell> for Cell {
    fn construct(format_: CellFormat) -> Cell {
        return match format_.type_ {
            CellType::Int32(_) => Cell { value: CellType::Int32(None) },
            CellType::Int64(_) => Cell { value: CellType::Int64(None) },
            CellType::Text(_) => Cell { value: CellType::Text(None) }
        }
    }
}

trait Container<T> {
    fn size(&self) -> usize;
    fn push(&mut self, item: T);
    //fn remove
}

pub struct Rec {
    pub guid: Uuid,
    pub cells: Vec<Cell>,
    pub format: Arc<RwLock<RecFormat>>
}

pub fn construct_rec(format: Arc<RwLock<RecFormat>>) -> Rec {
    let cells = format.read().unwrap().clone();
    return Rec{guid: Uuid::new_v4(),
        cells: cells,
        format: format}
}

impl Container<Cell> for Rec {

    fn size(&self) -> usize {
        return self.cells.len();
    }

    fn push(&mut self, item: Cell) {
        self.cells.push(item);
    }
}

pub struct Table {
    pub name: String,
    pub rows: Vec<Rec>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Container<Rec> for Table {
    fn size(&self) -> usize {
        return self.rows.len();
    }

    fn push(&mut self, item: Rec) {
        self.rows.push(item);
    }
}
<commit_msg>I want rustc on my pc<commit_after>use std::sync::{Arc, RwLock};
use std::option::Option;

use uuid::Uuid;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

pub struct CellFormat {
    name: String,
    type_: CellType
}

pub struct RecFormat {
    cols: Vec<CellFormat>
}

trait Metaformat<T> {
    fn construct(format_: CellFormat) -> T;
}

pub struct Cell {
    value: CellType
}

impl Metaformat<Cell> for Cell {
    fn construct(format_: CellFormat) -> Cell {
        return match format_.type_ {
            CellType::Int32(_) => Cell { value: CellType::Int32(None) },
            CellType::Int64(_) => Cell { value: CellType::Int64(None) },
            CellType::Text(_) => Cell { value: CellType::Text(None) }
        }
    }
}

trait Container<T> {
    fn size(&self) -> usize;
    fn push(&mut self, item: T);
    //fn remove
}

pub struct Rec {
    pub guid: Uuid,
    pub cells: Vec<Cell>,
    pub format: Arc<RwLock<RecFormat>>
}

pub fn construct_rec(format: Arc<RwLock<RecFormat>>) -> Rec {
    let cells = format.read().unwrap().cols.clone();
    return Rec{guid: Uuid::new_v4(),
        cells: cells,
        format: format}
}

impl Container<Cell> for Rec {

    fn size(&self) -> usize {
        return self.cells.len();
    }

    fn push(&mut self, item: Cell) {
        self.cells.push(item);
    }
}

pub struct Table {
    pub name: String,
    pub rows: Vec<Rec>,
    pub format: Arc<RwLock<RecFormat>>
}

impl Container<Rec> for Table {
    fn size(&self) -> usize {
        return self.rows.len();
    }

    fn push(&mut self, item: Rec) {
        self.rows.push(item);
    }
}
<|endoftext|>


<commit_before>//! A BSON document represented as an associative HashMap with insertion ordering.

use std::error;
use std::fmt::{self, Debug, Display, Formatter};
use std::iter::{FromIterator, Map};
use std::marker::PhantomData;

use chrono::{DateTime, Utc};

use linked_hash_map::{self, LinkedHashMap};

use serde::de::{self, MapAccess, Visitor};

use bson::{Array, Bson, Document};
use decimal128::Decimal128;
use oid::ObjectId;
use spec::BinarySubtype;

/// Error to indicate that either a value was empty or it contained an unexpected
/// type, for use with the direct getters.
#[derive(PartialEq)]
pub enum ValueAccessError {
    /// Cannot find the expected field with the specified key
    NotPresent,
    /// Found a Bson value with the specified key, but not with the expected type
    UnexpectedType,
}

/// Result of accessing Bson value
pub type ValueAccessResult<T> = Result<T, ValueAccessError>;

impl Debug for ValueAccessError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            ValueAccessError::NotPresent => write!(f, "ValueAccessError: field is not present"),
            ValueAccessError::UnexpectedType => write!(f, "ValueAccessError: field does not have the expected type"),
        }
    }
}

impl Display for ValueAccessError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            ValueAccessError::NotPresent => write!(f, "field is not present"),
            ValueAccessError::UnexpectedType => write!(f, "field does not have the expected type"),
        }
    }
}

impl error::Error for ValueAccessError {
    fn description(&self) -> &str {
        "Error to indicate that either a value was empty or it contained an unexpected type"
    }
}

/// A BSON document represented as an associative HashMap with insertion ordering.
#[derive(Clone, PartialEq)]
pub struct OrderedDocument {
    inner: LinkedHashMap<String, Bson>,
}

impl Default for OrderedDocument {
    fn default() -> Self {
        Document::new()
    }
}

impl Display for OrderedDocument {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.write_str("{")?;

        let mut first = true;
        for (k, v) in self {
            if first {
                first = false;
                fmt.write_str(" ")?;
            } else {
                fmt.write_str(", ")?;
            }

            write!(fmt, "{}: {}", k, v)?;
        }

        write!(fmt, "{}}}", if !first { " " } else { "" })
    }
}

impl Debug for OrderedDocument {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "OrderedDocument({:?})", self.inner)
    }
}

/// An iterator over OrderedDocument entries.
pub struct OrderedDocumentIntoIterator {
    inner: LinkedHashMap<String, Bson>,
}

/// An owning iterator over OrderedDocument entries.
pub struct OrderedDocumentIterator<'a> {
    inner: linked_hash_map::Iter<'a, String, Bson>,
}

/// An iterator over an OrderedDocument's keys.
pub struct Keys<'a> {
    inner: Map<OrderedDocumentIterator<'a>, fn((&'a String, &'a Bson)) -> &'a String>,
}

/// An iterator over an OrderedDocument's values.
pub struct Values<'a> {
    inner: Map<OrderedDocumentIterator<'a>, fn((&'a String, &'a Bson)) -> &'a Bson>,
}

impl<'a> Iterator for Keys<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<(&'a String)> {
        self.inner.next()
    }
}

impl<'a> Iterator for Values<'a> {
    type Item = &'a Bson;

    fn next(&mut self) -> Option<(&'a Bson)> {
        self.inner.next()
    }
}

impl IntoIterator for OrderedDocument {
    type Item = (String, Bson);
    type IntoIter = OrderedDocumentIntoIterator;

    fn into_iter(self) -> Self::IntoIter {
        OrderedDocumentIntoIterator { inner: self.inner }
    }
}

impl<'a> IntoIterator for &'a OrderedDocument {
    type Item = (&'a String, &'a Bson);
    type IntoIter = OrderedDocumentIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        OrderedDocumentIterator { inner: self.inner.iter(), }
    }
}

impl FromIterator<(String, Bson)> for OrderedDocument {
    fn from_iter<T: IntoIterator<Item = (String, Bson)>>(iter: T) -> Self {
        let mut doc = OrderedDocument::new();
        for (k, v) in iter {
            doc.insert(k, v);
        }
        doc
    }
}

impl<'a> Iterator for OrderedDocumentIntoIterator {
    type Item = (String, Bson);

    fn next(&mut self) -> Option<(String, Bson)> {
        self.inner.pop_front()
    }
}

impl<'a> Iterator for OrderedDocumentIterator<'a> {
    type Item = (&'a String, &'a Bson);

    fn next(&mut self) -> Option<(&'a String, &'a Bson)> {
        self.inner.next()
    }
}

impl OrderedDocument {
    /// Creates a new empty OrderedDocument.
    pub fn new() -> OrderedDocument {
        OrderedDocument { inner: LinkedHashMap::new(), }
    }

    /// Gets an iterator over the entries of the map.
    pub fn iter<'a>(&'a self) -> OrderedDocumentIterator<'a> {
        self.into_iter()
    }

    /// Clears the document, removing all values.
    pub fn clear(&mut self) {
        self.inner.clear();
    }

    /// Returns a reference to the Bson corresponding to the key.
    pub fn get(&self, key: &str) -> Option<&Bson> {
        self.inner.get(key)
    }

    /// Gets a mutable reference to the Bson corresponding to the key
    pub fn get_mut(&mut self, key: &str) -> Option<&mut Bson> {
        self.inner.get_mut(key)
    }

    /// Get a floating point value for this key if it exists and has
    /// the correct type.
    pub fn get_f64(&self, key: &str) -> ValueAccessResult<f64> {
        match self.get(key) {
            Some(&Bson::FloatingPoint(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get Decimal128 value for key, if it exists.
    pub fn get_decimal128(&self, key: &str) -> ValueAccessResult<&Decimal128> {
        match self.get(key) {
            Some(&Bson::Decimal128(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a string slice this key if it exists and has the correct type.
    pub fn get_str(&self, key: &str) -> ValueAccessResult<&str> {
        match self.get(key) {
            Some(&Bson::String(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a reference to an array for this key if it exists and has
    /// the correct type.
    pub fn get_array(&self, key: &str) -> ValueAccessResult<&Array> {
        match self.get(key) {
            Some(&Bson::Array(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a reference to a document for this key if it exists and has
    /// the correct type.
    pub fn get_document(&self, key: &str) -> ValueAccessResult<&Document> {
        match self.get(key) {
            Some(&Bson::Document(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a bool value for this key if it exists and has the correct type.
    pub fn get_bool(&self, key: &str) -> ValueAccessResult<bool> {
        match self.get(key) {
            Some(&Bson::Boolean(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Returns wether this key has a null value
    pub fn is_null(&self, key: &str) -> bool {
        self.get(key) == Some(&Bson::Null)
    }

    /// Get an i32 value for this key if it exists and has the correct type.
    pub fn get_i32(&self, key: &str) -> ValueAccessResult<i32> {
        match self.get(key) {
            Some(&Bson::I32(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get an i64 value for this key if it exists and has the correct type.
    pub fn get_i64(&self, key: &str) -> ValueAccessResult<i64> {
        match self.get(key) {
            Some(&Bson::I64(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a time stamp value for this key if it exists and has the correct type.
    pub fn get_time_stamp(&self, key: &str) -> ValueAccessResult<i64> {
        match self.get(key) {
            Some(&Bson::TimeStamp(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a generic binary value for this key if it exists and has the correct type.
    pub fn get_binary_generic(&self, key: &str) -> ValueAccessResult<&Vec<u8>> {
        match self.get(key) {
            Some(&Bson::Binary(BinarySubtype::Generic, ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get an object id value for this key if it exists and has the correct type.
    pub fn get_object_id(&self, key: &str) -> ValueAccessResult<&ObjectId> {
        match self.get(key) {
            Some(&Bson::ObjectId(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a UTC datetime value for this key if it exists and has the correct type.
    pub fn get_utc_datetime(&self, key: &str) -> ValueAccessResult<&DateTime<Utc>> {
        match self.get(key) {
            Some(&Bson::UtcDatetime(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Returns true if the map contains a value for the specified key.
    pub fn contains_key(&self, key: &str) -> bool {
        self.inner.contains_key(key)
    }

    /// Gets a collection of all keys in the document.
    pub fn keys<'a>(&'a self) -> Keys<'a> {
        fn first<A, B>((a, _): (A, B)) -> A {
            a
        }
        let first: fn((&'a String, &'a Bson)) -> &'a String = first;

        Keys { inner: self.iter().map(first), }
    }

    /// Gets a collection of all values in the document.
    pub fn values<'a>(&'a self) -> Values<'a> {
        fn second<A, B>((_, b): (A, B)) -> B {
            b
        }
        let second: fn((&'a String, &'a Bson)) -> &'a Bson = second;

        Values { inner: self.iter().map(second), }
    }

    /// Returns the number of elements in the document.
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    /// Returns true if the document contains no elements
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }

    /// Sets the value of the entry with the OccupiedEntry's key,
    /// and returns the entry's old value. Accepts any type that
    /// can be converted into Bson.
    pub fn insert<KT: Into<String>, BT: Into<Bson>>(&mut self, key: KT, val: BT) -> Option<Bson> {
        self.insert_bson(key.into(), val.into())
    }

    /// Sets the value of the entry with the OccupiedEntry's key,
    /// and returns the entry's old value.
    pub fn insert_bson(&mut self, key: String, val: Bson) -> Option<Bson> {
        self.inner.insert(key, val)
    }

    /// Takes the value of the entry out of the document, and returns it.
    pub fn remove(&mut self, key: &str) -> Option<Bson> {
        self.inner.remove(key)
    }

    pub fn entry(&mut self, k: String) -> Entry {
        Entry { inner: self.inner.entry(k), }
    }
}

pub struct Entry<'a> {
    inner: linked_hash_map::Entry<'a, String, Bson>,
}

impl<'a> Entry<'a> {
    pub fn key(&self) -> &str {
        self.inner.key()
    }

    pub fn or_insert(self, default: Bson) -> &'a mut Bson {
        self.inner.or_insert(default)
    }

    pub fn or_insert_with<F: FnOnce() -> Bson>(self, default: F) -> &'a mut Bson {
        self.inner.or_insert_with(default)
    }
}

impl From<LinkedHashMap<String, Bson>> for OrderedDocument {
    fn from(tree: LinkedHashMap<String, Bson>) -> OrderedDocument {
        OrderedDocument { inner: tree }
    }
}

pub struct OrderedDocumentVisitor {
    marker: PhantomData<OrderedDocument>,
}

impl OrderedDocumentVisitor {
    pub fn new() -> OrderedDocumentVisitor {
        OrderedDocumentVisitor { marker: PhantomData }
    }
}

impl<'de> Visitor<'de> for OrderedDocumentVisitor {
    type Value = OrderedDocument;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "expecting ordered document")
    }

    #[inline]
    fn visit_unit<E>(self) -> Result<OrderedDocument, E>
        where E: de::Error
    {
        Ok(OrderedDocument::new())
    }

    #[inline]
    fn visit_map<V>(self, mut visitor: V) -> Result<OrderedDocument, V::Error>
        where V: MapAccess<'de>
    {
        let mut inner = match visitor.size_hint() {
            Some(size) => LinkedHashMap::with_capacity(size),
            None => LinkedHashMap::new(),
        };

        while let Some((key, value)) = visitor.next_entry()? {
            inner.insert(key, value);
        }

        Ok(inner.into())
    }
}
<commit_msg>[#119] implemented Extend<(String, Bson)> for OrderedDocument<commit_after>//! A BSON document represented as an associative HashMap with insertion ordering.

use std::error;
use std::fmt::{self, Debug, Display, Formatter};
use std::iter::{Extend, FromIterator, Map};
use std::marker::PhantomData;

use chrono::{DateTime, Utc};

use linked_hash_map::{self, LinkedHashMap};

use serde::de::{self, MapAccess, Visitor};

use bson::{Array, Bson, Document};
use decimal128::Decimal128;
use oid::ObjectId;
use spec::BinarySubtype;

/// Error to indicate that either a value was empty or it contained an unexpected
/// type, for use with the direct getters.
#[derive(PartialEq)]
pub enum ValueAccessError {
    /// Cannot find the expected field with the specified key
    NotPresent,
    /// Found a Bson value with the specified key, but not with the expected type
    UnexpectedType,
}

/// Result of accessing Bson value
pub type ValueAccessResult<T> = Result<T, ValueAccessError>;

impl Debug for ValueAccessError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            ValueAccessError::NotPresent => write!(f, "ValueAccessError: field is not present"),
            ValueAccessError::UnexpectedType => write!(f, "ValueAccessError: field does not have the expected type"),
        }
    }
}

impl Display for ValueAccessError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            ValueAccessError::NotPresent => write!(f, "field is not present"),
            ValueAccessError::UnexpectedType => write!(f, "field does not have the expected type"),
        }
    }
}

impl error::Error for ValueAccessError {
    fn description(&self) -> &str {
        "Error to indicate that either a value was empty or it contained an unexpected type"
    }
}

/// A BSON document represented as an associative HashMap with insertion ordering.
#[derive(Clone, PartialEq)]
pub struct OrderedDocument {
    inner: LinkedHashMap<String, Bson>,
}

impl Default for OrderedDocument {
    fn default() -> Self {
        Document::new()
    }
}

impl Display for OrderedDocument {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        fmt.write_str("{")?;

        let mut first = true;
        for (k, v) in self {
            if first {
                first = false;
                fmt.write_str(" ")?;
            } else {
                fmt.write_str(", ")?;
            }

            write!(fmt, "{}: {}", k, v)?;
        }

        write!(fmt, "{}}}", if !first { " " } else { "" })
    }
}

impl Debug for OrderedDocument {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "OrderedDocument({:?})", self.inner)
    }
}

/// An iterator over OrderedDocument entries.
pub struct OrderedDocumentIntoIterator {
    inner: LinkedHashMap<String, Bson>,
}

/// An owning iterator over OrderedDocument entries.
pub struct OrderedDocumentIterator<'a> {
    inner: linked_hash_map::Iter<'a, String, Bson>,
}

/// An iterator over an OrderedDocument's keys.
pub struct Keys<'a> {
    inner: Map<OrderedDocumentIterator<'a>, fn((&'a String, &'a Bson)) -> &'a String>,
}

/// An iterator over an OrderedDocument's values.
pub struct Values<'a> {
    inner: Map<OrderedDocumentIterator<'a>, fn((&'a String, &'a Bson)) -> &'a Bson>,
}

impl<'a> Iterator for Keys<'a> {
    type Item = &'a String;

    fn next(&mut self) -> Option<(&'a String)> {
        self.inner.next()
    }
}

impl<'a> Iterator for Values<'a> {
    type Item = &'a Bson;

    fn next(&mut self) -> Option<(&'a Bson)> {
        self.inner.next()
    }
}

impl IntoIterator for OrderedDocument {
    type Item = (String, Bson);
    type IntoIter = OrderedDocumentIntoIterator;

    fn into_iter(self) -> Self::IntoIter {
        OrderedDocumentIntoIterator { inner: self.inner }
    }
}

impl<'a> IntoIterator for &'a OrderedDocument {
    type Item = (&'a String, &'a Bson);
    type IntoIter = OrderedDocumentIterator<'a>;

    fn into_iter(self) -> Self::IntoIter {
        OrderedDocumentIterator { inner: self.inner.iter() }
    }
}

impl FromIterator<(String, Bson)> for OrderedDocument {
    fn from_iter<T: IntoIterator<Item = (String, Bson)>>(iter: T) -> Self {
        let mut doc = OrderedDocument::new();
        for (k, v) in iter {
            doc.insert(k, v);
        }
        doc
    }
}

impl<'a> Iterator for OrderedDocumentIntoIterator {
    type Item = (String, Bson);

    fn next(&mut self) -> Option<(String, Bson)> {
        self.inner.pop_front()
    }
}

impl<'a> Iterator for OrderedDocumentIterator<'a> {
    type Item = (&'a String, &'a Bson);

    fn next(&mut self) -> Option<(&'a String, &'a Bson)> {
        self.inner.next()
    }
}

impl OrderedDocument {
    /// Creates a new empty OrderedDocument.
    pub fn new() -> OrderedDocument {
        OrderedDocument { inner: LinkedHashMap::new() }
    }

    /// Gets an iterator over the entries of the map.
    pub fn iter<'a>(&'a self) -> OrderedDocumentIterator<'a> {
        self.into_iter()
    }

    /// Clears the document, removing all values.
    pub fn clear(&mut self) {
        self.inner.clear();
    }

    /// Returns a reference to the Bson corresponding to the key.
    pub fn get(&self, key: &str) -> Option<&Bson> {
        self.inner.get(key)
    }

    /// Gets a mutable reference to the Bson corresponding to the key
    pub fn get_mut(&mut self, key: &str) -> Option<&mut Bson> {
        self.inner.get_mut(key)
    }

    /// Get a floating point value for this key if it exists and has
    /// the correct type.
    pub fn get_f64(&self, key: &str) -> ValueAccessResult<f64> {
        match self.get(key) {
            Some(&Bson::FloatingPoint(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get Decimal128 value for key, if it exists.
    pub fn get_decimal128(&self, key: &str) -> ValueAccessResult<&Decimal128> {
        match self.get(key) {
            Some(&Bson::Decimal128(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a string slice this key if it exists and has the correct type.
    pub fn get_str(&self, key: &str) -> ValueAccessResult<&str> {
        match self.get(key) {
            Some(&Bson::String(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a reference to an array for this key if it exists and has
    /// the correct type.
    pub fn get_array(&self, key: &str) -> ValueAccessResult<&Array> {
        match self.get(key) {
            Some(&Bson::Array(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a reference to a document for this key if it exists and has
    /// the correct type.
    pub fn get_document(&self, key: &str) -> ValueAccessResult<&Document> {
        match self.get(key) {
            Some(&Bson::Document(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a bool value for this key if it exists and has the correct type.
    pub fn get_bool(&self, key: &str) -> ValueAccessResult<bool> {
        match self.get(key) {
            Some(&Bson::Boolean(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Returns wether this key has a null value
    pub fn is_null(&self, key: &str) -> bool {
        self.get(key) == Some(&Bson::Null)
    }

    /// Get an i32 value for this key if it exists and has the correct type.
    pub fn get_i32(&self, key: &str) -> ValueAccessResult<i32> {
        match self.get(key) {
            Some(&Bson::I32(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get an i64 value for this key if it exists and has the correct type.
    pub fn get_i64(&self, key: &str) -> ValueAccessResult<i64> {
        match self.get(key) {
            Some(&Bson::I64(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a time stamp value for this key if it exists and has the correct type.
    pub fn get_time_stamp(&self, key: &str) -> ValueAccessResult<i64> {
        match self.get(key) {
            Some(&Bson::TimeStamp(v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a generic binary value for this key if it exists and has the correct type.
    pub fn get_binary_generic(&self, key: &str) -> ValueAccessResult<&Vec<u8>> {
        match self.get(key) {
            Some(&Bson::Binary(BinarySubtype::Generic, ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get an object id value for this key if it exists and has the correct type.
    pub fn get_object_id(&self, key: &str) -> ValueAccessResult<&ObjectId> {
        match self.get(key) {
            Some(&Bson::ObjectId(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Get a UTC datetime value for this key if it exists and has the correct type.
    pub fn get_utc_datetime(&self, key: &str) -> ValueAccessResult<&DateTime<Utc>> {
        match self.get(key) {
            Some(&Bson::UtcDatetime(ref v)) => Ok(v),
            Some(_) => Err(ValueAccessError::UnexpectedType),
            None => Err(ValueAccessError::NotPresent),
        }
    }

    /// Returns true if the map contains a value for the specified key.
    pub fn contains_key(&self, key: &str) -> bool {
        self.inner.contains_key(key)
    }

    /// Gets a collection of all keys in the document.
    pub fn keys<'a>(&'a self) -> Keys<'a> {
        fn first<A, B>((a, _): (A, B)) -> A {
            a
        }
        let first: fn((&'a String, &'a Bson)) -> &'a String = first;

        Keys { inner: self.iter().map(first) }
    }

    /// Gets a collection of all values in the document.
    pub fn values<'a>(&'a self) -> Values<'a> {
        fn second<A, B>((_, b): (A, B)) -> B {
            b
        }
        let second: fn((&'a String, &'a Bson)) -> &'a Bson = second;

        Values { inner: self.iter().map(second) }
    }

    /// Returns the number of elements in the document.
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    /// Returns true if the document contains no elements
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }

    /// Sets the value of the entry with the OccupiedEntry's key,
    /// and returns the entry's old value. Accepts any type that
    /// can be converted into Bson.
    pub fn insert<KT: Into<String>, BT: Into<Bson>>(&mut self, key: KT, val: BT) -> Option<Bson> {
        self.insert_bson(key.into(), val.into())
    }

    /// Sets the value of the entry with the OccupiedEntry's key,
    /// and returns the entry's old value.
    pub fn insert_bson(&mut self, key: String, val: Bson) -> Option<Bson> {
        self.inner.insert(key, val)
    }

    /// Takes the value of the entry out of the document, and returns it.
    pub fn remove(&mut self, key: &str) -> Option<Bson> {
        self.inner.remove(key)
    }

    pub fn entry(&mut self, k: String) -> Entry {
        Entry { inner: self.inner.entry(k) }
    }
}

pub struct Entry<'a> {
    inner: linked_hash_map::Entry<'a, String, Bson>,
}

impl<'a> Entry<'a> {
    pub fn key(&self) -> &str {
        self.inner.key()
    }

    pub fn or_insert(self, default: Bson) -> &'a mut Bson {
        self.inner.or_insert(default)
    }

    pub fn or_insert_with<F: FnOnce() -> Bson>(self, default: F) -> &'a mut Bson {
        self.inner.or_insert_with(default)
    }
}

impl From<LinkedHashMap<String, Bson>> for OrderedDocument {
    fn from(tree: LinkedHashMap<String, Bson>) -> OrderedDocument {
        OrderedDocument { inner: tree }
    }
}

pub struct OrderedDocumentVisitor {
    marker: PhantomData<OrderedDocument>,
}

impl OrderedDocumentVisitor {
    pub fn new() -> OrderedDocumentVisitor {
        OrderedDocumentVisitor { marker: PhantomData }
    }
}

impl<'de> Visitor<'de> for OrderedDocumentVisitor {
    type Value = OrderedDocument;

    fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "expecting ordered document")
    }

    #[inline]
    fn visit_unit<E>(self) -> Result<OrderedDocument, E>
        where E: de::Error
    {
        Ok(OrderedDocument::new())
    }

    #[inline]
    fn visit_map<V>(self, mut visitor: V) -> Result<OrderedDocument, V::Error>
        where V: MapAccess<'de>
    {
        let mut inner = match visitor.size_hint() {
            Some(size) => LinkedHashMap::with_capacity(size),
            None => LinkedHashMap::new(),
        };

        while let Some((key, value)) = visitor.next_entry()? {
            inner.insert(key, value);
        }

        Ok(inner.into())
    }
}

impl Extend<(String, Bson)> for OrderedDocument {
    fn extend<T: IntoIterator<Item = (String, Bson)>>(&mut self, iter: T) {
        for (k, v) in iter {
            self.insert(k, v);
        }
    }
}<|endoftext|>


<commit_before>use std::option::Option;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

pub enum CellMetatype {
    tInt32
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

trait Metaformat<T> {
    fn construct(type_: CellMetatype) -> T;
}

pub struct CellFormat {
    name: String,
    type_: CellMetatype
}

pub struct Cell {
    value: CellType
}

pub impl Metaformat<Cell> for Cell {
    fn construct(type_: CellMetatype) -> Cell {
        return match type_ {
            CellMetatype::tInt32 => Cell { value: CellType::Int32(None) }
        }
    }
}

pub struct Row {
    cells: Vec<CellType>
}

pub struct Table {
    rows: Vec<Row>
}

trait ISet {
    fn size(&self) -> usize;
    fn add(&mut self, row: Row);
    fn remove(&mut self, index: usize); // FIXME
}
<commit_msg>Delete unnecessary visibility qualifier<commit_after>use std::option::Option;

type OptInt32 = Option<i32>;
type OptInt64 = Option<i64>;
type OptString = Option<String>;

pub enum CellType {
    Int32 (OptInt32),
    Int64 (OptInt64),
    Text  (OptString)
}

pub enum CellMetatype {
    tInt32
}

trait Metainf {
    fn name(&self) -> String;
}

impl Metainf for CellType {
    fn name(&self) -> String {
        return match *self {
            CellType::Int32(_) => "INT32".to_string(),
            CellType::Int64(_) => "INT64".to_string(),
            CellType::Text(_) => "TEXT".to_string()
        }
    }
}

trait Metaformat<T> {
    fn construct(type_: CellMetatype) -> T;
}

pub struct CellFormat {
    name: String,
    type_: CellMetatype
}

pub struct Cell {
    value: CellType
}

impl Metaformat<Cell> for Cell {
    fn construct(type_: CellMetatype) -> Cell {
        return match type_ {
            CellMetatype::tInt32 => Cell { value: CellType::Int32(None) }
        }
    }
}

pub struct Row {
    cells: Vec<CellType>
}

pub struct Table {
    rows: Vec<Row>
}

trait ISet {
    fn size(&self) -> usize;
    fn add(&mut self, row: Row);
    fn remove(&mut self, index: usize); // FIXME
}
<|endoftext|>


<commit_before>//! This module is strictly internal.
//!
//! These functions are used by `date()`, `time()` and `datetime()`.
//! They are currently not private, because the need to be accessible,
//! but are not useful by themselves.
//!
//! Please refer to the top-level functions instead, as they offer a better abstraction.
//!
//! **These functions may be made private later.**

use helper::*;
use nom::{self, is_digit};
use super::{Time, DateTime, Date};

macro_rules! empty_or(
    ($i:expr, $submac:ident!( $($args:tt)* )) => (
        if $i.len() == 0 {
            nom::IResult::Done($i, None)
        } else {
            match $submac!($i, $($args)*) {
                nom::IResult::Done(i,o)     => nom::IResult::Done(i, Some(o)),
                nom::IResult::Error(_)      => nom::IResult::Done($i, None),
                nom::IResult::Incomplete(i) => nom::IResult::Incomplete(i)

            }
        }
    );
);

macro_rules! check(
  ($input:expr, $submac:ident!( $($args:tt)* )) => (

    {
      let mut failed = false;
      for &idx in $input {
        if !$submac!(idx, $($args)*) {
            failed = true;
            break;
        }
      }
      if failed {
        nom::IResult::Error(nom::ErrorKind::Custom(20))
      } else {
        nom::IResult::Done(&b""[..], $input)
      }
    }
  );
  ($input:expr, $f:expr) => (
    check!($input, call!($f));
  );
);

macro_rules! char_between(
    ($input:expr, $min:expr, $max:expr) => (
        {
        fn f(c: u8) -> bool { c >= ($min as u8) && c <= ($max as u8)}
        flat_map!($input, take!(1), check!(f))
        }
    );
);

named!(take_4_digits, flat_map!(take!(4), check!(is_digit)));

// year
named!(year_prefix, alt!(tag!("+") | tag!("-")));
named!(year <i32>, chain!(
        pref: opt!(complete!(year_prefix)) ~
        year: call!(take_4_digits)
        ,
        || {
            match pref {
                Some(b"-") => -buf_to_i32(year),
                _ => buf_to_i32(year)
            }
        }));

// MM
named!(lower_month <u32>, chain!(tag!("0") ~ s:char_between!('1', '9') , || buf_to_u32(s)));
named!(upper_month <u32>, chain!(tag!("1") ~ s:char_between!('0', '2') , || 10+buf_to_u32(s)));
named!(month <u32>, alt!(lower_month | upper_month));

// DD
named!(day_zero  <u32>, chain!(tag!("0") ~ s:char_between!('1', '9') , || buf_to_u32(s)));
named!(day_one   <u32>, chain!(tag!("1") ~ s:char_between!('0', '9') , || 10+buf_to_u32(s)));
named!(day_two   <u32>, chain!(tag!("2") ~ s:char_between!('0', '9') , || 20+buf_to_u32(s)));
named!(day_three <u32>, chain!(tag!("3") ~ s:char_between!('0', '1') , || 30+buf_to_u32(s)));
named!(day <u32>, alt!(day_zero | day_one | day_two | day_three));

// WW
// reusing day_N parsers, sorry
named!(week_three <u32>, chain!(tag!("3") ~ s:char_between!('0', '9') , || 30+buf_to_u32(s)));
named!(week_four  <u32>, chain!(tag!("4") ~ s:char_between!('0', '9') , || 40+buf_to_u32(s)));
named!(week_five  <u32>, chain!(tag!("5") ~ s:char_between!('0', '3') , || 50+buf_to_u32(s)));

named!(week <u32>, alt!(day_zero | day_one | day_two | week_three| week_four | week_five ));
named!(week_day <u32>, chain!(s:char_between!('1', '7') , || buf_to_u32(s)));

// ordinal DDD
named!(ord_day <u32>, chain!(
        a:char_between!('0','3') ~
        b:char_between!('0','9') ~
        c:char_between!('0','9')
        ,
        || { buf_to_u32(a)*100 + buf_to_u32(b)*10 + buf_to_u32(c) }
        ));

// YYYY-MM-DD
named!(pub ymd_date <Date>, chain!(
        y: year ~
        opt!(complete!(tag!("-"))) ~
        m: month ~
        opt!(complete!(tag!("-"))) ~
        d: day
        ,
        || { Date::YMD{ year: y, month: m, day: d } }
        ));

// YYYY-MM-DD
named!(pub ordinal_date <Date>, chain!(
        y: year ~
        opt!(complete!(tag!("-"))) ~
        d: ord_day
        ,
        || { Date::Ordinal{ year: y, ddd: d } }
        ));

// YYYY-"W"WW-D
named!(pub iso_week_date <Date>, chain!(
        y: year ~
        opt!(complete!(tag!("-"))) ~
        tag!("W") ~
        w: week ~
        opt!(complete!(tag!("-"))) ~
        d: week_day
        ,
        || { Date::Week{ year: y, ww: w, d: d } }
        ));

named!(pub parse_date <Date>, alt!( ymd_date | iso_week_date | ordinal_date ) );

// TIME

// HH
named!(lower_hour <u32>, chain!(f:char_between!('0','1') ~ s:char_between!('0','9') ,
                                       || { buf_to_u32(f)*10 + buf_to_u32(s) } ));
named!(upper_hour <u32>, chain!(tag!("2") ~ s:char_between!('0','4') , || 20+buf_to_u32(s)));
named!(hour <u32>, alt!(lower_hour | upper_hour));

// MM
named!(below_sixty <u32>, chain!(f:char_between!('0','5') ~ s:char_between!('0','9'), || { buf_to_u32(f)*10 + buf_to_u32(s) } ));
named!(upto_sixty <u32>, alt!(below_sixty | map!(tag!("60"), |_| 60)));

named!(minute <u32>, call!(below_sixty));
named!(second <u32>, call!(upto_sixty));
named!(millisecond <u32>, map!( is_a!("0123456789"), |ms| buf_to_u32(ms) ) );

// HH:MM:[SS][.(m*)][(Z|+...|-...)]
named!(pub parse_time <Time>, chain!(
        h: hour ~
        opt!(complete!(tag!(":"))) ~
        m: minute ~
        s:  opt!(complete!( chain!( opt!(tag!(":")) ~ s:second, || s))) ~
        ms: opt!(complete!( chain!( tag!(".") ~ ms:millisecond, || ms))) ~
        z:  opt!(complete!( alt!( timezone_hour | timezone_utc) )) ,
        || {
            Time {
                hour: h,
                minute: m,
                second: s.unwrap_or(0),
                millisecond: ms.unwrap_or(0),
                tz_offset_hours: z.unwrap_or((0,0)).0,
                tz_offset_minutes: z.unwrap_or((0,0)).1
            }
        }
        ));

named!(sign <i32>, alt!(
        tag!("-") => { |_| -1 } |
        tag!("+") => { |_| 1 }
        )
    );

named!(timezone_hour <(i32,i32)>, chain!(
        s: sign ~
        h: hour ~
        m: empty_or!(
            chain!(
                tag!(":")? ~ m: minute , || { m }
            ))
        ,
        || { (s * (h as i32) , s * (m.unwrap_or(0) as i32)) }
        ));

named!(timezone_utc <(i32,i32)>, map!(tag!("Z"), |_| (0,0)));

// Full ISO8601
named!(pub parse_datetime <DateTime>, chain!(
        d: parse_date ~
        tag!("T") ~
        t: parse_time
        ,
        || {
            DateTime{
                date: d,
                time: t,
            }
        }
        ));

#[cfg(test)]
mod tests{

    use super::{year, month, day};
    use super::{hour, minute, second};
    use nom::IResult::*;

    #[test]
    fn test_year() {
        assert_eq!(Done(&[][..],   2015), year(b"2015"));
        assert_eq!(Done(&[][..],  -0333), year(b"-0333"));
        assert_eq!(Done(&b"-"[..], 2015), year(b"2015-"));
        assert!(year(b"abcd").is_err());
        assert!(year(b"2a03").is_err());
    }

    #[test]
    fn test_month() {
        assert_eq!(Done(&[][..], 1),    month(b"01"));
        assert_eq!(Done(&[][..], 6),    month(b"06"));
        assert_eq!(Done(&[][..], 12),   month(b"12"));
        assert_eq!(Done(&b"-"[..], 12), month(b"12-"));

        assert!(month(b"13").is_err());
        assert!(month(b"00").is_err());
    }

    #[test]
    fn test_day() {
        assert_eq!(Done(&[][..], 1),    day(b"01"));
        assert_eq!(Done(&[][..], 12),   day(b"12"));
        assert_eq!(Done(&[][..], 20),   day(b"20"));
        assert_eq!(Done(&[][..], 28),   day(b"28"));
        assert_eq!(Done(&[][..], 30),   day(b"30"));
        assert_eq!(Done(&[][..], 31),   day(b"31"));
        assert_eq!(Done(&b"-"[..], 31), day(b"31-"));

        assert!(day(b"00").is_err());
        assert!(day(b"32").is_err());
    }

    #[test]
    fn test_hour() {
        assert_eq!(Done(&[][..], 0),  hour(b"00"));
        assert_eq!(Done(&[][..], 1),  hour(b"01"));
        assert_eq!(Done(&[][..], 6),  hour(b"06"));
        assert_eq!(Done(&[][..], 12), hour(b"12"));
        assert_eq!(Done(&[][..], 13), hour(b"13"));
        assert_eq!(Done(&[][..], 20), hour(b"20"));
        assert_eq!(Done(&[][..], 24), hour(b"24"));

        assert!(hour(b"25").is_err());
        assert!(hour(b"30").is_err());
        assert!(hour(b"ab").is_err());
    }

    #[test]
    fn test_minute() {
        assert_eq!(Done(&[][..], 0),  minute(b"00"));
        assert_eq!(Done(&[][..], 1),  minute(b"01"));
        assert_eq!(Done(&[][..], 30), minute(b"30"));
        assert_eq!(Done(&[][..], 59), minute(b"59"));

        assert!(minute(b"60").is_err());
        assert!(minute(b"61").is_err());
        assert!(minute(b"ab").is_err());
    }

    #[test]
    fn test_second() {
        assert_eq!(Done(&[][..], 0),  second(b"00"));
        assert_eq!(Done(&[][..], 1),  second(b"01"));
        assert_eq!(Done(&[][..], 30), second(b"30"));
        assert_eq!(Done(&[][..], 59), second(b"59"));
        assert_eq!(Done(&[][..], 60), second(b"60"));

        assert!(second(b"61").is_err());
        assert!(second(b"ab").is_err());
    }

}
<commit_msg>refactor: Switch to do_parse macro<commit_after>//! This module is strictly internal.
//!
//! These functions are used by `date()`, `time()` and `datetime()`.
//! They are currently not private, because the need to be accessible,
//! but are not useful by themselves.
//!
//! Please refer to the top-level functions instead, as they offer a better abstraction.
//!
//! **These functions may be made private later.**

use helper::*;
use nom::{self, is_digit};
use super::{Time, DateTime, Date};

macro_rules! empty_or(
    ($i:expr, $submac:ident!( $($args:tt)* )) => (
        if $i.len() == 0 {
            nom::IResult::Done($i, None)
        } else {
            match $submac!($i, $($args)*) {
                nom::IResult::Done(i,o)     => nom::IResult::Done(i, Some(o)),
                nom::IResult::Error(_)      => nom::IResult::Done($i, None),
                nom::IResult::Incomplete(i) => nom::IResult::Incomplete(i)

            }
        }
    );
);

macro_rules! check(
  ($input:expr, $submac:ident!( $($args:tt)* )) => (

    {
      let mut failed = false;
      for &idx in $input {
        if !$submac!(idx, $($args)*) {
            failed = true;
            break;
        }
      }
      if failed {
        nom::IResult::Error(nom::ErrorKind::Custom(20))
      } else {
        nom::IResult::Done(&b""[..], $input)
      }
    }
  );
  ($input:expr, $f:expr) => (
    check!($input, call!($f));
  );
);

macro_rules! char_between(
    ($input:expr, $min:expr, $max:expr) => (
        {
        fn f(c: u8) -> bool { c >= ($min as u8) && c <= ($max as u8)}
        flat_map!($input, take!(1), check!(f))
        }
    );
);

named!(take_4_digits, flat_map!(take!(4), check!(is_digit)));

// year
named!(year_prefix, alt!(tag!("+") | tag!("-")));
named!(year <i32>, do_parse!(
        pref: opt!(complete!(year_prefix)) >>
        year: call!(take_4_digits) >>
        (
            match pref {
                Some(b"-") => -buf_to_i32(year),
                _ => buf_to_i32(year)
            }
        )));

// MM
named!(lower_month <u32>, do_parse!(tag!("0") >> s:char_between!('1', '9') >> (buf_to_u32(s))));
named!(upper_month <u32>, do_parse!(tag!("1") >> s:char_between!('0', '2') >> (10+buf_to_u32(s))));
named!(month <u32>, alt!(lower_month | upper_month));

// DD
named!(day_zero  <u32>, do_parse!(tag!("0") >> s:char_between!('1', '9') >> (buf_to_u32(s))));
named!(day_one   <u32>, do_parse!(tag!("1") >> s:char_between!('0', '9') >> (10+buf_to_u32(s))));
named!(day_two   <u32>, do_parse!(tag!("2") >> s:char_between!('0', '9') >> (20+buf_to_u32(s))));
named!(day_three <u32>, do_parse!(tag!("3") >> s:char_between!('0', '1') >> (30+buf_to_u32(s))));
named!(day <u32>, alt!(day_zero | day_one | day_two | day_three));

// WW
// reusing day_N parsers, sorry
named!(week_three <u32>, do_parse!(tag!("3") >> s:char_between!('0', '9') >> (30+buf_to_u32(s))));
named!(week_four  <u32>, do_parse!(tag!("4") >> s:char_between!('0', '9') >> (40+buf_to_u32(s))));
named!(week_five  <u32>, do_parse!(tag!("5") >> s:char_between!('0', '3') >> (50+buf_to_u32(s))));

named!(week <u32>, alt!(day_zero | day_one | day_two | week_three| week_four | week_five ));
named!(week_day <u32>, map!(char_between!('1', '7') , |s| buf_to_u32(s)));

// ordinal DDD
named!(ord_day <u32>, do_parse!(
        a:char_between!('0','3') >>
        b:char_between!('0','9') >>
        c:char_between!('0','9') >>
        ( buf_to_u32(a)*100 + buf_to_u32(b)*10 + buf_to_u32(c) )
        ));

// YYYY-MM-DD
named!(pub ymd_date <Date>, do_parse!(
        y: year >>
        opt!(complete!(tag!("-"))) >>
        m: month >>
        opt!(complete!(tag!("-"))) >>
        d: day >>
        ( Date::YMD{ year: y, month: m, day: d } )
        ));

// YYYY-MM-DD
named!(pub ordinal_date <Date>, do_parse!(
        y: year >>
        opt!(complete!(tag!("-"))) >>
        d: ord_day >>
        ( Date::Ordinal{ year: y, ddd: d } )
        ));

// YYYY-"W"WW-D
named!(pub iso_week_date <Date>, do_parse!(
        y: year >>
        opt!(complete!(tag!("-"))) >>
        tag!("W") >>
        w: week >>
        opt!(complete!(tag!("-"))) >>
        d: week_day >>
        ( Date::Week{ year: y, ww: w, d: d } )
        ));

named!(pub parse_date <Date>, alt!( ymd_date | iso_week_date | ordinal_date ) );

// TIME

// HH
named!(lower_hour <u32>, do_parse!(f:char_between!('0','1') >>
                                   s:char_between!('0','9') >>
                                   ( buf_to_u32(f)*10 + buf_to_u32(s) )));
named!(upper_hour <u32>, do_parse!(tag!("2") >>
                                   s:char_between!('0','4') >>
                                   (20+buf_to_u32(s))));
named!(hour <u32>, alt!(lower_hour | upper_hour));

// MM
named!(below_sixty <u32>, do_parse!(f:char_between!('0','5') >>
                                    s:char_between!('0','9') >>
                                    ( buf_to_u32(f)*10 + buf_to_u32(s) ) ));
named!(upto_sixty <u32>, alt!(below_sixty | map!(tag!("60"), |_| 60)));

named!(minute <u32>, call!(below_sixty));
named!(second <u32>, call!(upto_sixty));
named!(millisecond <u32>, map!( is_a!("0123456789"), |ms| buf_to_u32(ms) ) );

// HH:MM:[SS][.(m*)][(Z|+...|-...)]
named!(pub parse_time <Time>, do_parse!(
        h: hour >>
        opt!(complete!(tag!(":"))) >>
        m: minute >>
        s:  opt!(complete!( do_parse!( opt!(tag!(":")) >> s:second >> (s)))) >>
        ms: opt!(complete!( do_parse!( tag!(".") >> ms:millisecond >> (ms)))) >>
        z:  opt!(complete!( alt!( timezone_hour | timezone_utc) )) >>
        (
            Time {
                hour: h,
                minute: m,
                second: s.unwrap_or(0),
                millisecond: ms.unwrap_or(0),
                tz_offset_hours: z.unwrap_or((0,0)).0,
                tz_offset_minutes: z.unwrap_or((0,0)).1
            }
        )
        ));

named!(sign <i32>, alt!(
        tag!("-") => { |_| -1 } |
        tag!("+") => { |_| 1 }
        )
    );

named!(timezone_hour <(i32,i32)>, do_parse!(
        s: sign >>
        h: hour >>
        m: empty_or!(
            do_parse!(opt!(tag!(":")) >> m: minute >> ( m ))
           ) >>
        ( (s * (h as i32) , s * (m.unwrap_or(0) as i32)) )
        ));

named!(timezone_utc <(i32,i32)>, map!(tag!("Z"), |_| (0,0)));

// Full ISO8601
named!(pub parse_datetime <DateTime>, do_parse!(
        d: parse_date >>
        tag!("T") >>
        t: parse_time >>
        (
            DateTime{
                date: d,
                time: t,
            }
        )
        ));

#[cfg(test)]
mod tests{

    use super::{year, month, day};
    use super::{hour, minute, second};
    use nom::IResult::*;

    #[test]
    fn test_year() {
        assert_eq!(Done(&[][..],   2015), year(b"2015"));
        assert_eq!(Done(&[][..],  -0333), year(b"-0333"));
        assert_eq!(Done(&b"-"[..], 2015), year(b"2015-"));
        assert!(year(b"abcd").is_err());
        assert!(year(b"2a03").is_err());
    }

    #[test]
    fn test_month() {
        assert_eq!(Done(&[][..], 1),    month(b"01"));
        assert_eq!(Done(&[][..], 6),    month(b"06"));
        assert_eq!(Done(&[][..], 12),   month(b"12"));
        assert_eq!(Done(&b"-"[..], 12), month(b"12-"));

        assert!(month(b"13").is_err());
        assert!(month(b"00").is_err());
    }

    #[test]
    fn test_day() {
        assert_eq!(Done(&[][..], 1),    day(b"01"));
        assert_eq!(Done(&[][..], 12),   day(b"12"));
        assert_eq!(Done(&[][..], 20),   day(b"20"));
        assert_eq!(Done(&[][..], 28),   day(b"28"));
        assert_eq!(Done(&[][..], 30),   day(b"30"));
        assert_eq!(Done(&[][..], 31),   day(b"31"));
        assert_eq!(Done(&b"-"[..], 31), day(b"31-"));

        assert!(day(b"00").is_err());
        assert!(day(b"32").is_err());
    }

    #[test]
    fn test_hour() {
        assert_eq!(Done(&[][..], 0),  hour(b"00"));
        assert_eq!(Done(&[][..], 1),  hour(b"01"));
        assert_eq!(Done(&[][..], 6),  hour(b"06"));
        assert_eq!(Done(&[][..], 12), hour(b"12"));
        assert_eq!(Done(&[][..], 13), hour(b"13"));
        assert_eq!(Done(&[][..], 20), hour(b"20"));
        assert_eq!(Done(&[][..], 24), hour(b"24"));

        assert!(hour(b"25").is_err());
        assert!(hour(b"30").is_err());
        assert!(hour(b"ab").is_err());
    }

    #[test]
    fn test_minute() {
        assert_eq!(Done(&[][..], 0),  minute(b"00"));
        assert_eq!(Done(&[][..], 1),  minute(b"01"));
        assert_eq!(Done(&[][..], 30), minute(b"30"));
        assert_eq!(Done(&[][..], 59), minute(b"59"));

        assert!(minute(b"60").is_err());
        assert!(minute(b"61").is_err());
        assert!(minute(b"ab").is_err());
    }

    #[test]
    fn test_second() {
        assert_eq!(Done(&[][..], 0),  second(b"00"));
        assert_eq!(Done(&[][..], 1),  second(b"01"));
        assert_eq!(Done(&[][..], 30), second(b"30"));
        assert_eq!(Done(&[][..], 59), second(b"59"));
        assert_eq!(Done(&[][..], 60), second(b"60"));

        assert!(second(b"61").is_err());
        assert!(second(b"ab").is_err());
    }

}
<|endoftext|>


<commit_before>#![macro_escape]

pub trait StrParseExt {
    fn end_of_start_rest(&self, is_first: |char| -> bool, is_rest: |char| -> bool) -> Option<uint>;
    fn end_of_literal(&self, expected: &str) -> Option<uint>;
}

impl<'a> StrParseExt for &'a str {
    fn end_of_start_rest(&self,
                         is_first: |char| -> bool,
                         is_rest: |char| -> bool)
                         -> Option<uint>
    {
        let mut positions = self.char_indices();

        match positions.next() {
            Some((_, c)) if is_first(c) => (),
            Some((_, _)) => return None,
            None => return None,
        };

        let mut positions = positions.skip_while(|&(_, c)| is_rest(c));
        match positions.next() {
            Some((offset, _)) => Some(offset),
            None => Some(self.len()),
        }
    }

    fn end_of_literal(&self, expected: &str) -> Option<uint> {
        if self.starts_with(expected) {
            Some(expected.len())
        } else {
            None
        }
    }
}

pub struct BestFailure<'a, E> {
    pub failure: Option<Progress<'a, E>>
}

impl<'a, E> BestFailure<'a, E> {
    pub fn new() -> BestFailure<'a, E> {
        BestFailure {
            failure: None,
        }
    }

    pub fn with(failure: Progress<'a, E>) -> BestFailure<'a, E> {
        BestFailure {
            failure: Some(failure),
        }
    }

    pub fn push(&mut self, failure: Progress<'a, E>) {
        if let Some(ref old) = self.failure {
            if failure.point.offset <= old.point.offset {
                return;
            }
        }

        self.failure = Some(failure)
    }

    pub fn pop(self) -> Progress<'a, E> {
        self.failure.expect("No errors found")
    }
}

#[deriving(Show,Clone,PartialEq,Copy)]
pub struct Point<'a> {
    pub offset: uint,
    pub s: &'a str,
}

impl<'a> Point<'a> {
    pub fn to(&self, other: Point<'a>) -> &'a str {
        let len = other.offset - self.offset;
        self.s.slice_to(len)
    }

    pub fn slice_at(&self, position: uint) -> Progress<'a, &'a str> {
        Progress {
            data: self.s.slice_to(position),
            point: Point { offset: self.offset + position,
                           s: self.s.slice_from(position) }
        }
    }

    pub fn consume_to<E>(&self, l: Option<uint>) -> Result<'a, &'a str, E> {
        match l {
            None => Result::Failure(Progress{point: self.clone(), data: None}),
            Some(position) => Result::Success(self.slice_at(position)),
        }
    }

    pub fn consume_literal<E>(&self, literal: &str) -> Result<'a, &'a str, E> {
        self.consume_to(self.s.end_of_literal(literal))
    }

    pub fn consume_identifier<T, E>(&self, identifiers: &[Identifier<T>]) -> Result<'a, T, E>
        where T: Clone
    {
        for &(id_str, ref id_data) in identifiers.iter() {
            let result = self.consume_literal(id_str);
            if let Result::Success(..) = result {
                return result.map(|_| id_data.clone());
            }
        }

        Result::Failure(Progress {point: *self, data: None})
    }
}

pub type Identifier<'a, T> = (&'a str, T);

pub struct Progress<'a, T> {
    pub point: Point<'a>,
    pub data: T,
}

impl<'a, T> Progress<'a, T> {
    pub fn to_tuple(self) -> (T, Point<'a>) {
        (self.data, self.point)
    }

    pub fn map<F, B>(self, f: F) -> Progress<'a, B>
        where F: FnOnce(T) -> B
    {
        Progress { data: f(self.data), point: self.point }
    }
}

pub enum Result<'a, T, E> {
    Success(Progress<'a, T>),
    Partial{success: Progress<'a, T>, failure: Progress<'a, Option<E>>},
    Failure(Progress<'a, Option<E>>),
}

impl<'a, T, E> Result<'a, T, E> {
    pub fn success(data: T, point: Point<'a>) -> Result<'a, T, E> {
        Result::Success(Progress { data: data, point: point })
    }

    // Pattern: zero-or-one
    pub fn optional(self, point: Point<'a>) -> (Option<T>, Point<'a>) {
        match self {
            Result::Success(progress) |
            Result::Partial{ success: progress, .. } =>
                (Some(progress.data), progress.point),
            Result::Failure(_) =>
                (None, point),
        }
    }

    // Pattern: alternate
    pub fn or_else(self, f: || -> Result<'a, T, E>) -> Result<'a, T, E> {
        match self {
            Result::Success(..) => self,
            Result::Partial{ failure: fail, .. } |
            Result::Failure(fail) => {
                let next = f();
                match next {
                    Result::Success(..) => next,
                    Result::Partial{ failure: next_fail, .. } |
                    Result::Failure(next_fail) => {
                        let mut bf = BestFailure::with(fail);
                        bf.push(next_fail);
                        Result::Failure(bf.pop())
                    }
                }
            },
        }
    }

    pub fn map<F, B>(self, f: F) -> Result<'a, B, E>
        where F: FnOnce(T) -> B
    {
        match self {
            Result::Success(prog) =>
                Result::Success(prog.map(f)),
            Result::Partial{success: s, failure: ff} => {
                Result::Partial{ success: s.map(f), failure: ff}
            },
            Result::Failure(pf) =>
                Result::Failure(pf),
        }
    }

    pub fn set_error(self, error: E) -> Result<'a, T, E> {
        match self {
            Result::Success(..) =>
                self,
            Result::Partial{ success: s, failure: f } =>
                Result::Partial{ success: s, failure: f.map(move |_| Some(error)) },
            Result::Failure(f) =>
                Result::Failure(f.map(move |_| Some(error))),
        }
    }
}

#[macro_export]
macro_rules! try_parse(
    ($e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) =>
                return ::document::peresil::Result::Failure(pf),
        }
    });
    ($e:expr, $err:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) => {
                let fail = ::document::peresil::Progress{ data: Some($err), ..pf };
                return ::document::peresil::Result::Failure(fail);
            },
        }
    });
);

#[macro_export]
macro_rules! try_partial_parse(
    ($e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                (progress.data, ::document::peresil::BestFailure::new(), progress.point),
            ::document::peresil::Result::Partial{ success: s, failure: pf } =>
                (s.data, ::document::peresil::BestFailure::with(pf), s.point),
            ::document::peresil::Result::Failure(pf) =>
                return ::document::peresil::Result::Failure(pf),
        }
    })
);

#[macro_export]
macro_rules! try_resume_after_partial_failure(
    ($partial:expr, $e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) => {
                let mut partial = $partial;
                partial.push(pf);
                return ::document::peresil::Result::Failure(partial.pop())
            },
        }
    });
);

// Pattern: zero-or-many
pub fn zero_or_more<'a, T, E, P>(point: Point<'a>, parser: P) -> Result<'a, Vec<T>, E>
    where P: FnMut(Point<'a>) -> Result<'a, T, E>
{
    let mut err;
    let mut data = Vec::new();
    let mut point = point;
    let mut parser = parser;

    loop {
        let (d, next_start) = match parser(point) {
            Result::Success(progress) =>
                progress.to_tuple(),
            Result::Partial{ failure: pf, .. } |
            Result::Failure(pf) => {
                err = Some(pf);
                break
            }
        };

        data.push(d);
        point = next_start;
    }

    Result::Partial {
        success: Progress { data: data, point: point },
        failure: err.unwrap()
    }
}
<commit_msg>Add a constructor for failed parses<commit_after>#![macro_escape]

pub trait StrParseExt {
    fn end_of_start_rest(&self, is_first: |char| -> bool, is_rest: |char| -> bool) -> Option<uint>;
    fn end_of_literal(&self, expected: &str) -> Option<uint>;
}

impl<'a> StrParseExt for &'a str {
    fn end_of_start_rest(&self,
                         is_first: |char| -> bool,
                         is_rest: |char| -> bool)
                         -> Option<uint>
    {
        let mut positions = self.char_indices();

        match positions.next() {
            Some((_, c)) if is_first(c) => (),
            Some((_, _)) => return None,
            None => return None,
        };

        let mut positions = positions.skip_while(|&(_, c)| is_rest(c));
        match positions.next() {
            Some((offset, _)) => Some(offset),
            None => Some(self.len()),
        }
    }

    fn end_of_literal(&self, expected: &str) -> Option<uint> {
        if self.starts_with(expected) {
            Some(expected.len())
        } else {
            None
        }
    }
}

pub struct BestFailure<'a, E> {
    pub failure: Option<Progress<'a, E>>
}

impl<'a, E> BestFailure<'a, E> {
    pub fn new() -> BestFailure<'a, E> {
        BestFailure {
            failure: None,
        }
    }

    pub fn with(failure: Progress<'a, E>) -> BestFailure<'a, E> {
        BestFailure {
            failure: Some(failure),
        }
    }

    pub fn push(&mut self, failure: Progress<'a, E>) {
        if let Some(ref old) = self.failure {
            if failure.point.offset <= old.point.offset {
                return;
            }
        }

        self.failure = Some(failure)
    }

    pub fn pop(self) -> Progress<'a, E> {
        self.failure.expect("No errors found")
    }
}

#[deriving(Show,Clone,PartialEq,Copy)]
pub struct Point<'a> {
    pub offset: uint,
    pub s: &'a str,
}

impl<'a> Point<'a> {
    pub fn to(&self, other: Point<'a>) -> &'a str {
        let len = other.offset - self.offset;
        self.s.slice_to(len)
    }

    pub fn slice_at(&self, position: uint) -> Progress<'a, &'a str> {
        Progress {
            data: self.s.slice_to(position),
            point: Point { offset: self.offset + position,
                           s: self.s.slice_from(position) }
        }
    }

    pub fn consume_to<E>(&self, l: Option<uint>) -> Result<'a, &'a str, E> {
        match l {
            None => Result::Failure(Progress{point: self.clone(), data: None}),
            Some(position) => Result::Success(self.slice_at(position)),
        }
    }

    pub fn consume_literal<E>(&self, literal: &str) -> Result<'a, &'a str, E> {
        self.consume_to(self.s.end_of_literal(literal))
    }

    pub fn consume_identifier<T, E>(&self, identifiers: &[Identifier<T>]) -> Result<'a, T, E>
        where T: Clone
    {
        for &(id_str, ref id_data) in identifiers.iter() {
            let result = self.consume_literal(id_str);
            if let Result::Success(..) = result {
                return result.map(|_| id_data.clone());
            }
        }

        Result::Failure(Progress {point: *self, data: None})
    }
}

pub type Identifier<'a, T> = (&'a str, T);

pub struct Progress<'a, T> {
    pub point: Point<'a>,
    pub data: T,
}

impl<'a, T> Progress<'a, T> {
    pub fn to_tuple(self) -> (T, Point<'a>) {
        (self.data, self.point)
    }

    pub fn map<F, B>(self, f: F) -> Progress<'a, B>
        where F: FnOnce(T) -> B
    {
        Progress { data: f(self.data), point: self.point }
    }
}

pub enum Result<'a, T, E> {
    Success(Progress<'a, T>),
    Partial{success: Progress<'a, T>, failure: Progress<'a, Option<E>>},
    Failure(Progress<'a, Option<E>>),
}

impl<'a, T, E> Result<'a, T, E> {
    pub fn success(data: T, point: Point<'a>) -> Result<'a, T, E> {
        Result::Success(Progress { data: data, point: point })
    }

    pub fn failure(data: Option<E>, point: Point<'a>) -> Result<'a, T, E> {
        Result::Failure(Progress { data: data, point: point })
    }

    // Pattern: zero-or-one
    pub fn optional(self, point: Point<'a>) -> (Option<T>, Point<'a>) {
        match self {
            Result::Success(progress) |
            Result::Partial{ success: progress, .. } =>
                (Some(progress.data), progress.point),
            Result::Failure(_) =>
                (None, point),
        }
    }

    // Pattern: alternate
    pub fn or_else(self, f: || -> Result<'a, T, E>) -> Result<'a, T, E> {
        match self {
            Result::Success(..) => self,
            Result::Partial{ failure: fail, .. } |
            Result::Failure(fail) => {
                let next = f();
                match next {
                    Result::Success(..) => next,
                    Result::Partial{ failure: next_fail, .. } |
                    Result::Failure(next_fail) => {
                        let mut bf = BestFailure::with(fail);
                        bf.push(next_fail);
                        Result::Failure(bf.pop())
                    }
                }
            },
        }
    }

    pub fn map<F, B>(self, f: F) -> Result<'a, B, E>
        where F: FnOnce(T) -> B
    {
        match self {
            Result::Success(prog) =>
                Result::Success(prog.map(f)),
            Result::Partial{success: s, failure: ff} => {
                Result::Partial{ success: s.map(f), failure: ff}
            },
            Result::Failure(pf) =>
                Result::Failure(pf),
        }
    }

    pub fn set_error(self, error: E) -> Result<'a, T, E> {
        match self {
            Result::Success(..) =>
                self,
            Result::Partial{ success: s, failure: f } =>
                Result::Partial{ success: s, failure: f.map(move |_| Some(error)) },
            Result::Failure(f) =>
                Result::Failure(f.map(move |_| Some(error))),
        }
    }
}

#[macro_export]
macro_rules! try_parse(
    ($e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) =>
                return ::document::peresil::Result::Failure(pf),
        }
    });
    ($e:expr, $err:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) => {
                let fail = ::document::peresil::Progress{ data: Some($err), ..pf };
                return ::document::peresil::Result::Failure(fail);
            },
        }
    });
);

#[macro_export]
macro_rules! try_partial_parse(
    ($e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                (progress.data, ::document::peresil::BestFailure::new(), progress.point),
            ::document::peresil::Result::Partial{ success: s, failure: pf } =>
                (s.data, ::document::peresil::BestFailure::with(pf), s.point),
            ::document::peresil::Result::Failure(pf) =>
                return ::document::peresil::Result::Failure(pf),
        }
    })
);

#[macro_export]
macro_rules! try_resume_after_partial_failure(
    ($partial:expr, $e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) => {
                let mut partial = $partial;
                partial.push(pf);
                return ::document::peresil::Result::Failure(partial.pop())
            },
        }
    });
);

// Pattern: zero-or-many
pub fn zero_or_more<'a, T, E, P>(point: Point<'a>, parser: P) -> Result<'a, Vec<T>, E>
    where P: FnMut(Point<'a>) -> Result<'a, T, E>
{
    let mut err;
    let mut data = Vec::new();
    let mut point = point;
    let mut parser = parser;

    loop {
        let (d, next_start) = match parser(point) {
            Result::Success(progress) =>
                progress.to_tuple(),
            Result::Partial{ failure: pf, .. } |
            Result::Failure(pf) => {
                err = Some(pf);
                break
            }
        };

        data.push(d);
        point = next_start;
    }

    Result::Partial {
        success: Progress { data: data, point: point },
        failure: err.unwrap()
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

#[cfg(gtk_3_4)]
pub use auto::traits::ActionableExt;
pub use auto::traits::BinExt;
pub use auto::traits::BoxExt;
pub use auto::traits::ButtonExt;
pub use auto::traits::CellAreaExt;
pub use auto::traits::CellEditableExt;
pub use auto::traits::CellLayoutExt;
pub use auto::traits::CellRendererExt;
pub use auto::traits::CheckButtonExt;
pub use auto::traits::ComboBoxExt;
pub use auto::traits::ContainerExt;
pub use auto::traits::DialogExt;
pub use auto::traits::EditableExt;
pub use auto::traits::EntryExt;
pub use auto::traits::FileChooserExt;
pub use auto::traits::FontChooserExt;
pub use auto::traits::FrameExt;
pub use auto::traits::MenuItemExt;
pub use auto::traits::MenuShellExt;
pub use auto::traits::MiscExt;
pub use auto::traits::OrientableExt;
#[cfg(gtk_3_12)]
pub use auto::traits::PopoverExt;
pub use auto::traits::RangeExt;
pub use auto::traits::RecentChooserExt;
pub use auto::traits::ScaleButtonExt;
pub use auto::traits::ScrollableExt;
pub use auto::traits::ScrolledWindowExt;
pub use auto::traits::ToggleButtonExt;
pub use auto::traits::ToolButtonExt;
pub use auto::traits::ToolItemExt;
pub use auto::traits::ToolShellExt;
//pub use auto::traits::TreeModelExt;
pub use auto::traits::TreeSortableExt;

pub use app_chooser::AppChooserExt;
pub use color_chooser::ColorChooserExt;
pub use tree_model::TreeModelExt;
pub use widget::WidgetExt;
pub use window::WindowExt;
<commit_msg>Add `Upcast` and `Downcast` to prelude<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

pub use glib::object::{Downcast, Upcast};

#[cfg(gtk_3_4)]
pub use auto::traits::ActionableExt;
pub use auto::traits::BinExt;
pub use auto::traits::BoxExt;
pub use auto::traits::ButtonExt;
pub use auto::traits::CellAreaExt;
pub use auto::traits::CellEditableExt;
pub use auto::traits::CellLayoutExt;
pub use auto::traits::CellRendererExt;
pub use auto::traits::CheckButtonExt;
pub use auto::traits::ComboBoxExt;
pub use auto::traits::ContainerExt;
pub use auto::traits::DialogExt;
pub use auto::traits::EditableExt;
pub use auto::traits::EntryExt;
pub use auto::traits::FileChooserExt;
pub use auto::traits::FontChooserExt;
pub use auto::traits::FrameExt;
pub use auto::traits::MenuItemExt;
pub use auto::traits::MenuShellExt;
pub use auto::traits::MiscExt;
pub use auto::traits::OrientableExt;
#[cfg(gtk_3_12)]
pub use auto::traits::PopoverExt;
pub use auto::traits::RangeExt;
pub use auto::traits::RecentChooserExt;
pub use auto::traits::ScaleButtonExt;
pub use auto::traits::ScrollableExt;
pub use auto::traits::ScrolledWindowExt;
pub use auto::traits::ToggleButtonExt;
pub use auto::traits::ToolButtonExt;
pub use auto::traits::ToolItemExt;
pub use auto::traits::ToolShellExt;
//pub use auto::traits::TreeModelExt;
pub use auto::traits::TreeSortableExt;

pub use app_chooser::AppChooserExt;
pub use color_chooser::ColorChooserExt;
pub use tree_model::TreeModelExt;
pub use widget::WidgetExt;
pub use window::WindowExt;
<|endoftext|>


<commit_before>//! Makes drawing on ncurses windows easier.

use std::cmp::min;

use ncurses;
use ncurses::chtype;

use theme::{ColorPair, Theme};
use vec::{Vec2, ToVec2};

/// Convenient interface to draw on a subset of the screen.
pub struct Printer {
    /// Offset into the window this printer should start drawing at.
    pub offset: Vec2,
    /// Size of the area we are allowed to draw on.
    pub size: Vec2,
    /// Whether the view to draw is currently focused or not.
    pub focused: bool,
    /// Currently used theme
    pub theme: Theme,
}

impl Printer {
    /// Creates a new printer on the given window.
    pub fn new<T: ToVec2>(size: T, theme: Theme) -> Self {
        Printer {
            offset: Vec2::zero(),
            size: size.to_vec2(),
            focused: true,
            theme: theme,
        }
    }

    /// Prints some text at the given position relative to the window.
    pub fn print<S: ToVec2>(&self, pos: S, text: &str) {
        let p = pos.to_vec2();
        if p.y >= self.size.y || p.x >= self.size.x {
            return;
        }
        // Do we have enough room for the entire line?
        let room = self.size.x - p.x;
        // We want the number of CHARACTERS, not bytes.
        let text = match text.char_indices().nth(room) {
            Some((i, _)) => &text[..i],
            _ => text,
        };

        let p = p + self.offset;
        if text.contains("%") {
            ncurses::mvprintw(p.y as i32, p.x as i32, &text.replace("%", "%%"));
        } else {
            ncurses::mvprintw(p.y as i32, p.x as i32, text);
        }
    }

    /// Prints a vertical line using the given character.
    pub fn print_vline<T: ToVec2>(&self, start: T, len: usize, c: chtype) {
        let p = start.to_vec2();
        if p.y > self.size.y || p.x > self.size.x {
            return;
        }
        let len = min(len, self.size.y - p.y);

        let p = p + self.offset;
        ncurses::mvvline(p.y as i32, p.x as i32, c, len as i32);
    }

    /// Prints a horizontal line using the given character.
    pub fn print_hline<T: ToVec2>(&self, start: T, len: usize, c: chtype) {
        let p = start.to_vec2();
        if p.y > self.size.y || p.x > self.size.x {
            return;
        }
        let len = min(len, self.size.x - p.x);

        let p = p + self.offset;
        ncurses::mvhline(p.y as i32, p.x as i32, c, len as i32);
    }

    /// Call the given closure with a colored printer,
    /// that will apply the given color on prints.
    ///
    /// # Examples
    ///
    /// ```
    /// # use cursive::printer::Printer;
    /// # use cursive::theme;
    /// # let printer = Printer::new((6,4), theme::load_default());
    /// printer.with_color(theme::ColorPair::Highlight, |printer| {
    ///     printer.print((0,0), "This text is highlighted!");
    /// });
    /// ```
    pub fn with_color<'a, F>(&'a self, c: ColorPair, f: F)
        where F: Fn(&Printer)
    {
        self.with_style(ncurses::COLOR_PAIR(c.ncurses_id()), f);
        ncurses::attron(ncurses::COLOR_PAIR(ColorPair::Primary.ncurses_id()));
    }

    /// Same as `with_color`, but apply a ncurses style instead,
    /// like `ncurses::A_BOLD()` or `ncurses::A_REVERSE()`.
    ///
    /// Will probably use a cursive enum some day.
    pub fn with_style<'a, F>(&'a self, style: ncurses::attr_t, f: F)
        where F: Fn(&Printer)
    {
        ncurses::attron(style);
        f(self);
        ncurses::attroff(style);
    }

    /// Prints a rectangular box.
    ///
    /// # Examples
    ///
    /// ```
    /// # use cursive::printer::Printer;
    /// # use cursive::theme;
    /// # let printer = Printer::new((6,4), theme::load_default());
    /// printer.print_box((0,0), (6,4));
    /// ```
    pub fn print_box<T: ToVec2>(&self, start: T, size: T) {
        let start_v = start.to_vec2();
        let size_v = size.to_vec2() - (1, 1);

        self.print(start_v, "┌");
        self.print(start_v + size_v.keep_x(), "┐");
        self.print(start_v + size_v.keep_y(), "└");
        self.print(start_v + size_v, "┘");

        self.print_hline(start_v + (1, 0), size_v.x - 1, ncurses::ACS_HLINE());
        self.print_vline(start_v + (0, 1), size_v.y - 1, ncurses::ACS_VLINE());
        self.print_hline(start_v + (1, 0) + size_v.keep_y(),
                         size_v.x - 1,
                         ncurses::ACS_HLINE());
        self.print_vline(start_v + (0, 1) + size_v.keep_x(),
                         size_v.y - 1,
                         ncurses::ACS_VLINE());
    }

    /// Returns a printer on a subset of this one's area.
    pub fn sub_printer<S: ToVec2>(&self, offset: S, size: S, focused: bool) -> Printer {
        let offset_v = offset.to_vec2();
        Printer {
            offset: self.offset + offset_v,
            // We can't be larger than what remains
            size: Vec2::min(self.size - offset_v, size.to_vec2()),
            focused: self.focused && focused,
            theme: self.theme.clone(),
        }
    }
}
<commit_msg>Experiment: use direct utf-8 VLINE char<commit_after>//! Makes drawing on ncurses windows easier.

use std::cmp::min;

use ncurses;
use ncurses::chtype;

use theme::{ColorPair, Theme};
use vec::{Vec2, ToVec2};

/// Convenient interface to draw on a subset of the screen.
pub struct Printer {
    /// Offset into the window this printer should start drawing at.
    pub offset: Vec2,
    /// Size of the area we are allowed to draw on.
    pub size: Vec2,
    /// Whether the view to draw is currently focused or not.
    pub focused: bool,
    /// Currently used theme
    pub theme: Theme,
}

impl Printer {
    /// Creates a new printer on the given window.
    pub fn new<T: ToVec2>(size: T, theme: Theme) -> Self {
        Printer {
            offset: Vec2::zero(),
            size: size.to_vec2(),
            focused: true,
            theme: theme,
        }
    }

    /// Prints some text at the given position relative to the window.
    pub fn print<S: ToVec2>(&self, pos: S, text: &str) {
        let p = pos.to_vec2();
        if p.y >= self.size.y || p.x >= self.size.x {
            return;
        }
        // Do we have enough room for the entire line?
        let room = self.size.x - p.x;
        // We want the number of CHARACTERS, not bytes.
        let text = match text.char_indices().nth(room) {
            Some((i, _)) => &text[..i],
            _ => text,
        };

        let p = p + self.offset;
        if text.contains("%") {
            ncurses::mvprintw(p.y as i32, p.x as i32, &text.replace("%", "%%"));
        } else {
            ncurses::mvprintw(p.y as i32, p.x as i32, text);
        }
    }

    /// Prints a vertical line using the given character.
    pub fn print_vline<T: ToVec2>(&self, start: T, len: usize, c: chtype) {
        let p = start.to_vec2();
        if p.y > self.size.y || p.x > self.size.x {
            return;
        }
        let len = min(len, self.size.y - p.y);

        let p = p + self.offset;
        for y in 0..len {
            ncurses::mvaddstr((p.y + y) as i32, p.x as i32, "│");
            // ncurses::mvaddstr(p.y as i32, p.x as i32, "┌");
        }
    }

    /// Prints a horizontal line using the given character.
    pub fn print_hline<T: ToVec2>(&self, start: T, len: usize, c: chtype) {
        let p = start.to_vec2();
        if p.y > self.size.y || p.x > self.size.x {
            return;
        }
        let len = min(len, self.size.x - p.x);

        let p = p + self.offset;
        ncurses::mvhline(p.y as i32, p.x as i32, c, len as i32);
    }

    /// Call the given closure with a colored printer,
    /// that will apply the given color on prints.
    ///
    /// # Examples
    ///
    /// ```
    /// # use cursive::printer::Printer;
    /// # use cursive::theme;
    /// # let printer = Printer::new((6,4), theme::load_default());
    /// printer.with_color(theme::ColorPair::Highlight, |printer| {
    ///     printer.print((0,0), "This text is highlighted!");
    /// });
    /// ```
    pub fn with_color<'a, F>(&'a self, c: ColorPair, f: F)
        where F: Fn(&Printer)
    {
        self.with_style(ncurses::COLOR_PAIR(c.ncurses_id()), f);
        ncurses::attron(ncurses::COLOR_PAIR(ColorPair::Primary.ncurses_id()));
    }

    /// Same as `with_color`, but apply a ncurses style instead,
    /// like `ncurses::A_BOLD()` or `ncurses::A_REVERSE()`.
    ///
    /// Will probably use a cursive enum some day.
    pub fn with_style<'a, F>(&'a self, style: ncurses::attr_t, f: F)
        where F: Fn(&Printer)
    {
        ncurses::attron(style);
        f(self);
        ncurses::attroff(style);
    }

    /// Prints a rectangular box.
    ///
    /// # Examples
    ///
    /// ```
    /// # use cursive::printer::Printer;
    /// # use cursive::theme;
    /// # let printer = Printer::new((6,4), theme::load_default());
    /// printer.print_box((0,0), (6,4));
    /// ```
    pub fn print_box<T: ToVec2>(&self, start: T, size: T) {
        let start_v = start.to_vec2();
        let size_v = size.to_vec2() - (1, 1);

        self.print(start_v, "┌");
        self.print(start_v + size_v.keep_x(), "┐");
        self.print(start_v + size_v.keep_y(), "└");
        self.print(start_v + size_v, "┘");

        self.print_hline(start_v + (1, 0), size_v.x - 1, ncurses::ACS_HLINE());
        self.print_vline(start_v + (0, 1), size_v.y - 1, ncurses::ACS_VLINE());
        self.print_hline(start_v + (1, 0) + size_v.keep_y(),
                         size_v.x - 1,
                         ncurses::ACS_HLINE());
        self.print_vline(start_v + (0, 1) + size_v.keep_x(),
                         size_v.y - 1,
                         ncurses::ACS_VLINE());
    }

    /// Returns a printer on a subset of this one's area.
    pub fn sub_printer<S: ToVec2>(&self, offset: S, size: S, focused: bool) -> Printer {
        let offset_v = offset.to_vec2();
        Printer {
            offset: self.offset + offset_v,
            // We can't be larger than what remains
            size: Vec2::min(self.size - offset_v, size.to_vec2()),
            focused: self.focused && focused,
            theme: self.theme.clone(),
        }
    }
}
<|endoftext|>