<commit_before>#[macro_use]
extern crate nom;

use nom::IResult;
use nom::IResult::*;
use nom::Err::*;
use std::fmt;

mod helper;
use helper::*;

macro_rules! errprint {
    ($($arg:tt)*) => (
        std::io::stderr().write_fmt(format_args!($($arg)*))
        );
}

macro_rules! errln {
    ($fmt:expr) => (errprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (errprint!(concat!($fmt, "\n"), $($arg)*));
}

#[allow(unused_imports)] use std::io::Write;

#[derive(Eq,PartialEq)]
struct Date {
    year: i32,
    month: u32,
    day: u32,
}

#[derive(Eq,PartialEq)]
struct Time {
    hour: u32,
    minute: u32,
    second: u32,
    tz_offset: i32,
}

#[derive(Eq,PartialEq)]
struct DateTime {
    date: Date,
    time: Time,
}

impl fmt::Debug for Date {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:0>4?}-{:0>2?}-{:0>2?}",
               self.year, self.month, self.day)
    }
}
impl fmt::Debug for Time {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:0>2?}:{:0>2?}:{:0>2?}Z{:0>4?}",
               self.hour, self.minute, self.second, self.tz_offset*100)
    }
}
impl fmt::Debug for DateTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}T{:?}", self.date, self.time)
    }
}

/// Take n bytes and ensure that they are only in the provided range of bytes
macro_rules! take_n_between(
    ($input:expr, $count:expr, $min:expr, $max:expr) => (
        {
            let new_min = $min as u8;
            let new_max = $max as u8;
            let cnt = $count as usize;
            if $input.len() < cnt {
                nom::IResult::Incomplete(nom::Needed::Size(cnt))
            } else {
                for idx in 0..$count {
                    if $input[idx] < new_min || $input[idx] > new_max {
                        return nom::IResult::Error(nom::Err::Position(42 as u32,$input));
                    }
                }

                nom::IResult::Done(&$input[$count..], &$input[0..$count])
            }
        }
        );
    );

macro_rules! char_between(
    ($input:expr, $min:expr, $max:expr) => (
        take_n_between!($input, 1, $min, $max)
    );
);

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)

            }
        }
    );
);

named!(year_prefix, alt!(tag!("+") | tag!("-")));

named!(pub year <&[u8], i32>, chain!(
        pref: opt!(year_prefix) ~
        year: take_n_between!(4, '0', '9')
        ,
        || {
            match pref {
                Some(b"-") => -buf_to_i32(year),
                _ => buf_to_i32(year)
            }
        }));

named!(lower_month <&[u8], u32>, chain!(tag!("0") ~ s:char_between!('1', '9') , || buf_to_u32(s)));
named!(upper_month <&[u8], u32>, chain!(tag!("1") ~ s:char_between!('0', '2') ,       || 10+buf_to_u32(s)));

named!(month <&[u8], u32>, alt!(lower_month | upper_month));

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

named!(day <&[u8], u32>, alt!(day_zero | day_one | day_two | day_three));

named!(date <&[u8], Date>, chain!(
        y: year ~
        tag!("-") ~
        m: month ~
        tag!("-") ~
        d: day
        ,
        || { Date{ year: y, month: m, day: d } }
        ));

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

named!(below_sixty <&[u8], u32>, chain!(f:char_between!('0','5') ~ s:char_between!('0','9') ,
                                       || { buf_to_u32(f)*10 + buf_to_u32(s) } ));

named!(minute <&[u8], u32>, call!(below_sixty));
named!(second <&[u8], u32>, call!(below_sixty));

named!(append_seconds <&[u8], u32>, chain!(tag!(":") ~ sec:second, || sec));

named!(time <&[u8], Time>, chain!(
        h: hour ~
        tag!(":") ~
        m: minute ~
        s: empty_or!(
            chain!(tag!(":") ~ s:second , || s)
            )
        ,
        || {
            Time {
                hour: h,
                minute: m,
                second: s.unwrap_or(0),
                tz_offset: 0
            }
        }
        ));

named!(timezone <&[u8], u32>, chain!(
        tag!("+") ~
        h: hour ~
        tag!(":")? ~
        m: minute
        ,
        || { h }));

named!(tz_z, tag!("Z"));
named!(timezone_utc <&[u8], u32>, map!(tz_z, |_| 0));

named!(time_with_timezone <&[u8], Time>, chain!(
        t: time ~
        s: empty_or!(alt!(timezone_utc | timezone))
        ,
        || {
            Time {
                hour: t.hour,
                minute: t.minute,
                second: t.second,
                tz_offset: s.unwrap_or(0) as i32
            }
        }
        ));

#[test]
fn parse_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 parse_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 parse_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 parse_date() {
    assert_eq!(Done(&[][..], Date{ year: 2015, month: 6, day: 26 }), date(b"2015-06-26"));
    assert_eq!(Done(&[][..], Date{ year: -333, month: 7, day: 11 }), date(b"-0333-07-11"));

    assert!(date(b"201").is_incomplete());
    assert!(date(b"2015p00p00").is_err());
    assert!(date(b"pppp").is_err());
}

#[test]
fn parse_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 parse_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 parse_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!(second(b"60").is_err());
    assert!(second(b"61").is_err());
    assert!(second(b"ab").is_err());
}

#[test]
fn parse_time() {
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 0}), time(b"16:43:16"));
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second:  0, tz_offset: 0}), time(b"16:43"));

    assert!(time(b"20:").is_incomplete());
    assert!(time(b"20p42p16").is_err());
    assert!(time(b"pppp").is_err());
}

#[test]
fn parse_time_with_timezone() {
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 0}),
               time_with_timezone(b"16:43:16"));
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 0}),
               time_with_timezone(b"16:43:16Z"));
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 0}),
               time_with_timezone(b"16:43:16+00:00"));
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 5}),
               time_with_timezone(b"16:43:16+05:00"));

    assert!(time_with_timezone(b"20:").is_incomplete());
    assert!(time_with_timezone(b"20p42p16").is_err());
    assert!(time_with_timezone(b"pppp").is_err());

    assert!(time_with_timezone(b"16:43:16+").is_err());
    assert!(time_with_timezone(b"16:43:16+0").is_err());
    assert!(time_with_timezone(b"16:43:16+05:").is_err());
}
<commit_msg>Minute is optional (and unused for now)<commit_after>#[macro_use]
extern crate nom;

use nom::IResult;
use nom::IResult::*;
use nom::Err::*;
use std::fmt;

mod helper;
use helper::*;

macro_rules! errprint {
    ($($arg:tt)*) => (
        std::io::stderr().write_fmt(format_args!($($arg)*))
        );
}

macro_rules! errln {
    ($fmt:expr) => (errprint!(concat!($fmt, "\n")));
    ($fmt:expr, $($arg:tt)*) => (errprint!(concat!($fmt, "\n"), $($arg)*));
}

#[allow(unused_imports)] use std::io::Write;

#[derive(Eq,PartialEq)]
struct Date {
    year: i32,
    month: u32,
    day: u32,
}

#[derive(Eq,PartialEq)]
struct Time {
    hour: u32,
    minute: u32,
    second: u32,
    tz_offset: i32,
}

#[derive(Eq,PartialEq)]
struct DateTime {
    date: Date,
    time: Time,
}

impl fmt::Debug for Date {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:0>4?}-{:0>2?}-{:0>2?}",
               self.year, self.month, self.day)
    }
}
impl fmt::Debug for Time {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:0>2?}:{:0>2?}:{:0>2?}Z{:0>4?}",
               self.hour, self.minute, self.second, self.tz_offset*100)
    }
}
impl fmt::Debug for DateTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}T{:?}", self.date, self.time)
    }
}

/// Take n bytes and ensure that they are only in the provided range of bytes
macro_rules! take_n_between(
    ($input:expr, $count:expr, $min:expr, $max:expr) => (
        {
            let new_min = $min as u8;
            let new_max = $max as u8;
            let cnt = $count as usize;
            if $input.len() < cnt {
                nom::IResult::Incomplete(nom::Needed::Size(cnt))
            } else {
                for idx in 0..$count {
                    if $input[idx] < new_min || $input[idx] > new_max {
                        return nom::IResult::Error(nom::Err::Position(42 as u32,$input));
                    }
                }

                nom::IResult::Done(&$input[$count..], &$input[0..$count])
            }
        }
        );
    );

macro_rules! char_between(
    ($input:expr, $min:expr, $max:expr) => (
        take_n_between!($input, 1, $min, $max)
    );
);

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)

            }
        }
    );
);

named!(year_prefix, alt!(tag!("+") | tag!("-")));

named!(pub year <&[u8], i32>, chain!(
        pref: opt!(year_prefix) ~
        year: take_n_between!(4, '0', '9')
        ,
        || {
            match pref {
                Some(b"-") => -buf_to_i32(year),
                _ => buf_to_i32(year)
            }
        }));

named!(lower_month <&[u8], u32>, chain!(tag!("0") ~ s:char_between!('1', '9') , || buf_to_u32(s)));
named!(upper_month <&[u8], u32>, chain!(tag!("1") ~ s:char_between!('0', '2') ,       || 10+buf_to_u32(s)));

named!(month <&[u8], u32>, alt!(lower_month | upper_month));

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

named!(day <&[u8], u32>, alt!(day_zero | day_one | day_two | day_three));

named!(date <&[u8], Date>, chain!(
        y: year ~
        tag!("-") ~
        m: month ~
        tag!("-") ~
        d: day
        ,
        || { Date{ year: y, month: m, day: d } }
        ));

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

named!(below_sixty <&[u8], u32>, chain!(f:char_between!('0','5') ~ s:char_between!('0','9') ,
                                       || { buf_to_u32(f)*10 + buf_to_u32(s) } ));

named!(minute <&[u8], u32>, call!(below_sixty));
named!(second <&[u8], u32>, call!(below_sixty));

named!(append_seconds <&[u8], u32>, chain!(tag!(":") ~ sec:second, || sec));

named!(time <&[u8], Time>, chain!(
        h: hour ~
        tag!(":") ~
        m: minute ~
        s: empty_or!(
            chain!(tag!(":") ~ s:second , || s)
            )
        ,
        || {
            Time {
                hour: h,
                minute: m,
                second: s.unwrap_or(0),
                tz_offset: 0
            }
        }
        ));

named!(timezone <&[u8], u32>, chain!(
        tag!("+") ~
        h: hour ~
        m: empty_or!(
            chain!(
                tag!(":")? ~ m: minute , || { m }
            ))
        ,
        || { h }));

named!(tz_z, tag!("Z"));
named!(timezone_utc <&[u8], u32>, map!(tz_z, |_| 0));

named!(time_with_timezone <&[u8], Time>, chain!(
        t: time ~
        s: empty_or!(alt!(timezone_utc | timezone))
        ,
        || {
            Time {
                hour: t.hour,
                minute: t.minute,
                second: t.second,
                tz_offset: s.unwrap_or(0) as i32
            }
        }
        ));

#[test]
fn parse_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 parse_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 parse_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 parse_date() {
    assert_eq!(Done(&[][..], Date{ year: 2015, month: 6, day: 26 }), date(b"2015-06-26"));
    assert_eq!(Done(&[][..], Date{ year: -333, month: 7, day: 11 }), date(b"-0333-07-11"));

    assert!(date(b"201").is_incomplete());
    assert!(date(b"2015p00p00").is_err());
    assert!(date(b"pppp").is_err());
}

#[test]
fn parse_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 parse_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 parse_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!(second(b"60").is_err());
    assert!(second(b"61").is_err());
    assert!(second(b"ab").is_err());
}

#[test]
fn parse_time() {
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 0}), time(b"16:43:16"));
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second:  0, tz_offset: 0}), time(b"16:43"));

    assert!(time(b"20:").is_incomplete());
    assert!(time(b"20p42p16").is_err());
    assert!(time(b"pppp").is_err());
}

#[test]
fn parse_time_with_timezone() {
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 0}),
               time_with_timezone(b"16:43:16"));
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 0}),
               time_with_timezone(b"16:43:16Z"));
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 0}),
               time_with_timezone(b"16:43:16+00:00"));
    assert_eq!(Done(&[][..], Time{ hour: 16, minute: 43, second: 16, tz_offset: 5}),
               time_with_timezone(b"16:43:16+05:00"));

    assert!(time_with_timezone(b"20:").is_incomplete());
    assert!(time_with_timezone(b"20p42p16").is_err());
    assert!(time_with_timezone(b"pppp").is_err());

    assert!(time_with_timezone(b"16:43:16+").is_err());
    assert!(time_with_timezone(b"16:43:16+0").is_err());
    assert!(time_with_timezone(b"16:43:16+05:").is_err());
}
<|endoftext|>


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

//! Rust wrapper for RocksDB.
//!
//! # Examples
//!
//! ```
//!  use rocksdb::DB;
//!  // NB: db is automatically closed at end of lifetime
//!  let db = DB::open_default("path/for/rocksdb/storage").unwrap();
//!  db.put(b"my key", b"my value");
//!  match db.get(b"my key") {
//!     Ok(Some(value)) => println!("retrieved value {}", value.to_utf8().unwrap()),
//!     Ok(None) => println!("value not found"),
//!     Err(e) => println!("operational problem encountered: {}", e),
//!  }
//!  db.delete(b"my key").unwrap();
//! ```
//!
//! Opening a database and a single column family with custom options:
//!
//! ```
//! use rocksdb::{DB, ColumnFamilyDescriptor, Options};
//! let mut cf_opts = Options::default();
//! cf_opts.set_max_write_buffer_number(16);
//! let cf = ColumnFamilyDescriptor::new("cf1", cf_opts);
//!
//! let mut db_opts = Options::default();
//! db_opts.create_missing_column_families(true);
//! db_opts.create_if_missing(true);
//!
//! let db = DB::open_cf_descriptors(&db_opts, "path/for/rocksdb/storage_with_cfs", vec![cf]).unwrap();
//! ```
//!

extern crate libc;
extern crate librocksdb_sys as ffi;

#[macro_use]
mod ffi_util;

pub mod backup;
pub mod checkpoint;
mod comparator;
pub mod merge_operator;
pub mod compaction_filter;
mod db;
mod db_options;
mod slice_transform;

pub use compaction_filter::Decision as CompactionDecision;
pub use db::{DBCompactionStyle, DBCompressionType, DBIterator, DBRawIterator, DBRecoveryMode,
             DBVector, ReadOptions, Direction, IteratorMode, Snapshot, WriteBatch,
             new_bloom_filter};

pub use slice_transform::SliceTransform;

pub use merge_operator::MergeOperands;
use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::path::PathBuf;

/// A RocksDB database.
///
/// See crate level documentation for a simple usage example.
pub struct DB {
    inner: *mut ffi::rocksdb_t,
    cfs: BTreeMap<String, ColumnFamily>,
    path: PathBuf,
}

/// A descriptor for a RocksDB column family.
///
/// A description of the column family, containing the name and `Options`.
pub struct ColumnFamilyDescriptor {
    name: String,
    options: Options,
}

/// A simple wrapper round a string, used for errors reported from
/// ffi calls.
#[derive(Debug, Clone, PartialEq)]
pub struct Error {
    message: String,
}

impl Error {
    fn new(message: String) -> Error {
        Error { message: message }
    }

    pub fn to_string(self) -> String {
        self.into()
    }
}

impl AsRef<str> for Error {
    fn as_ref(&self) -> &str {
        &self.message
    }
}

impl From<Error> for String {
    fn from(e: Error) -> String {
        e.message
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        &self.message
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.message.fmt(formatter)
    }
}

/// For configuring block-based file storage.
pub struct BlockBasedOptions {
    inner: *mut ffi::rocksdb_block_based_table_options_t,
}

/// Used by BlockBasedOptions::set_index_type.
pub enum BlockBasedIndexType {
    /// A space efficient index block that is optimized for
    /// binary-search-based index.
    BinarySearch,

    /// The hash index, if enabled, will perform a hash lookup if
    /// a prefix extractor has been provided through Options::set_prefix_extractor.
    HashSearch,

    /// A two-level index implementation. Both levels are binary search indexes.
    TwoLevelIndexSearch,
}

/// Defines the underlying memtable implementation.
/// See https://github.com/facebook/rocksdb/wiki/MemTable for more information.
pub enum MemtableFactory {
    Vector,
    HashSkipList { bucket_count: usize, height: i32, branching_factor: i32 },
    HashLinkList { bucket_count: usize }
}

/// Database-wide options around performance and behavior.
///
/// Please read [the official tuning guide](https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide), and most importantly, measure performance under realistic workloads with realistic hardware.
///
/// # Examples
///
/// ```
/// use rocksdb::{Options, DB};
/// use rocksdb::DBCompactionStyle;
///
/// fn badly_tuned_for_somebody_elses_disk() -> DB {
///    let path = "path/for/rocksdb/storageX";
///    let mut opts = Options::default();
///    opts.create_if_missing(true);
///    opts.set_max_open_files(10000);
///    opts.set_use_fsync(false);
///    opts.set_bytes_per_sync(8388608);
///    opts.optimize_for_point_lookup(1024);
///    opts.set_table_cache_num_shard_bits(6);
///    opts.set_max_write_buffer_number(32);
///    opts.set_write_buffer_size(536870912);
///    opts.set_target_file_size_base(1073741824);
///    opts.set_min_write_buffer_number_to_merge(4);
///    opts.set_level_zero_stop_writes_trigger(2000);
///    opts.set_level_zero_slowdown_writes_trigger(0);
///    opts.set_compaction_style(DBCompactionStyle::Universal);
///    opts.set_max_background_compactions(4);
///    opts.set_max_background_flushes(4);
///    opts.set_disable_auto_compactions(true);
///
///    DB::open(&opts, path).unwrap()
/// }
/// ```
pub struct Options {
    inner: *mut ffi::rocksdb_options_t,
}

/// Optionally disable WAL or sync for this write.
///
/// # Examples
///
/// Making an unsafe write of a batch:
///
/// ```
/// use rocksdb::{DB, WriteBatch, WriteOptions};
///
/// let db = DB::open_default("path/for/rocksdb/storageY").unwrap();
///
/// let mut batch = WriteBatch::default();
/// batch.put(b"my key", b"my value");
/// batch.put(b"key2", b"value2");
/// batch.put(b"key3", b"value3");
///
/// let mut write_options = WriteOptions::default();
/// write_options.set_sync(false);
/// write_options.disable_wal(true);
///
/// db.write_opt(batch, &write_options);
/// ```
pub struct WriteOptions {
    inner: *mut ffi::rocksdb_writeoptions_t,
}

/// An opaque type used to represent a column family. Returned from some functions, and used
/// in others
#[derive(Copy, Clone)]
pub struct ColumnFamily {
    inner: *mut ffi::rocksdb_column_family_handle_t,
}
<commit_msg>Makes ColumnFamily Send<commit_after>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Rust wrapper for RocksDB.
//!
//! # Examples
//!
//! ```
//!  use rocksdb::DB;
//!  // NB: db is automatically closed at end of lifetime
//!  let db = DB::open_default("path/for/rocksdb/storage").unwrap();
//!  db.put(b"my key", b"my value");
//!  match db.get(b"my key") {
//!     Ok(Some(value)) => println!("retrieved value {}", value.to_utf8().unwrap()),
//!     Ok(None) => println!("value not found"),
//!     Err(e) => println!("operational problem encountered: {}", e),
//!  }
//!  db.delete(b"my key").unwrap();
//! ```
//!
//! Opening a database and a single column family with custom options:
//!
//! ```
//! use rocksdb::{DB, ColumnFamilyDescriptor, Options};
//! let mut cf_opts = Options::default();
//! cf_opts.set_max_write_buffer_number(16);
//! let cf = ColumnFamilyDescriptor::new("cf1", cf_opts);
//!
//! let mut db_opts = Options::default();
//! db_opts.create_missing_column_families(true);
//! db_opts.create_if_missing(true);
//!
//! let db = DB::open_cf_descriptors(&db_opts, "path/for/rocksdb/storage_with_cfs", vec![cf]).unwrap();
//! ```
//!

extern crate libc;
extern crate librocksdb_sys as ffi;

#[macro_use]
mod ffi_util;

pub mod backup;
pub mod checkpoint;
mod comparator;
pub mod merge_operator;
pub mod compaction_filter;
mod db;
mod db_options;
mod slice_transform;

pub use compaction_filter::Decision as CompactionDecision;
pub use db::{DBCompactionStyle, DBCompressionType, DBIterator, DBRawIterator, DBRecoveryMode,
             DBVector, ReadOptions, Direction, IteratorMode, Snapshot, WriteBatch,
             new_bloom_filter};

pub use slice_transform::SliceTransform;

pub use merge_operator::MergeOperands;
use std::collections::BTreeMap;
use std::error;
use std::fmt;
use std::path::PathBuf;

/// A RocksDB database.
///
/// See crate level documentation for a simple usage example.
pub struct DB {
    inner: *mut ffi::rocksdb_t,
    cfs: BTreeMap<String, ColumnFamily>,
    path: PathBuf,
}

/// A descriptor for a RocksDB column family.
///
/// A description of the column family, containing the name and `Options`.
pub struct ColumnFamilyDescriptor {
    name: String,
    options: Options,
}

/// A simple wrapper round a string, used for errors reported from
/// ffi calls.
#[derive(Debug, Clone, PartialEq)]
pub struct Error {
    message: String,
}

impl Error {
    fn new(message: String) -> Error {
        Error { message: message }
    }

    pub fn to_string(self) -> String {
        self.into()
    }
}

impl AsRef<str> for Error {
    fn as_ref(&self) -> &str {
        &self.message
    }
}

impl From<Error> for String {
    fn from(e: Error) -> String {
        e.message
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        &self.message
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.message.fmt(formatter)
    }
}

/// For configuring block-based file storage.
pub struct BlockBasedOptions {
    inner: *mut ffi::rocksdb_block_based_table_options_t,
}

/// Used by BlockBasedOptions::set_index_type.
pub enum BlockBasedIndexType {
    /// A space efficient index block that is optimized for
    /// binary-search-based index.
    BinarySearch,

    /// The hash index, if enabled, will perform a hash lookup if
    /// a prefix extractor has been provided through Options::set_prefix_extractor.
    HashSearch,

    /// A two-level index implementation. Both levels are binary search indexes.
    TwoLevelIndexSearch,
}

/// Defines the underlying memtable implementation.
/// See https://github.com/facebook/rocksdb/wiki/MemTable for more information.
pub enum MemtableFactory {
    Vector,
    HashSkipList { bucket_count: usize, height: i32, branching_factor: i32 },
    HashLinkList { bucket_count: usize }
}

/// Database-wide options around performance and behavior.
///
/// Please read [the official tuning guide](https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide), and most importantly, measure performance under realistic workloads with realistic hardware.
///
/// # Examples
///
/// ```
/// use rocksdb::{Options, DB};
/// use rocksdb::DBCompactionStyle;
///
/// fn badly_tuned_for_somebody_elses_disk() -> DB {
///    let path = "path/for/rocksdb/storageX";
///    let mut opts = Options::default();
///    opts.create_if_missing(true);
///    opts.set_max_open_files(10000);
///    opts.set_use_fsync(false);
///    opts.set_bytes_per_sync(8388608);
///    opts.optimize_for_point_lookup(1024);
///    opts.set_table_cache_num_shard_bits(6);
///    opts.set_max_write_buffer_number(32);
///    opts.set_write_buffer_size(536870912);
///    opts.set_target_file_size_base(1073741824);
///    opts.set_min_write_buffer_number_to_merge(4);
///    opts.set_level_zero_stop_writes_trigger(2000);
///    opts.set_level_zero_slowdown_writes_trigger(0);
///    opts.set_compaction_style(DBCompactionStyle::Universal);
///    opts.set_max_background_compactions(4);
///    opts.set_max_background_flushes(4);
///    opts.set_disable_auto_compactions(true);
///
///    DB::open(&opts, path).unwrap()
/// }
/// ```
pub struct Options {
    inner: *mut ffi::rocksdb_options_t,
}

/// Optionally disable WAL or sync for this write.
///
/// # Examples
///
/// Making an unsafe write of a batch:
///
/// ```
/// use rocksdb::{DB, WriteBatch, WriteOptions};
///
/// let db = DB::open_default("path/for/rocksdb/storageY").unwrap();
///
/// let mut batch = WriteBatch::default();
/// batch.put(b"my key", b"my value");
/// batch.put(b"key2", b"value2");
/// batch.put(b"key3", b"value3");
///
/// let mut write_options = WriteOptions::default();
/// write_options.set_sync(false);
/// write_options.disable_wal(true);
///
/// db.write_opt(batch, &write_options);
/// ```
pub struct WriteOptions {
    inner: *mut ffi::rocksdb_writeoptions_t,
}

/// An opaque type used to represent a column family. Returned from some functions, and used
/// in others
#[derive(Copy, Clone)]
pub struct ColumnFamily {
    inner: *mut ffi::rocksdb_column_family_handle_t,
}

unsafe impl Send for ColumnFamily {}
<|endoftext|>


<commit_before>//! Implementation of the [CoAP Protocol][spec].
//!
//! This library provides both a client interface (`CoAPClient`)
//!   and a server interface (`CoAPServer`).
//!
//! Features:
//! - CoAP core protocol [RFC 7252](https://tools.ietf.org/rfc/rfc7252.txt)
//! - CoAP Observe option [RFC 7641](https://tools.ietf.org/rfc/rfc7641.txt)
//!
//! # Installation
//!
//! First add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! coap = "0.7"
//! ```
//!
//! Then, add this to your crate root:
//!
//! ```
//! extern crate coap;
//! ```
//!
//! # Example
//!
//! ## Server:
//! ```no_run
//! extern crate coap;

//! use std::io;
//! use coap::{CoAPServer, CoAPClient, CoAPRequest, CoAPResponse, Method};

//! fn request_handler(request: CoAPRequest) -> Option<CoAPResponse> {
//!     match request.get_method() {
//! 		&Method::Get => println!("request by get {}", request.get_path()),
//! 		&Method::Post => println!("request by post {}", String::from_utf8(request.message.payload).unwrap()),
//! 		_ => println!("request by other method"),
//! 	};
//!
//!     // Return the auto-generated response
//!    request.response
//! }

//! fn main() {
//! 	let addr = "127.0.0.1:5683";
//!
//! 	let mut server = CoAPServer::new(addr).unwrap();
//! 	server.handle(request_handler).unwrap();
//!
//! 	println!("Server up on {}", addr);
//!     println!("Press any key to stop...");
//!
//! 	io::stdin().read_line(&mut String::new()).unwrap();
//!
//! 	println!("Server shutdown");
//! }
//! ```
//!
//! ## Client:
//! ```no_run
//! extern crate coap;
//!
//! use coap::{CoAPClient, CoAPResponse};
//!
//! fn main() {
//! 	let url = "coap://127.0.0.1:5683/Rust";
//! 	println!("Client request: {}", url);
//!
//! 	let response = CoAPClient::get(url).unwrap();
//! 	println!("Server reply: {}", String::from_utf8(response.message.payload).unwrap());
//! }
//! ```

#[cfg(test)]
extern crate quickcheck;

pub use self::client::CoAPClient;
pub use self::message::header::MessageType;
pub use self::message::IsMessage;
pub use self::message::packet::CoAPOption;
pub use self::message::request::CoAPRequest;
pub use self::message::request::Method;
pub use self::message::response::CoAPResponse;
pub use self::message::response::Status;
pub use self::server::CoAPServer;
pub mod message;
pub mod client;
pub mod server;
mod observer;

<commit_msg>fix doc<commit_after>//! Implementation of the [CoAP Protocol][spec].
//!
//! This library provides both a client interface (`CoAPClient`)
//!   and a server interface (`CoAPServer`).
//!
//! Features:
//! - CoAP core protocol [RFC 7252](https://tools.ietf.org/rfc/rfc7252.txt)
//! - CoAP Observe option [RFC 7641](https://tools.ietf.org/rfc/rfc7641.txt)
//! - *Too Many Requests* Response Code [RFC 8516](https://tools.ietf.org/html/rfc8516)
//!
//! # Installation
//!
//! First add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! coap = "0.7"
//! ```
//!
//! Then, add this to your crate root:
//!
//! ```
//! extern crate coap;
//! ```
//!
//! # Example
//!
//! ## Server:
//! ```no_run
//! extern crate coap;

//! use std::io;
//! use coap::{CoAPServer, CoAPClient, CoAPRequest, CoAPResponse, Method};

//! fn request_handler(request: CoAPRequest) -> Option<CoAPResponse> {
//!     match request.get_method() {
//! 		&Method::Get => println!("request by get {}", request.get_path()),
//! 		&Method::Post => println!("request by post {}", String::from_utf8(request.message.payload).unwrap()),
//! 		_ => println!("request by other method"),
//! 	};
//!
//!     // Return the auto-generated response
//!    request.response
//! }

//! fn main() {
//! 	let addr = "127.0.0.1:5683";
//!
//! 	let mut server = CoAPServer::new(addr).unwrap();
//! 	server.handle(request_handler).unwrap();
//!
//! 	println!("Server up on {}", addr);
//!     println!("Press any key to stop...");
//!
//! 	io::stdin().read_line(&mut String::new()).unwrap();
//!
//! 	println!("Server shutdown");
//! }
//! ```
//!
//! ## Client:
//! ```no_run
//! extern crate coap;
//!
//! use coap::{CoAPClient, CoAPResponse};
//!
//! fn main() {
//! 	let url = "coap://127.0.0.1:5683/Rust";
//! 	println!("Client request: {}", url);
//!
//! 	let response = CoAPClient::get(url).unwrap();
//! 	println!("Server reply: {}", String::from_utf8(response.message.payload).unwrap());
//! }
//! ```

#[cfg(test)]
extern crate quickcheck;

pub use self::client::CoAPClient;
pub use self::message::header::MessageType;
pub use self::message::IsMessage;
pub use self::message::packet::CoAPOption;
pub use self::message::request::CoAPRequest;
pub use self::message::request::Method;
pub use self::message::response::CoAPResponse;
pub use self::message::response::Status;
pub use self::server::CoAPServer;
pub mod message;
pub mod client;
pub mod server;
mod observer;

<|endoftext|>


<commit_before>//! Lorem ipsum generator.
//!
//! This crate contains functions for generating pseudo-Latin lorem
//! ipsum placeholder text. The traditional lorem ipsum text start
//! like this:
//!
//! > Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
//! > eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
//! > enim ad minim veniam, quis nostrud exercitation ullamco laboris
//! > nisi ut aliquip ex ea commodo consequat. [...]
//!
//! This text is in the [`LOREM_IPSUM`] constant. Random text looking
//! like the above can be generated using the [`lipsum`] function.
//! This function allows you to generate as much text as desired and
//! each invocation will generate different text. This is done using a
//! [Markov chain] based on both the [`LOREM_IPSUM`] and
//! [`LIBER_PRIMUS`] texts. The latter constant holds the full text of
//! the first book of a work by Cicero, of which the lorem ipsum text
//! is a scrambled subset.
//!
//! The random looking text is generatd using a Markov chain of order
//! two, which simply means that the next word is based on the
//! previous two words in the input texts. The Markov chain can be
//! used with other input texts by creating an instance of
//! [`MarkovChain`] and calling its [`learn`] method.
//!
//! [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
//! [`LIBER_PRIMUS`]: constant.LIBER_PRIMUS.html
//! [`lipsum`]: fn.lipsum.html
//! [`MarkovChain`]: struct.MarkovChain.html
//! [`learn`]: struct.MarkovChain.html#method.learn
//! [Markov chain]: https://en.wikipedia.org/wiki/Markov_chain

extern crate rand;

#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;
use rand::Rng;

/// A bigram is simply two consecutive words.
pub type Bigram<'a> = (&'a str, &'a str);

/// Simple order two Markov chain implementation.
///
/// The [Markov chain] is a chain of order two, which means that it
/// will use the previous two words (a bigram) when predicting the
/// next word. This is normally enough to generate random text that
/// looks somewhat plausible. The implementation is based on
/// [Generating arbitrary text with Markov chains in Rust][blog post].
///
/// [Markov chain]: https://en.wikipedia.org/wiki/Markov_chain
/// [blog post]: https://blakewilliams.me/posts/generating-arbitrary-text-with-markov-chains-in-rust
#[derive(Default)]
pub struct MarkovChain<'a> {
    pub map: HashMap<Bigram<'a>, Vec<&'a str>>,
}

impl<'a> MarkovChain<'a> {
    /// Create a new Markov chain. It will use a default thread-local
    /// random number generator.
    pub fn new() -> MarkovChain<'a> {
        MarkovChain { map: HashMap::new() }
    }

    /// Add new text to the Markov chain. This can be called several
    /// times to build up the chain.
    ///
    /// # Examples
    ///
    /// ```
    /// use lipsum::MarkovChain;
    ///
    /// let mut chain = MarkovChain::new();
    /// chain.learn("red green blue");
    /// assert_eq!(chain.map[&("red", "green")], vec!["blue"]);
    ///
    /// chain.learn("red green yellow");
    /// assert_eq!(chain.map[&("red", "green")], vec!["blue", "yellow"]);
    /// ```
    pub fn learn(&mut self, sentence: &'a str) {
        let words = sentence.split_whitespace().collect::<Vec<&str>>();
        for window in words.windows(3) {
            let (a, b, c) = (window[0], window[1], window[2]);
            self.map.entry((a, b)).or_insert(vec![]).push(c);
        }
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from a random point in the Markov chain.
    ///
    /// See [`generate_from`] if you want to control the starting
    /// point for the generated text.
    ///
    /// # Examples
    ///
    /// Generating the sounds of a grandfather clock:
    ///
    /// ```
    /// use lipsum::MarkovChain;
    ///
    /// let mut chain = MarkovChain::new();
    /// chain.learn("Tick, Tock, Tick, Tock, Ding! Tick, Tock, Ding! Ding!");
    /// println!("{}", chain.generate(15));
    /// ```
    ///
    /// The output looks like this:
    ///
    /// > Ding! Tick, Tock, Tick, Tock, Ding! Ding! Tock, Ding! Tick,
    /// > Tock, Tick, Tock, Tick, Tock
    ///
    /// [`generate_from`]: struct.MarkovChain.html#method.generate_from
    pub fn generate(&self, n: usize) -> String {
        join_words(self.iter().take(n))
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from the given bigram.
    ///
    /// Use [`generate`] if the starting point is not important.
    ///
    /// [`generate`]: struct.MarkovChain.html#method.generate
    pub fn generate_from(&self, n: usize, from: Bigram<'a>) -> String {
        join_words(self.iter_from(from).take(n))
    }

    /// Make a never-ending iterator over the words in the Markov
    /// chain. The iterator starts at a random point in the chain.
    pub fn iter(&self) -> Words {
        let keys = self.map.keys().collect::<Vec<&(&str, &str)>>();
        let state = if keys.is_empty() {
            ("", "")
        } else {
            let mut rng = rand::thread_rng();
            **rng.choose(&keys).unwrap()
        };
        Words { map: &self.map, keys: keys, state: state }
    }

    /// Make a never-ending iterator over the words in the Markov
    /// chain. The iterator starts at the given bigram.
    pub fn iter_from(&self, from: Bigram<'a>) -> Words {
        let keys = self.map.keys().collect::<Vec<&(&str, &str)>>();
        Words { map: &self.map, keys: keys, state: from }
    }
}

pub struct Words<'a> {
    map: &'a HashMap<Bigram<'a>, Vec<&'a str>>,
    keys: Vec<&'a Bigram<'a>>,
    state: Bigram<'a>,
}

impl<'a> Iterator for Words<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.map.is_empty() {
            return None;
        }

        let result = Some(self.state.0);
        let mut rng = rand::thread_rng();

        while !self.map.contains_key(&self.state) {
            self.state = **rng.choose(&self.keys).unwrap();
        }
        let next_words = &self.map[&self.state];
        let next = rng.choose(next_words).unwrap();
        self.state = (self.state.1, next);
        result
    }
}

fn join_words<'a, I: Iterator<Item = &'a str>>(mut words: I) -> String {
    match words.next() {
        None => String::new(),
        Some(word) => {
            let mut sentence = String::from(word);
            for word in words {
                sentence.push(' ');
                sentence.push_str(word);
            }
            sentence
        }
    }
}

/// The traditional lorem ipsum text as given in [Wikipedia]. Using
/// this text alone for a Markov chain of order two doesn't work very
/// well since each bigram (two consequtive words) is followed by just
/// one other word. In other words, the Markov chain will always
/// produce the same output and recreate the lorem ipsum text
/// precisely. However, combining it with the full text in
/// [`LIBER_PRIMUS`] works well.
///
/// [Wikipedia]: https://en.wikipedia.org/wiki/Lorem_ipsum
/// [`LIBER_PRIMUS`]: constant.LIBER_PRIMUS.html
pub const LOREM_IPSUM: &'static str = include_str!("lorem-ipsum.txt");

/// The first book in Cicero's work De finibus bonorum et malorum ("On
/// the ends of good and evil"). The lorem ipsum text in
/// [`LOREM_IPSUM`] is derived from part of this text.
///
/// [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
pub const LIBER_PRIMUS: &'static str = include_str!("liber-primus.txt");

lazy_static! {
    /// Markov chain generating lorem ipsum text.
    static ref LOREM_IPSUM_CHAIN: MarkovChain<'static> = {
        let mut chain = MarkovChain::new();
        chain.learn(LOREM_IPSUM);
        chain.learn(LIBER_PRIMUS);
        chain
    };
}

/// Generate `n` words of lorem ipsum text. The output starts with
/// "Lorem ipsum" and continues with the standard lorem ipsum text
/// from [`LOREM_IPSUM`]. The text will become random if sufficiently
/// long output is requested.
///
/// [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
pub fn lipsum(n: usize) -> String {
    LOREM_IPSUM_CHAIN.generate_from(n, ("Lorem", "ipsum"))
}

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

    #[test]
    fn starts_with_lorem_ipsum() {
        assert_eq!(&lipsum(10)[..11], "Lorem ipsum");
    }

    #[test]
    fn generate_zero_words() {
        assert_eq!(lipsum(0).split_whitespace().count(), 0);
    }

    #[test]
    fn generate_one_word() {
        assert_eq!(lipsum(1).split_whitespace().count(), 1);
    }

    #[test]
    fn generate_two_words() {
        assert_eq!(lipsum(2).split_whitespace().count(), 2);
    }

    #[test]
    fn empty_chain() {
        let chain = MarkovChain::new();
        assert_eq!(chain.generate(10), "");
    }

    #[test]
    fn generate_from() {
        let mut chain = MarkovChain::new();
        chain.learn("red orange yellow green blue indigo violet");
        assert_eq!(chain.generate_from(5, ("orange", "yellow")),
                   "orange yellow green blue indigo");
    }

    #[test]
    fn generate_last_bigram() {
        // The bigram "yyy zzz" will not be present in the Markov
        // chain's map, and so we will not generate "xxx yyy zzz" as
        // one would expect. The chain moves from state "xxx yyy" to
        // "yyy zzz", but sees that as invalid state and resets itsel
        // back to "xxx yyy".
        let mut chain = MarkovChain::new();
        chain.learn("xxx yyy zzz");
        // We use assert! instead of assert_ne! to support early
        // versions of Rust.
        assert!(chain.generate_from(3, ("xxx", "yyy")) != "xxx yyy zzz");
    }

    #[test]
    fn generate_from_no_panic() {
        // No panic when asked to generate a chain from a starting
        // point that doesn't exist in the chain.
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz");
        chain.generate_from(3, ("xxx", "yyy"));
    }

    #[test]
    fn chain_map() {
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz quuz");
        let map = &chain.map;

        assert_eq!(map.len(), 2);
        assert_eq!(map[&("foo", "bar")], vec!["baz"]);
        assert_eq!(map[&("bar", "baz")], vec!["quuz"]);
    }
}
<commit_msg>clippy: avoid or_insert followed by function call<commit_after>//! Lorem ipsum generator.
//!
//! This crate contains functions for generating pseudo-Latin lorem
//! ipsum placeholder text. The traditional lorem ipsum text start
//! like this:
//!
//! > Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
//! > eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut
//! > enim ad minim veniam, quis nostrud exercitation ullamco laboris
//! > nisi ut aliquip ex ea commodo consequat. [...]
//!
//! This text is in the [`LOREM_IPSUM`] constant. Random text looking
//! like the above can be generated using the [`lipsum`] function.
//! This function allows you to generate as much text as desired and
//! each invocation will generate different text. This is done using a
//! [Markov chain] based on both the [`LOREM_IPSUM`] and
//! [`LIBER_PRIMUS`] texts. The latter constant holds the full text of
//! the first book of a work by Cicero, of which the lorem ipsum text
//! is a scrambled subset.
//!
//! The random looking text is generatd using a Markov chain of order
//! two, which simply means that the next word is based on the
//! previous two words in the input texts. The Markov chain can be
//! used with other input texts by creating an instance of
//! [`MarkovChain`] and calling its [`learn`] method.
//!
//! [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
//! [`LIBER_PRIMUS`]: constant.LIBER_PRIMUS.html
//! [`lipsum`]: fn.lipsum.html
//! [`MarkovChain`]: struct.MarkovChain.html
//! [`learn`]: struct.MarkovChain.html#method.learn
//! [Markov chain]: https://en.wikipedia.org/wiki/Markov_chain

extern crate rand;

#[macro_use]
extern crate lazy_static;

use std::collections::HashMap;
use rand::Rng;

/// A bigram is simply two consecutive words.
pub type Bigram<'a> = (&'a str, &'a str);

/// Simple order two Markov chain implementation.
///
/// The [Markov chain] is a chain of order two, which means that it
/// will use the previous two words (a bigram) when predicting the
/// next word. This is normally enough to generate random text that
/// looks somewhat plausible. The implementation is based on
/// [Generating arbitrary text with Markov chains in Rust][blog post].
///
/// [Markov chain]: https://en.wikipedia.org/wiki/Markov_chain
/// [blog post]: https://blakewilliams.me/posts/generating-arbitrary-text-with-markov-chains-in-rust
#[derive(Default)]
pub struct MarkovChain<'a> {
    pub map: HashMap<Bigram<'a>, Vec<&'a str>>,
}

impl<'a> MarkovChain<'a> {
    /// Create a new Markov chain. It will use a default thread-local
    /// random number generator.
    pub fn new() -> MarkovChain<'a> {
        MarkovChain { map: HashMap::new() }
    }

    /// Add new text to the Markov chain. This can be called several
    /// times to build up the chain.
    ///
    /// # Examples
    ///
    /// ```
    /// use lipsum::MarkovChain;
    ///
    /// let mut chain = MarkovChain::new();
    /// chain.learn("red green blue");
    /// assert_eq!(chain.map[&("red", "green")], vec!["blue"]);
    ///
    /// chain.learn("red green yellow");
    /// assert_eq!(chain.map[&("red", "green")], vec!["blue", "yellow"]);
    /// ```
    pub fn learn(&mut self, sentence: &'a str) {
        let words = sentence.split_whitespace().collect::<Vec<&str>>();
        for window in words.windows(3) {
            let (a, b, c) = (window[0], window[1], window[2]);
            self.map.entry((a, b)).or_insert_with(Vec::new).push(c);
        }
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from a random point in the Markov chain.
    ///
    /// See [`generate_from`] if you want to control the starting
    /// point for the generated text.
    ///
    /// # Examples
    ///
    /// Generating the sounds of a grandfather clock:
    ///
    /// ```
    /// use lipsum::MarkovChain;
    ///
    /// let mut chain = MarkovChain::new();
    /// chain.learn("Tick, Tock, Tick, Tock, Ding! Tick, Tock, Ding! Ding!");
    /// println!("{}", chain.generate(15));
    /// ```
    ///
    /// The output looks like this:
    ///
    /// > Ding! Tick, Tock, Tick, Tock, Ding! Ding! Tock, Ding! Tick,
    /// > Tock, Tick, Tock, Tick, Tock
    ///
    /// [`generate_from`]: struct.MarkovChain.html#method.generate_from
    pub fn generate(&self, n: usize) -> String {
        join_words(self.iter().take(n))
    }

    /// Generate `n` words worth of lorem ipsum text. The text will
    /// start from the given bigram.
    ///
    /// Use [`generate`] if the starting point is not important.
    ///
    /// [`generate`]: struct.MarkovChain.html#method.generate
    pub fn generate_from(&self, n: usize, from: Bigram<'a>) -> String {
        join_words(self.iter_from(from).take(n))
    }

    /// Make a never-ending iterator over the words in the Markov
    /// chain. The iterator starts at a random point in the chain.
    pub fn iter(&self) -> Words {
        let keys = self.map.keys().collect::<Vec<&(&str, &str)>>();
        let state = if keys.is_empty() {
            ("", "")
        } else {
            let mut rng = rand::thread_rng();
            **rng.choose(&keys).unwrap()
        };
        Words { map: &self.map, keys: keys, state: state }
    }

    /// Make a never-ending iterator over the words in the Markov
    /// chain. The iterator starts at the given bigram.
    pub fn iter_from(&self, from: Bigram<'a>) -> Words {
        let keys = self.map.keys().collect::<Vec<&(&str, &str)>>();
        Words { map: &self.map, keys: keys, state: from }
    }
}

pub struct Words<'a> {
    map: &'a HashMap<Bigram<'a>, Vec<&'a str>>,
    keys: Vec<&'a Bigram<'a>>,
    state: Bigram<'a>,
}

impl<'a> Iterator for Words<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        if self.map.is_empty() {
            return None;
        }

        let result = Some(self.state.0);
        let mut rng = rand::thread_rng();

        while !self.map.contains_key(&self.state) {
            self.state = **rng.choose(&self.keys).unwrap();
        }
        let next_words = &self.map[&self.state];
        let next = rng.choose(next_words).unwrap();
        self.state = (self.state.1, next);
        result
    }
}

fn join_words<'a, I: Iterator<Item = &'a str>>(mut words: I) -> String {
    match words.next() {
        None => String::new(),
        Some(word) => {
            let mut sentence = String::from(word);
            for word in words {
                sentence.push(' ');
                sentence.push_str(word);
            }
            sentence
        }
    }
}

/// The traditional lorem ipsum text as given in [Wikipedia]. Using
/// this text alone for a Markov chain of order two doesn't work very
/// well since each bigram (two consequtive words) is followed by just
/// one other word. In other words, the Markov chain will always
/// produce the same output and recreate the lorem ipsum text
/// precisely. However, combining it with the full text in
/// [`LIBER_PRIMUS`] works well.
///
/// [Wikipedia]: https://en.wikipedia.org/wiki/Lorem_ipsum
/// [`LIBER_PRIMUS`]: constant.LIBER_PRIMUS.html
pub const LOREM_IPSUM: &'static str = include_str!("lorem-ipsum.txt");

/// The first book in Cicero's work De finibus bonorum et malorum ("On
/// the ends of good and evil"). The lorem ipsum text in
/// [`LOREM_IPSUM`] is derived from part of this text.
///
/// [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
pub const LIBER_PRIMUS: &'static str = include_str!("liber-primus.txt");

lazy_static! {
    /// Markov chain generating lorem ipsum text.
    static ref LOREM_IPSUM_CHAIN: MarkovChain<'static> = {
        let mut chain = MarkovChain::new();
        chain.learn(LOREM_IPSUM);
        chain.learn(LIBER_PRIMUS);
        chain
    };
}

/// Generate `n` words of lorem ipsum text. The output starts with
/// "Lorem ipsum" and continues with the standard lorem ipsum text
/// from [`LOREM_IPSUM`]. The text will become random if sufficiently
/// long output is requested.
///
/// [`LOREM_IPSUM`]: constant.LOREM_IPSUM.html
pub fn lipsum(n: usize) -> String {
    LOREM_IPSUM_CHAIN.generate_from(n, ("Lorem", "ipsum"))
}

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

    #[test]
    fn starts_with_lorem_ipsum() {
        assert_eq!(&lipsum(10)[..11], "Lorem ipsum");
    }

    #[test]
    fn generate_zero_words() {
        assert_eq!(lipsum(0).split_whitespace().count(), 0);
    }

    #[test]
    fn generate_one_word() {
        assert_eq!(lipsum(1).split_whitespace().count(), 1);
    }

    #[test]
    fn generate_two_words() {
        assert_eq!(lipsum(2).split_whitespace().count(), 2);
    }

    #[test]
    fn empty_chain() {
        let chain = MarkovChain::new();
        assert_eq!(chain.generate(10), "");
    }

    #[test]
    fn generate_from() {
        let mut chain = MarkovChain::new();
        chain.learn("red orange yellow green blue indigo violet");
        assert_eq!(chain.generate_from(5, ("orange", "yellow")),
                   "orange yellow green blue indigo");
    }

    #[test]
    fn generate_last_bigram() {
        // The bigram "yyy zzz" will not be present in the Markov
        // chain's map, and so we will not generate "xxx yyy zzz" as
        // one would expect. The chain moves from state "xxx yyy" to
        // "yyy zzz", but sees that as invalid state and resets itsel
        // back to "xxx yyy".
        let mut chain = MarkovChain::new();
        chain.learn("xxx yyy zzz");
        // We use assert! instead of assert_ne! to support early
        // versions of Rust.
        assert!(chain.generate_from(3, ("xxx", "yyy")) != "xxx yyy zzz");
    }

    #[test]
    fn generate_from_no_panic() {
        // No panic when asked to generate a chain from a starting
        // point that doesn't exist in the chain.
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz");
        chain.generate_from(3, ("xxx", "yyy"));
    }

    #[test]
    fn chain_map() {
        let mut chain = MarkovChain::new();
        chain.learn("foo bar baz quuz");
        let map = &chain.map;

        assert_eq!(map.len(), 2);
        assert_eq!(map[&("foo", "bar")], vec!["baz"]);
        assert_eq!(map[&("bar", "baz")], vec!["quuz"]);
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;

pub mod columns;
pub mod error;

use self::columns::{Columns, BytesColumns};
use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};
use std::iter::{Enumerate, Iterator};
use std::path::Path;

use error::{Error, Result};
use rustc_serialize::Decodable;

#[cfg(test)] mod test;

/// Csv reader
///
/// Iterates over the rows of the csv
///
/// # Example
///
/// ```rust
/// let csv = quick_csv::Csv::from_file("./examples/data/bench.csv").unwrap();
/// for row in csv.into_iter() {
///     let row = row.unwrap(); // unwrap result, panic if not utf8
///     {
///         // either use columns iterator directly (Item = &str)
///         if let Ok(mut columns) = row.columns() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", columns.next(), columns.next());
///         }
///     }
///
///     {
///         // or decode it directly into something simpler
///         if let Ok((col1, col2)) = row.decode::<(String, u64)>() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", &col1, &col2);
///         }
///     }
///
/// }
/// ```
pub struct Csv<B: BufRead> {
    /// delimiter
    delimiter: u8,
    /// reader
    reader: B,
    /// header
    has_header: bool,
    /// column count
    len: Option<usize>,
    /// if was error, exit next
    exit: bool,
}

impl<B: BufRead> Csv<B> {

    /// Creates a Csv from a generic BufReader
    ///
    /// Note: default delimiter = ','
    pub fn from_reader(reader: B) -> Csv<B> {
        Csv {
            reader: reader,
            delimiter: b',',
            has_header: false,
            len: None,
            exit: false,
        }
    }

    /// Sets a new delimiter
    pub fn delimiter(mut self, delimiter: u8) -> Csv<B> {
        self.delimiter = delimiter;
        self
    }

    /// Defines whether there is a header or not
    pub fn has_header(mut self, has_header: bool) -> Csv<B> {
        self.has_header = has_header;
        self
    }

   /// gets first row as Vec<String>
    pub fn header(&mut self) -> Result<Vec<String>> {
        if self.has_header {
            if let Some(r) = self.next() {
                let r = try!(r);
                return r.decode();
            }
        }
        Ok(Vec::new())
    }

    /// Get column count
    pub fn len(&self) -> Option<usize> {
        self.len
    }
}

impl Csv<BufReader<File>> {
    /// Creates a csv from a file path
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Csv<BufReader<File>>>
    {
        let reader = BufReader::new(try!(File::open(path)));
        Ok(Csv::from_reader(reader))
    }
}

impl<'a> Csv<&'a [u8]> {
    /// Creates a CSV reader for an in memory string buffer.
    pub fn from_string(s: &'a str) -> Csv<&'a [u8]> {
        Csv::from_reader(s.as_bytes())
    }
}

/// Iterator on csv returning rows
impl<B: BufRead> Iterator for Csv<B> {
    type Item = Result<Row>;
    fn next(&mut self) -> Option<Result<Row>> {
        if self.exit { return None; }
        let mut buf = Vec::new();
        let mut cols = self.len.map_or_else(|| Vec::new(), |n| Vec::with_capacity(n));
        match read_line(&mut self.reader, &mut buf, self.delimiter, &mut cols) {
            Ok(0) => None,
            Ok(_n) => {
                if buf.ends_with(&[b'\r']) {
                    buf.pop();
                }
                cols.push(buf.len());
                let c = cols.len();
                if let Some(n) = self.len {
                    if n != c {
                        return Some(Err(Error::ColumnMismatch(n, c)));
                    }
                } else {
                    self.len = Some(c);
                }
                Some(Ok(Row {
                    line: buf,
                    cols: cols,
                }))
            }
            Err(e) => {
                self.exit = true;
                Some(Err(e))
            },
        }
    }
}

/// Row struct used as Csv iterator Item
///
/// Row can be decoded into a Result<T: Decodable>
pub struct Row {
    line: Vec<u8>,
    cols: Vec<usize>,
}

impl Row {

    /// Gets an iterator over columns
    pub fn columns<'a>(&'a self) -> Result<Columns<'a>> {
        match ::std::str::from_utf8(&self.line) {
            Err(_) => Err(Error::from(io::Error::new(io::ErrorKind::InvalidData,
                                            "stream did not contain valid UTF-8"))),
            Ok(s) => Ok(Columns::new(s, &self.cols)),
        }
    }

    ///  Creates a new BytesColumns iterator over &[u8]
    pub fn bytes_columns<'a>(&'a self) -> BytesColumns<'a> {
        BytesColumns::new(&self.line, &self.cols)
    }

    /// Decode row into custom decodable type
    pub fn decode<T: Decodable>(&self) -> Result<T> {
        let mut columns = try!(self.columns());
        Decodable::decode(&mut columns)
    }

    /// Gets columns count
    pub fn len(&self) -> usize {
        self.cols.len()
    }

}

/// Consumes bytes as long as they are within quotes
/// manages "" as quote escape
/// returns
/// - Ok(true) if entirely consumed
/// - Ok(false) if no issue but it reached end of buffer
/// - Err(Error::UnescapeQuote) if a quote if found within the column
fn consume_quote<'a>(bytes: &'a mut Enumerate<::std::slice::Iter<u8>>, delimiter: u8)
    -> Result<bool>
{
    loop {
        match bytes.next() {
            Some((_, &b'\"')) => {
                match bytes.clone().next() {
                    Some((_, &b'\"')) => {
                        bytes.next(); // escaping quote
                    },
                    None | Some((_, &b'\r')) | Some((_, &b'\n')) => return Ok(true),
                    Some((_, d)) if *d == delimiter => return Ok(true),
                    Some((_, _)) => return Err(Error::UnescapedQuote),
                }
            },
            None => return Ok(false),
            _ => (),
        }
    }
}

fn read_line<R: BufRead>(r: &mut R, buf: &mut Vec<u8>,
    delimiter: u8, cols: &mut Vec<usize>) -> Result<usize>
{
    let mut read = 0;
    let mut in_quote = false;
    let mut done = false;
    while !done {
        let used = {
            let available = match r.fill_buf() {
                Ok(n) if n.is_empty() => return Ok(read),
                Ok(n) => n,
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                Err(e) => return Err(Error::from(e)),
            };

            let mut bytes = available.iter().enumerate();

            // previous buffer was exhausted without exiting from quotes
            if in_quote && try!(consume_quote(&mut bytes, delimiter)) {
                in_quote = false;
            }

            // use a simple loop instead of for loop to allow nested loop
            let used: usize;
            loop {
                match bytes.next() {
                    Some((i, &b'\"')) => {
                        if i == 0 || available[i - 1] == delimiter {
                            if !try!(consume_quote(&mut bytes, delimiter)) {
                                in_quote = true;
                            }
                        } else {
                            return Err(Error::UnexpextedQuote);
                        }
                    },
                    Some((i, &b'\n')) => {
                        let _ = buf.write(&available[..i]);
                        done = true;
                        used = i + 1;
                        break;
                    },
                    Some((i, &d)) => {
                        if d == delimiter { cols.push(read + i); }
                    },
                    None => {
                        let _ = buf.write(available);
                        used = available.len();
                        break;
                    },
                }
            }
            used
        };
        r.consume(used);
        read += used;
    }
    Ok(read)
}
<commit_msg>Use macro_rule for consume_quote<commit_after>extern crate rustc_serialize;

pub mod columns;
pub mod error;

use self::columns::{Columns, BytesColumns};
use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};
use std::iter::Iterator;
use std::path::Path;

use error::{Error, Result};
use rustc_serialize::Decodable;

#[cfg(test)] mod test;

/// Csv reader
///
/// Iterates over the rows of the csv
///
/// # Example
///
/// ```rust
/// let csv = quick_csv::Csv::from_file("./examples/data/bench.csv").unwrap();
/// for row in csv.into_iter() {
///     let row = row.unwrap(); // unwrap result, panic if not utf8
///     {
///         // either use columns iterator directly (Item = &str)
///         if let Ok(mut columns) = row.columns() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", columns.next(), columns.next());
///         }
///     }
///
///     {
///         // or decode it directly into something simpler
///         if let Ok((col1, col2)) = row.decode::<(String, u64)>() {
///             println!("Column 1: '{:?}', Column 2: '{:?}'", &col1, &col2);
///         }
///     }
///
/// }
/// ```
pub struct Csv<B: BufRead> {
    /// delimiter
    delimiter: u8,
    /// reader
    reader: B,
    /// header
    has_header: bool,
    /// column count
    len: Option<usize>,
    /// if was error, exit next
    exit: bool,
}

impl<B: BufRead> Csv<B> {

    /// Creates a Csv from a generic BufReader
    ///
    /// Note: default delimiter = ','
    pub fn from_reader(reader: B) -> Csv<B> {
        Csv {
            reader: reader,
            delimiter: b',',
            has_header: false,
            len: None,
            exit: false,
        }
    }

    /// Sets a new delimiter
    pub fn delimiter(mut self, delimiter: u8) -> Csv<B> {
        self.delimiter = delimiter;
        self
    }

    /// Defines whether there is a header or not
    pub fn has_header(mut self, has_header: bool) -> Csv<B> {
        self.has_header = has_header;
        self
    }

   /// gets first row as Vec<String>
    pub fn header(&mut self) -> Result<Vec<String>> {
        if self.has_header {
            if let Some(r) = self.next() {
                let r = try!(r);
                return r.decode();
            }
        }
        Ok(Vec::new())
    }

    /// Get column count
    pub fn len(&self) -> Option<usize> {
        self.len
    }
}

impl Csv<BufReader<File>> {
    /// Creates a csv from a file path
    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Csv<BufReader<File>>>
    {
        let reader = BufReader::new(try!(File::open(path)));
        Ok(Csv::from_reader(reader))
    }
}

impl<'a> Csv<&'a [u8]> {
    /// Creates a CSV reader for an in memory string buffer.
    pub fn from_string(s: &'a str) -> Csv<&'a [u8]> {
        Csv::from_reader(s.as_bytes())
    }
}

/// Iterator on csv returning rows
impl<B: BufRead> Iterator for Csv<B> {
    type Item = Result<Row>;
    fn next(&mut self) -> Option<Result<Row>> {
        if self.exit { return None; }
        let mut buf = Vec::new();
        let mut cols = self.len.map_or_else(|| Vec::new(), |n| Vec::with_capacity(n));
        match read_line(&mut self.reader, &mut buf, self.delimiter, &mut cols) {
            Ok(0) => None,
            Ok(_n) => {
                if buf.ends_with(&[b'\r']) {
                    buf.pop();
                }
                cols.push(buf.len());
                let c = cols.len();
                if let Some(n) = self.len {
                    if n != c {
                        return Some(Err(Error::ColumnMismatch(n, c)));
                    }
                } else {
                    self.len = Some(c);
                }
                Some(Ok(Row {
                    line: buf,
                    cols: cols,
                }))
            }
            Err(e) => {
                self.exit = true;
                Some(Err(e))
            },
        }
    }
}

/// Row struct used as Csv iterator Item
///
/// Row can be decoded into a Result<T: Decodable>
pub struct Row {
    line: Vec<u8>,
    cols: Vec<usize>,
}

impl Row {

    /// Gets an iterator over columns
    pub fn columns<'a>(&'a self) -> Result<Columns<'a>> {
        match ::std::str::from_utf8(&self.line) {
            Err(_) => Err(Error::from(io::Error::new(io::ErrorKind::InvalidData,
                                            "stream did not contain valid UTF-8"))),
            Ok(s) => Ok(Columns::new(s, &self.cols)),
        }
    }

    ///  Creates a new BytesColumns iterator over &[u8]
    pub fn bytes_columns<'a>(&'a self) -> BytesColumns<'a> {
        BytesColumns::new(&self.line, &self.cols)
    }

    /// Decode row into custom decodable type
    pub fn decode<T: Decodable>(&self) -> Result<T> {
        let mut columns = try!(self.columns());
        Decodable::decode(&mut columns)
    }

    /// Gets columns count
    pub fn len(&self) -> usize {
        self.cols.len()
    }

}

/// Consumes bytes as long as they are within quotes
/// manages "" as quote escape
/// returns
/// - Ok(true) if entirely consumed
/// - Ok(false) if no issue but it reached end of buffer
/// - Err(Error::UnescapeQuote) if a quote if found within the column
macro_rules! consume_quote {
    ($bytes: expr, $delimiter: expr, $in_quote: expr) => {
        $in_quote = false;
        loop {
            match $bytes.next() {
                Some((_, &b'\"')) => {
                    match $bytes.clone().next() {
                        Some((_, &b'\"')) => {
                            $bytes.next(); // escaping quote
                        },
                        None | Some((_, &b'\r')) | Some((_, &b'\n')) => break,
                        Some((_, d)) if *d == $delimiter => break,
                        Some((_, _)) => return Err(Error::UnescapedQuote),
                    }
                },
                None => {
                    $in_quote = true;
                    break;
                },
                _ => (),
            }
        }
    }
}

fn read_line<R: BufRead>(r: &mut R, buf: &mut Vec<u8>,
    delimiter: u8, cols: &mut Vec<usize>) -> Result<usize>
{
    let mut read = 0;
    let mut in_quote = false;
    let mut done = false;
    while !done {
        let used = {
            let available = match r.fill_buf() {
                Ok(n) if n.is_empty() => return Ok(read),
                Ok(n) => n,
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => continue,
                Err(e) => return Err(Error::from(e)),
            };

            let mut bytes = available.iter().enumerate();

            // previous buffer was exhausted without exiting from quotes
            if in_quote {
                consume_quote!(bytes, delimiter, in_quote);
            }

            // use a simple loop instead of for loop to allow nested loop
            let used: usize;
            loop {
                match bytes.next() {
                    Some((i, &b'\"')) => {
                        if i == 0 || available[i - 1] == delimiter {
                            consume_quote!(bytes, delimiter, in_quote);
                        } else {
                            return Err(Error::UnexpextedQuote);
                        }
                    },
                    Some((i, &b'\n')) => {
                        let _ = buf.write(&available[..i]);
                        done = true;
                        used = i + 1;
                        break;
                    },
                    Some((i, &d)) => {
                        if d == delimiter { cols.push(read + i); }
                    },
                    None => {
                        let _ = buf.write(available);
                        used = available.len();
                        break;
                    },
                }
            }
            used
        };
        r.consume(used);
        read += used;
    }
    Ok(read)
}
<|endoftext|>


<commit_before>// Copyright 2017 Brian Langenberger
//
// 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.

//! Traits and helpers for bitstream handling functionality
//!
//! Bitstream readers are for reading signed and unsigned integer
//! values from a stream whose sizes may not be whole bytes.
//! Bitstream writers are for writing signed and unsigned integer
//! values to a stream, also potentially un-aligned at a whole byte.
//!
//! Both big-endian and little-endian streams are supported.
//!
//! The only requirement for wrapped reader streams is that they must
//! implement the `Read` trait, and the only requirement
//! for writer streams is that they must implement the `Write` trait.
//!
//! In addition, reader streams do not consume any more bytes
//! from the underlying reader than necessary, buffering only a
//! single partial byte as needed.
//! Writer streams also write out all whole bytes as they are accumulated.
//!
//! Readers and writers are also designed to work with integer
//! types of any possible size.
//! Many of Rust's built-in integer types are supported by default.
//!
//! ## Type Sizes
//!
//! Because both the type sizes and bit counts are variable,
//! it is the responsibity of the programmer to ensure that
//! the capacity of one's variables does not exceed the
//! requested bit count when reading or writing.
//! Otherwise, an overflow error panic may occur.
//!
//! For example, reading 8 bits from the stream to a 32-bit variable
//! is harmless (the topmost 24 bits are left empty),
//! but reading 32 bits from the stream to an 8-bit variable
//! may result in a panic.
//! Similarly, writing a 32-bit variable to 8 bits is also harmless
//! (the topmost 24 bits are ignored), but writing an 8-bit variable
//! to 32 bits in the stream may cause a panic.

use std::ops::{Shl, ShlAssign, Shr, ShrAssign, Rem, RemAssign, BitOrAssign,
               BitXor, Not, Sub};
use std::marker::PhantomData;
use std::fmt::Debug;

pub mod read;
pub mod write;
pub mod huffman;
pub use read::BitReader;
pub use write::BitWriter;

/// This trait extends many common integer types (both unsigned and signed)
/// with a few trivial methods so that they can be used
/// with the bitstream handling traits.
pub trait Numeric: Sized + Copy + Default + Debug +
    Shl<u32,Output=Self> + ShlAssign<u32> +
    Shr<u32,Output=Self> + ShrAssign<u32> +
    Rem<Self,Output=Self> + RemAssign<Self> +
    BitOrAssign<Self> + BitXor<Self,Output=Self> + Not<Output=Self> +
    Sub<Self,Output=Self> {

    /// The value of 1 in this type
    fn one() -> Self;

    /// Returns true if this value is 0, in its type
    fn is_zero(self) -> bool;

    /// Returns a `u8` value in this type
    fn from_u8(u: u8) -> Self;

    /// Assuming 0 <= value < 256, returns this value as a `u8` type
    fn to_u8(self) -> u8;

    /// Counts the number of 1 bits
    fn count_ones(self) -> u32;

    /// Counts the number of leading zeros
    fn leading_zeros(self) -> u32;

    /// Counts the number of trailing zeros
    fn trailing_zeros(self) -> u32;

    /// Size of type in bits
    fn bits_size() -> u32;
}

macro_rules! define_numeric {
    ($t:ty, $bits:expr) => {
        impl Numeric for $t {
            #[inline(always)]
            fn one() -> Self {1}
            #[inline(always)]
            fn is_zero(self) -> bool {self == 0}
            #[inline(always)]
            fn from_u8(u: u8) -> Self {u as $t}
            #[inline(always)]
            fn to_u8(self) -> u8 {self as u8}
            #[inline(always)]
            fn count_ones(self) -> u32 {self.count_ones()}
            #[inline(always)]
            fn leading_zeros(self) -> u32 {self.leading_zeros()}
            #[inline(always)]
            fn trailing_zeros(self) -> u32 {self.trailing_zeros()}
            #[inline(always)]
            fn bits_size() -> u32 {$bits}
        }
    }
}

/// This trait extends many common signed integer types
/// so that they can be used with the bitstream handling traits.
pub trait SignedNumeric: Numeric {
    /// Returns true if this value is negative
    fn is_negative(self) -> bool;

    /// Given a two-complement positive value and certain number of bits,
    /// returns this value as a negative number.
    fn as_negative(self, bits: u32) -> Self;

    /// Given a negative value and a certain number of bits,
    /// returns this value as a twos-complement positive number.
    fn as_unsigned(self, bits: u32) -> Self;
}

macro_rules! define_signed_numeric {
    ($t:ty) => {
        impl SignedNumeric for $t {
            #[inline(always)]
            fn is_negative(self) -> bool {self < 0}
            #[inline(always)]
            fn as_negative(self, bits: u32) -> Self {self + (-1 << (bits - 1))}
            #[inline(always)]
            fn as_unsigned(self, bits: u32) -> Self {self - (-1 << (bits - 1))}
        }
    }
}

define_numeric!(u8, 8);
define_numeric!(i8, 8);
define_numeric!(u16, 16);
define_numeric!(i16, 16);
define_numeric!(u32, 32);
define_numeric!(i32, 32);
define_numeric!(u64, 64);
define_numeric!(i64, 64);

define_signed_numeric!(i8);
define_signed_numeric!(i16);
define_signed_numeric!(i32);
define_signed_numeric!(i64);

pub trait Endianness {
    fn leading_sign() -> bool;

    fn push<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32,
               value: N) where N: Numeric;

    fn pop<N>(bits_acc: &mut u32,
              value_acc: &mut N,
              bits: u32) -> N where N: Numeric;

    fn drop<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32) where N: Numeric;

    fn next_zeros<N>(bits: u32, value: N) -> u32 where N: Numeric;

    fn next_ones<N>(bits: u32, value: N) -> u32 where N: Numeric;
}

pub struct BigEndian {}
pub type BE = BigEndian;

impl Endianness for BigEndian {
    #[inline(always)]
    fn leading_sign() -> bool {true}

    fn push<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32,
               value: N) where N: Numeric {
        if !value_acc.is_zero() {
            *value_acc <<= bits;
        }
        *value_acc |= value;
        *bits_acc += bits;
    }

    fn pop<N>(bits_acc: &mut u32,
              value_acc: &mut N,
              bits: u32) -> N where N: Numeric {
        if bits < *bits_acc {
            let offset = *bits_acc - bits;
            let to_return = *value_acc >> offset;
            *value_acc %= N::one() << offset;
            *bits_acc -= bits;
            to_return
        } else {
            let to_return = *value_acc;
            *value_acc = N::default();
            *bits_acc = 0;
            to_return
        }
    }

    fn drop<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32) where N: Numeric {
        if bits < *bits_acc {
            *value_acc %= N::one() << (*bits_acc - bits);
            *bits_acc -= bits;
        } else {
            *value_acc = N::default();
            *bits_acc = 0;
        }
    }

    #[inline]
    fn next_zeros<N>(bits: u32, value: N) -> u32 where N: Numeric {
        value.leading_zeros() - (N::bits_size() - bits)
    }

    #[inline]
    fn next_ones<N>(bits: u32, value: N) -> u32 where N: Numeric {
        if bits < N::bits_size() {
            (value ^ ((N::one() << bits) - N::one())).leading_zeros() -
            (N::bits_size() - bits)
        } else {
            (!value).leading_zeros()
        }
    }
}

pub struct LittleEndian {}
pub type LE = LittleEndian;

impl Endianness for LittleEndian {
    #[inline(always)]
    fn leading_sign() -> bool {false}

    fn push<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32,
               mut value: N) where N: Numeric {
        value <<= *bits_acc;
        *value_acc |= value;
        *bits_acc += bits;
    }

    fn pop<N>(bits_acc: &mut u32,
              value_acc: &mut N,
              bits: u32) -> N where N: Numeric {
        if bits < *bits_acc {
            let to_return = *value_acc % (N::one() << bits);
            *value_acc >>= bits;
            *bits_acc -= bits;
            to_return
        } else {
            let to_return = *value_acc;
            *value_acc = N::default();
            *bits_acc = 0;
            to_return
        }
    }

    fn drop<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32) where N: Numeric {
        if bits < *bits_acc {
            *value_acc >>= bits;
            *bits_acc -= bits;
        } else {
            *value_acc = N::default();
            *bits_acc = 0;
        }
    }

    #[inline]
    fn next_zeros<N>(_: u32, value: N) -> u32 where N: Numeric {
        value.trailing_zeros()
    }

    #[inline]
    fn next_ones<N>(_: u32, value: N) -> u32 where N: Numeric {
        (value ^ !N::default()).trailing_zeros()
    }
}

pub struct BitQueue<E: Endianness, N: Numeric> {
    phantom: PhantomData<E>,
    value: N,
    bits: u32,
}

impl<E: Endianness, N: Numeric> BitQueue<E, N> {
    /// Returns a new empty queue
    #[inline]
    pub fn new() -> BitQueue<E, N> {
        BitQueue{phantom: PhantomData, value: N::default(), bits: 0}
    }

    /// Creates a new queue from the given value with the given size
    #[inline]
    pub fn from_value(value: N, bits: u32) -> BitQueue<E,N> {
        BitQueue{phantom: PhantomData, value: value, bits: bits}
    }

    /// Sets the queue to a given value with the given number of bits
    #[inline]
    pub fn set(&mut self, value: N, bits: u32) {
        self.value = value;
        self.bits = bits;
    }

    /// Consumes the queue and returns its current value
    #[inline(always)]
    pub fn value(self) -> N {self.value}

    /// Returns the total bits in the queue
    #[inline(always)]
    pub fn len(&self) -> u32 {self.bits}

    /// Returns true if the queue is empty
    #[inline(always)]
    pub fn is_empty(&self) -> bool {self.bits == 0}

    /// Drops all values in the queue
    #[inline(always)]
    pub fn clear(&mut self) {self.set(N::default(), 0)}

    /// Returns true if all bits remaining in the queue are 0
    #[inline(always)]
    pub fn all_0(&self) -> bool {self.value.count_ones() == 0}

    /// Returns true if all bits remaining in the queue are 1
    #[inline(always)]
    pub fn all_1(&self) -> bool {self.value.count_ones() == self.bits}

    /// Pushes a value with the given number of bits onto the tail of the queue
    #[inline(always)]
    pub fn push(&mut self, bits: u32, value: N) {
        E::push(&mut self.bits, &mut self.value, bits, value)
    }

    /// Pops a value with the given number of bits from the head of the queue
    #[inline(always)]
    pub fn pop(&mut self, bits: u32) -> N {
        E::pop(&mut self.bits, &mut self.value, bits)
    }

    /// Drops the given number of bits from the head of the queue
    /// without returning them.
    #[inline(always)]
    pub fn drop(&mut self, bits: u32) {
        E::drop(&mut self.bits, &mut self.value, bits)
    }

    /// Pops all 0 bits up to and including the next 1 bit
    /// and returns the amount of 0 bits popped
    #[inline]
    pub fn pop_0(&mut self) -> u32 {
        let zeros = E::next_zeros(self.bits, self.value);
        self.drop(zeros + 1);
        zeros
    }

    /// Pops all 1 bits up to and including the next 0 bit
    /// and returns the amount of 1 bits popped
    #[inline]
    pub fn pop_1(&mut self) -> u32 {
        let ones = E::next_ones(self.bits, self.value);
        self.drop(ones + 1);
        ones
    }
}
<commit_msg>Minor documentation updates<commit_after>// Copyright 2017 Brian Langenberger
//
// 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.

//! Traits and helpers for bitstream handling functionality
//!
//! Bitstream readers are for reading signed and unsigned integer
//! values from a stream whose sizes may not be whole bytes.
//! Bitstream writers are for writing signed and unsigned integer
//! values to a stream, also potentially un-aligned at a whole byte.
//!
//! Both big-endian and little-endian streams are supported.
//!
//! The only requirement for wrapped reader streams is that they must
//! implement the `Read` trait, and the only requirement
//! for writer streams is that they must implement the `Write` trait.
//!
//! In addition, reader streams do not consume any more bytes
//! from the underlying reader than necessary, buffering only a
//! single partial byte as needed.
//! Writer streams also write out all whole bytes as they are accumulated.
//!
//! Readers and writers are also designed to work with integer
//! types of any possible size.
//! Many of Rust's built-in integer types are supported by default.
//!
//! ## Type Sizes
//!
//! Because both the type sizes and bit counts are variable,
//! it is the responsibity of the programmer to ensure that
//! the capacity of one's variables does not exceed the
//! requested bit count when reading or writing.
//! Otherwise, an overflow error panic may occur.
//!
//! For example, reading 8 bits from the stream to a 32-bit variable
//! is harmless (the topmost 24 bits are left empty),
//! but reading 32 bits from the stream to an 8-bit variable
//! may result in a panic.
//! Similarly, writing a 32-bit variable to 8 bits is also harmless
//! (the topmost 24 bits are ignored), but writing an 8-bit variable
//! to 32 bits in the stream may cause a panic.

use std::ops::{Shl, ShlAssign, Shr, ShrAssign, Rem, RemAssign, BitOrAssign,
               BitXor, Not, Sub};
use std::marker::PhantomData;
use std::fmt::Debug;

pub mod read;
pub mod write;
pub mod huffman;
pub use read::BitReader;
pub use write::BitWriter;

/// This trait extends many common integer types (both unsigned and signed)
/// with a few trivial methods so that they can be used
/// with the bitstream handling traits.
pub trait Numeric: Sized + Copy + Default + Debug +
    Shl<u32,Output=Self> + ShlAssign<u32> +
    Shr<u32,Output=Self> + ShrAssign<u32> +
    Rem<Self,Output=Self> + RemAssign<Self> +
    BitOrAssign<Self> + BitXor<Self,Output=Self> + Not<Output=Self> +
    Sub<Self,Output=Self> {

    /// The value of 1 in this type
    fn one() -> Self;

    /// Returns true if this value is 0, in its type
    fn is_zero(self) -> bool;

    /// Returns a `u8` value in this type
    fn from_u8(u: u8) -> Self;

    /// Assuming 0 <= value < 256, returns this value as a `u8` type
    fn to_u8(self) -> u8;

    /// Counts the number of 1 bits
    fn count_ones(self) -> u32;

    /// Counts the number of leading zeros
    fn leading_zeros(self) -> u32;

    /// Counts the number of trailing zeros
    fn trailing_zeros(self) -> u32;

    /// Size of type in bits
    fn bits_size() -> u32;
}

macro_rules! define_numeric {
    ($t:ty, $bits:expr) => {
        impl Numeric for $t {
            #[inline(always)]
            fn one() -> Self {1}
            #[inline(always)]
            fn is_zero(self) -> bool {self == 0}
            #[inline(always)]
            fn from_u8(u: u8) -> Self {u as $t}
            #[inline(always)]
            fn to_u8(self) -> u8 {self as u8}
            #[inline(always)]
            fn count_ones(self) -> u32 {self.count_ones()}
            #[inline(always)]
            fn leading_zeros(self) -> u32 {self.leading_zeros()}
            #[inline(always)]
            fn trailing_zeros(self) -> u32 {self.trailing_zeros()}
            #[inline(always)]
            fn bits_size() -> u32 {$bits}
        }
    }
}

/// This trait extends many common signed integer types
/// so that they can be used with the bitstream handling traits.
pub trait SignedNumeric: Numeric {
    /// Returns true if this value is negative
    fn is_negative(self) -> bool;

    /// Given a two-complement positive value and certain number of bits,
    /// returns this value as a negative number.
    fn as_negative(self, bits: u32) -> Self;

    /// Given a negative value and a certain number of bits,
    /// returns this value as a twos-complement positive number.
    fn as_unsigned(self, bits: u32) -> Self;
}

macro_rules! define_signed_numeric {
    ($t:ty) => {
        impl SignedNumeric for $t {
            #[inline(always)]
            fn is_negative(self) -> bool {self < 0}
            #[inline(always)]
            fn as_negative(self, bits: u32) -> Self {self + (-1 << (bits - 1))}
            #[inline(always)]
            fn as_unsigned(self, bits: u32) -> Self {self - (-1 << (bits - 1))}
        }
    }
}

define_numeric!(u8, 8);
define_numeric!(i8, 8);
define_numeric!(u16, 16);
define_numeric!(i16, 16);
define_numeric!(u32, 32);
define_numeric!(i32, 32);
define_numeric!(u64, 64);
define_numeric!(i64, 64);

define_signed_numeric!(i8);
define_signed_numeric!(i16);
define_signed_numeric!(i32);
define_signed_numeric!(i64);

/// A stream's endianness, or byte order, for determining
/// how bits should be read.
pub trait Endianness {
    fn leading_sign() -> bool;

    fn push<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32,
               value: N) where N: Numeric;

    fn pop<N>(bits_acc: &mut u32,
              value_acc: &mut N,
              bits: u32) -> N where N: Numeric;

    fn drop<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32) where N: Numeric;

    fn next_zeros<N>(bits: u32, value: N) -> u32 where N: Numeric;

    fn next_ones<N>(bits: u32, value: N) -> u32 where N: Numeric;
}

/// Big-endian, or most significant bits first
pub struct BigEndian {}

/// Big-endian, or most significant bits first
pub type BE = BigEndian;

impl Endianness for BigEndian {
    #[inline(always)]
    fn leading_sign() -> bool {true}

    fn push<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32,
               value: N) where N: Numeric {
        if !value_acc.is_zero() {
            *value_acc <<= bits;
        }
        *value_acc |= value;
        *bits_acc += bits;
    }

    fn pop<N>(bits_acc: &mut u32,
              value_acc: &mut N,
              bits: u32) -> N where N: Numeric {
        if bits < *bits_acc {
            let offset = *bits_acc - bits;
            let to_return = *value_acc >> offset;
            *value_acc %= N::one() << offset;
            *bits_acc -= bits;
            to_return
        } else {
            let to_return = *value_acc;
            *value_acc = N::default();
            *bits_acc = 0;
            to_return
        }
    }

    fn drop<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32) where N: Numeric {
        if bits < *bits_acc {
            *value_acc %= N::one() << (*bits_acc - bits);
            *bits_acc -= bits;
        } else {
            *value_acc = N::default();
            *bits_acc = 0;
        }
    }

    #[inline]
    fn next_zeros<N>(bits: u32, value: N) -> u32 where N: Numeric {
        value.leading_zeros() - (N::bits_size() - bits)
    }

    #[inline]
    fn next_ones<N>(bits: u32, value: N) -> u32 where N: Numeric {
        if bits < N::bits_size() {
            (value ^ ((N::one() << bits) - N::one())).leading_zeros() -
            (N::bits_size() - bits)
        } else {
            (!value).leading_zeros()
        }
    }
}

/// Little-endian, or least significant bits first
pub struct LittleEndian {}

/// Little-endian, or least significant bits first
pub type LE = LittleEndian;

impl Endianness for LittleEndian {
    #[inline(always)]
    fn leading_sign() -> bool {false}

    fn push<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32,
               mut value: N) where N: Numeric {
        value <<= *bits_acc;
        *value_acc |= value;
        *bits_acc += bits;
    }

    fn pop<N>(bits_acc: &mut u32,
              value_acc: &mut N,
              bits: u32) -> N where N: Numeric {
        if bits < *bits_acc {
            let to_return = *value_acc % (N::one() << bits);
            *value_acc >>= bits;
            *bits_acc -= bits;
            to_return
        } else {
            let to_return = *value_acc;
            *value_acc = N::default();
            *bits_acc = 0;
            to_return
        }
    }

    fn drop<N>(bits_acc: &mut u32,
               value_acc: &mut N,
               bits: u32) where N: Numeric {
        if bits < *bits_acc {
            *value_acc >>= bits;
            *bits_acc -= bits;
        } else {
            *value_acc = N::default();
            *bits_acc = 0;
        }
    }

    #[inline]
    fn next_zeros<N>(_: u32, value: N) -> u32 where N: Numeric {
        value.trailing_zeros()
    }

    #[inline]
    fn next_ones<N>(_: u32, value: N) -> u32 where N: Numeric {
        (value ^ !N::default()).trailing_zeros()
    }
}

/// A queue for efficiently pushing bits onto a value
/// and popping them off a value.
pub struct BitQueue<E: Endianness, N: Numeric> {
    phantom: PhantomData<E>,
    value: N,
    bits: u32,
}

impl<E: Endianness, N: Numeric> BitQueue<E, N> {
    /// Returns a new empty queue
    #[inline]
    pub fn new() -> BitQueue<E, N> {
        BitQueue{phantom: PhantomData, value: N::default(), bits: 0}
    }

    /// Creates a new queue from the given value with the given size
    #[inline]
    pub fn from_value(value: N, bits: u32) -> BitQueue<E,N> {
        BitQueue{phantom: PhantomData, value: value, bits: bits}
    }

    /// Sets the queue to a given value with the given number of bits
    #[inline]
    pub fn set(&mut self, value: N, bits: u32) {
        self.value = value;
        self.bits = bits;
    }

    /// Consumes the queue and returns its current value
    #[inline(always)]
    pub fn value(self) -> N {self.value}

    /// Returns the total bits in the queue
    #[inline(always)]
    pub fn len(&self) -> u32 {self.bits}

    /// Returns true if the queue is empty
    #[inline(always)]
    pub fn is_empty(&self) -> bool {self.bits == 0}

    /// Drops all values in the queue
    #[inline(always)]
    pub fn clear(&mut self) {self.set(N::default(), 0)}

    /// Returns true if all bits remaining in the queue are 0
    #[inline(always)]
    pub fn all_0(&self) -> bool {self.value.count_ones() == 0}

    /// Returns true if all bits remaining in the queue are 1
    #[inline(always)]
    pub fn all_1(&self) -> bool {self.value.count_ones() == self.bits}

    /// Pushes a value with the given number of bits onto the tail of the queue
    #[inline(always)]
    pub fn push(&mut self, bits: u32, value: N) {
        E::push(&mut self.bits, &mut self.value, bits, value)
    }

    /// Pops a value with the given number of bits from the head of the queue
    #[inline(always)]
    pub fn pop(&mut self, bits: u32) -> N {
        E::pop(&mut self.bits, &mut self.value, bits)
    }

    /// Drops the given number of bits from the head of the queue
    /// without returning them.
    #[inline(always)]
    pub fn drop(&mut self, bits: u32) {
        E::drop(&mut self.bits, &mut self.value, bits)
    }

    /// Pops all 0 bits up to and including the next 1 bit
    /// and returns the amount of 0 bits popped
    #[inline]
    pub fn pop_0(&mut self) -> u32 {
        let zeros = E::next_zeros(self.bits, self.value);
        self.drop(zeros + 1);
        zeros
    }

    /// Pops all 1 bits up to and including the next 0 bit
    /// and returns the amount of 1 bits popped
    #[inline]
    pub fn pop_1(&mut self) -> u32 {
        let ones = E::next_ones(self.bits, self.value);
        self.drop(ones + 1);
        ones
    }
}
<|endoftext|>