<commit_before>//! I/O conveniences when working with primitives in `tokio-core`
//!
//! Contains various combinators to work with I/O objects and type definitions
//! as well.
//!
//! A description of the high-level I/O combinators can be [found online] in
//! addition to a description of the [low level details].
//!
//! [found online]: https://tokio.rs/docs/getting-started/core/
//! [low level details]: https://tokio.rs/docs/going-deeper/core-low-level/

#[macro_use]
extern crate log;
extern crate futures;

use std::io;

use futures::{BoxFuture, Async};
use futures::stream::BoxStream;

/// A convenience typedef around a `Future` whose error component is `io::Error`
pub type IoFuture<T> = BoxFuture<T, io::Error>;

/// A convenience typedef around a `Stream` whose error component is `io::Error`
pub type IoStream<T> = BoxStream<T, io::Error>;

/// A convenience macro for working with `io::Result<T>` from the `Read` and
/// `Write` traits.
///
/// This macro takes `io::Result<T>` as input, and returns `T` as the output. If
/// the input type is of the `Err` variant, then `Poll::NotReady` is returned if
/// it indicates `WouldBlock` or otherwise `Err` is returned.
#[macro_export]
macro_rules! try_nb {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
            return Ok(::futures::Async::NotReady)
        }
        Err(e) => return Err(e.into()),
    })
}

mod copy;
mod frame;
mod flush;
mod read_exact;
mod read_to_end;
mod read;
mod read_until;
mod split;
mod window;
mod write_all;
pub use self::copy::{copy, Copy};
pub use self::frame::{EasyBuf, EasyBufMut, Framed, Codec};
pub use self::flush::{flush, Flush};
pub use self::read_exact::{read_exact, ReadExact};
pub use self::read_to_end::{read_to_end, ReadToEnd};
pub use self::read::{read, Read};
pub use self::read_until::{read_until, ReadUntil};
pub use self::split::{ReadHalf, WriteHalf};
pub use self::window::Window;
pub use self::write_all::{write_all, WriteAll};

pub trait AsyncRead: io::Read {
    /// Tests to see if this I/O object may be readable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be readable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `read` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is readable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_read(&mut self) -> Async<()> {
        Async::Ready(())
    }

    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    fn framed<C: Codec>(self, codec: C) -> Framed<Self, C>
        where Self: AsyncWrite + Sized,
    {
        frame::framed(self, codec)
    }

    /// Helper method for splitting this read/write object into two halves.
    ///
    /// The two halves returned implement the `Read` and `Write` traits,
    /// respectively.
    fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
        where Self: AsyncWrite + Sized,
    {
        split::split(self)
    }
}

pub trait AsyncWrite: io::Write {
    /// Tests to see if this I/O object may be writable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be writable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `write` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is writable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_write(&mut self) -> Async<()> {
        Async::Ready(())
    }
}
<commit_msg>Add some impls<commit_after>//! I/O conveniences when working with primitives in `tokio-core`
//!
//! Contains various combinators to work with I/O objects and type definitions
//! as well.
//!
//! A description of the high-level I/O combinators can be [found online] in
//! addition to a description of the [low level details].
//!
//! [found online]: https://tokio.rs/docs/getting-started/core/
//! [low level details]: https://tokio.rs/docs/going-deeper/core-low-level/

#[macro_use]
extern crate log;
extern crate futures;

use std::io;

use futures::{BoxFuture, Async};
use futures::stream::BoxStream;

/// A convenience typedef around a `Future` whose error component is `io::Error`
pub type IoFuture<T> = BoxFuture<T, io::Error>;

/// A convenience typedef around a `Stream` whose error component is `io::Error`
pub type IoStream<T> = BoxStream<T, io::Error>;

/// A convenience macro for working with `io::Result<T>` from the `Read` and
/// `Write` traits.
///
/// This macro takes `io::Result<T>` as input, and returns `T` as the output. If
/// the input type is of the `Err` variant, then `Poll::NotReady` is returned if
/// it indicates `WouldBlock` or otherwise `Err` is returned.
#[macro_export]
macro_rules! try_nb {
    ($e:expr) => (match $e {
        Ok(t) => t,
        Err(ref e) if e.kind() == ::std::io::ErrorKind::WouldBlock => {
            return Ok(::futures::Async::NotReady)
        }
        Err(e) => return Err(e.into()),
    })
}

mod copy;
mod frame;
mod flush;
mod read_exact;
mod read_to_end;
mod read;
mod read_until;
mod split;
mod window;
mod write_all;
pub use self::copy::{copy, Copy};
pub use self::frame::{EasyBuf, EasyBufMut, Framed, Codec};
pub use self::flush::{flush, Flush};
pub use self::read_exact::{read_exact, ReadExact};
pub use self::read_to_end::{read_to_end, ReadToEnd};
pub use self::read::{read, Read};
pub use self::read_until::{read_until, ReadUntil};
pub use self::split::{ReadHalf, WriteHalf};
pub use self::window::Window;
pub use self::write_all::{write_all, WriteAll};

pub trait AsyncRead: io::Read {
    /// Tests to see if this I/O object may be readable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be readable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `read` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is readable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_read(&mut self) -> Async<()> {
        Async::Ready(())
    }

    /// Provides a `Stream` and `Sink` interface for reading and writing to this
    /// `Io` object, using `Decode` and `Encode` to read and write the raw data.
    ///
    /// Raw I/O objects work with byte sequences, but higher-level code usually
    /// wants to batch these into meaningful chunks, called "frames". This
    /// method layers framing on top of an I/O object, by using the `Codec`
    /// traits to handle encoding and decoding of messages frames. Note that
    /// the incoming and outgoing frame types may be distinct.
    ///
    /// This function returns a *single* object that is both `Stream` and
    /// `Sink`; grouping this into a single object is often useful for layering
    /// things like gzip or TLS, which require both read and write access to the
    /// underlying object.
    ///
    /// If you want to work more directly with the streams and sink, consider
    /// calling `split` on the `Framed` returned by this method, which will
    /// break them into separate objects, allowing them to interact more easily.
    fn framed<C: Codec>(self, codec: C) -> Framed<Self, C>
        where Self: AsyncWrite + Sized,
    {
        frame::framed(self, codec)
    }

    /// Helper method for splitting this read/write object into two halves.
    ///
    /// The two halves returned implement the `Read` and `Write` traits,
    /// respectively.
    fn split(self) -> (ReadHalf<Self>, WriteHalf<Self>)
        where Self: AsyncWrite + Sized,
    {
        split::split(self)
    }
}

pub trait AsyncWrite: io::Write {
    /// Tests to see if this I/O object may be writable.
    ///
    /// This method returns an `Async<()>` indicating whether the object
    /// **might** be writable. It is possible that even if this method returns
    /// `Async::Ready` that a call to `write` would return a `WouldBlock` error.
    ///
    /// There is a default implementation for this function which always
    /// indicates that an I/O object is writable, but objects which can
    /// implement a finer grained version of this are recommended to do so.
    ///
    /// If this function returns `Async::NotReady` then the current future's
    /// task is arranged to receive a notification when it might not return
    /// `NotReady`.
    ///
    /// # Panics
    ///
    /// This method is likely to panic if called from outside the context of a
    /// future's task.
    fn poll_write(&mut self) -> Async<()> {
        Async::Ready(())
    }
}

impl AsyncRead for io::Repeat {}
impl AsyncWrite for io::Sink {}
impl<T: AsyncRead> AsyncRead for io::Take<T> {}
<|endoftext|>


<commit_before>#![crate_name = "amethyst"]
#![crate_type = "lib"]
#![doc(html_logo_url = "http://tinyurl.com/hgsb45k")]

//! Amethyst is a free and open source game engine written in idiomatic
//! [Rust][rs] for building video games and interactive multimedia applications.
//! The source code is available for download on [GitHub][gh]. See the online
//! [online book][bk] for a complete guide to using Amethyst.
//!
//! [rs]: https://www.rust-lang.org/
//! [gh]: https://github.com/ebkalderon/amethyst
//! [bk]: http://ebkalderon.github.io/amethyst/
//!
//! This project is a work in progress and is very incomplete. Pardon the dust!
//!
//! # Example
//!
//! ```ignore
//! extern crate amethyst;
//!
//! use amethyst::*;
//!
//! struct GameState;
//!
//! impl State for GameState {
//!     fn handle_events(&mut self, events: &Vec<Event>) -> Trans {
//!         for e in events {
//!             match e {
//!                 Event::Closed => Trans::Quit,
//!                 Event::Resized(x, y) => println!("x: {}, y: {}", x, y),
//!                 Event::KeyPressed(k) => if k == Key::Esc { Trans::Quit },
//!             }
//!         }
//!         Trans::None
//!     }
//!
//!     fn update(&mut self, _delta: Duration) -> Trans {
//!         println!("Computing some more whoop-ass...");
//!         Trans::None
//!     }
//! }
//!
//! fn main() {
//!     let mut game = Application::new(GameState);
//!     game.run();
//! }
//! ```

extern crate amethyst_engine;
extern crate amethyst_renderer;

pub use amethyst_engine as engine;
pub use amethyst_renderer as renderer;
<commit_msg>remove redundant word<commit_after>#![crate_name = "amethyst"]
#![crate_type = "lib"]
#![doc(html_logo_url = "http://tinyurl.com/hgsb45k")]

//! Amethyst is a free and open source game engine written in idiomatic
//! [Rust][rs] for building video games and interactive multimedia applications.
//! The source code is available for download on [GitHub][gh]. See the
//! [online book][bk] for a complete guide to using Amethyst.
//!
//! [rs]: https://www.rust-lang.org/
//! [gh]: https://github.com/ebkalderon/amethyst
//! [bk]: http://ebkalderon.github.io/amethyst/
//!
//! This project is a work in progress and is very incomplete. Pardon the dust!
//!
//! # Example
//!
//! ```ignore
//! extern crate amethyst;
//!
//! use amethyst::*;
//!
//! struct GameState;
//!
//! impl State for GameState {
//!     fn handle_events(&mut self, events: &Vec<Event>) -> Trans {
//!         for e in events {
//!             match e {
//!                 Event::Closed => Trans::Quit,
//!                 Event::Resized(x, y) => println!("x: {}, y: {}", x, y),
//!                 Event::KeyPressed(k) => if k == Key::Esc { Trans::Quit },
//!             }
//!         }
//!         Trans::None
//!     }
//!
//!     fn update(&mut self, _delta: Duration) -> Trans {
//!         println!("Computing some more whoop-ass...");
//!         Trans::None
//!     }
//! }
//!
//! fn main() {
//!     let mut game = Application::new(GameState);
//!     game.run();
//! }
//! ```

extern crate amethyst_engine;
extern crate amethyst_renderer;

pub use amethyst_engine as engine;
pub use amethyst_renderer as renderer;
<|endoftext|>


<commit_before>#![feature(rustc_private)]
#![feature(map_try_insert)]
#![feature(never_type)]
#![feature(try_blocks)]
#![feature(io_error_more)]
#![feature(int_log)]
#![feature(variant_count)]
#![feature(yeet_expr)]
#![feature(is_some_and)]
#![feature(nonzero_ops)]
#![feature(local_key_cell_methods)]
#![feature(is_terminal)]
// Configure clippy and other lints
#![allow(
    clippy::collapsible_else_if,
    clippy::collapsible_if,
    clippy::comparison_chain,
    clippy::enum_variant_names,
    clippy::field_reassign_with_default,
    clippy::manual_map,
    clippy::new_without_default,
    clippy::single_match,
    clippy::useless_format,
    clippy::derive_partial_eq_without_eq,
    clippy::derive_hash_xor_eq,
    clippy::too_many_arguments,
    clippy::type_complexity,
    clippy::single_element_loop,
    clippy::needless_return,
    clippy::bool_to_int_with_if,
    // We are not implementing queries here so it's fine
    rustc::potential_query_instability
)]
#![warn(
    rust_2018_idioms,
    clippy::cast_possible_wrap, // unsigned -> signed
    clippy::cast_sign_loss, // signed -> unsigned
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
)]

extern crate rustc_apfloat;
extern crate rustc_ast;
#[macro_use]
extern crate rustc_middle;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_hir;
extern crate rustc_index;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;

mod clock;
mod concurrency;
mod diagnostics;
mod eval;
mod helpers;
mod intptrcast;
mod machine;
mod mono_hash_map;
mod operator;
mod range_map;
mod shims;
mod stacked_borrows;
mod tag_gc;

// Establish a "crate-wide prelude": we often import `crate::*`.

// Make all those symbols available in the same place as our own.
pub use rustc_const_eval::interpret::*;
// Resolve ambiguity.
pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};

pub use crate::shims::dlsym::{Dlsym, EvalContextExt as _};
pub use crate::shims::env::{EnvVars, EvalContextExt as _};
pub use crate::shims::foreign_items::EvalContextExt as _;
pub use crate::shims::intrinsics::EvalContextExt as _;
pub use crate::shims::os_str::EvalContextExt as _;
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
pub use crate::shims::time::EvalContextExt as _;
pub use crate::shims::tls::{EvalContextExt as _, TlsData};
pub use crate::shims::EvalContextExt as _;

pub use crate::clock::{Clock, Instant};
pub use crate::concurrency::{
    data_race::{AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _},
    init_once::{EvalContextExt as _, InitOnceId},
    sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SyncId},
    thread::{EvalContextExt as _, SchedulingAction, ThreadId, ThreadManager, ThreadState, Time},
};
pub use crate::diagnostics::{
    report_error, EvalContextExt as _, NonHaltingDiagnostic, TerminationInfo,
};
pub use crate::eval::{
    create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
};
pub use crate::helpers::{CurrentSpan, EvalContextExt as _};
pub use crate::intptrcast::ProvenanceMode;
pub use crate::machine::{
    AllocExtra, FrameData, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
    PrimitiveLayouts, Provenance, ProvenanceExtra, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::operator::EvalContextExt as _;
pub use crate::range_map::RangeMap;
pub use crate::stacked_borrows::{
    CallId, EvalContextExt as _, Item, Permission, RetagFields, SbTag, Stack, Stacks,
};
pub use crate::tag_gc::{EvalContextExt as _, VisitTags};

/// Insert rustc arguments at the beginning of the argument list that Miri wants to be
/// set per default, for maximal validation power.
pub const MIRI_DEFAULT_ARGS: &[&str] = &[
    "-Zalways-encode-mir",
    "-Zmir-emit-retag",
    "-Zmir-opt-level=0",
    "--cfg=miri",
    "-Cdebug-assertions=on",
    "-Zextra-const-ub-checks",
];
<commit_msg>Auto merge of #102950 - oli-obk:check_miri, r=RalfJung<commit_after>#![feature(rustc_private)]
#![feature(map_try_insert)]
#![feature(never_type)]
#![feature(try_blocks)]
#![feature(io_error_more)]
#![feature(int_log)]
#![feature(variant_count)]
#![feature(yeet_expr)]
#![feature(is_some_and)]
#![feature(nonzero_ops)]
#![feature(local_key_cell_methods)]
#![feature(is_terminal)]
// Configure clippy and other lints
#![allow(
    clippy::collapsible_else_if,
    clippy::collapsible_if,
    clippy::comparison_chain,
    clippy::enum_variant_names,
    clippy::field_reassign_with_default,
    clippy::manual_map,
    clippy::new_without_default,
    clippy::single_match,
    clippy::useless_format,
    clippy::derive_partial_eq_without_eq,
    clippy::derive_hash_xor_eq,
    clippy::too_many_arguments,
    clippy::type_complexity,
    clippy::single_element_loop,
    clippy::needless_return,
    clippy::bool_to_int_with_if,
    // We are not implementing queries here so it's fine
    rustc::potential_query_instability
)]
#![warn(
    rust_2018_idioms,
    clippy::cast_possible_wrap, // unsigned -> signed
    clippy::cast_sign_loss, // signed -> unsigned
    clippy::cast_lossless,
    clippy::cast_possible_truncation,
)]
// Needed for rustdoc from bootstrap (with `-Znormalize-docs`).
#![recursion_limit = "256"]

extern crate rustc_apfloat;
extern crate rustc_ast;
#[macro_use]
extern crate rustc_middle;
extern crate rustc_const_eval;
extern crate rustc_data_structures;
extern crate rustc_hir;
extern crate rustc_index;
extern crate rustc_session;
extern crate rustc_span;
extern crate rustc_target;

mod clock;
mod concurrency;
mod diagnostics;
mod eval;
mod helpers;
mod intptrcast;
mod machine;
mod mono_hash_map;
mod operator;
mod range_map;
mod shims;
mod stacked_borrows;
mod tag_gc;

// Establish a "crate-wide prelude": we often import `crate::*`.

// Make all those symbols available in the same place as our own.
pub use rustc_const_eval::interpret::*;
// Resolve ambiguity.
pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};

pub use crate::shims::dlsym::{Dlsym, EvalContextExt as _};
pub use crate::shims::env::{EnvVars, EvalContextExt as _};
pub use crate::shims::foreign_items::EvalContextExt as _;
pub use crate::shims::intrinsics::EvalContextExt as _;
pub use crate::shims::os_str::EvalContextExt as _;
pub use crate::shims::panic::{CatchUnwindData, EvalContextExt as _};
pub use crate::shims::time::EvalContextExt as _;
pub use crate::shims::tls::{EvalContextExt as _, TlsData};
pub use crate::shims::EvalContextExt as _;

pub use crate::clock::{Clock, Instant};
pub use crate::concurrency::{
    data_race::{AtomicFenceOrd, AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, EvalContextExt as _},
    init_once::{EvalContextExt as _, InitOnceId},
    sync::{CondvarId, EvalContextExt as _, MutexId, RwLockId, SyncId},
    thread::{EvalContextExt as _, SchedulingAction, ThreadId, ThreadManager, ThreadState, Time},
};
pub use crate::diagnostics::{
    report_error, EvalContextExt as _, NonHaltingDiagnostic, TerminationInfo,
};
pub use crate::eval::{
    create_ecx, eval_entry, AlignmentCheck, BacktraceStyle, IsolatedOp, MiriConfig, RejectOpWith,
};
pub use crate::helpers::{CurrentSpan, EvalContextExt as _};
pub use crate::intptrcast::ProvenanceMode;
pub use crate::machine::{
    AllocExtra, FrameData, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind,
    PrimitiveLayouts, Provenance, ProvenanceExtra, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
};
pub use crate::mono_hash_map::MonoHashMap;
pub use crate::operator::EvalContextExt as _;
pub use crate::range_map::RangeMap;
pub use crate::stacked_borrows::{
    CallId, EvalContextExt as _, Item, Permission, RetagFields, SbTag, Stack, Stacks,
};
pub use crate::tag_gc::{EvalContextExt as _, VisitTags};

/// Insert rustc arguments at the beginning of the argument list that Miri wants to be
/// set per default, for maximal validation power.
pub const MIRI_DEFAULT_ARGS: &[&str] = &[
    "-Zalways-encode-mir",
    "-Zmir-emit-retag",
    "-Zmir-opt-level=0",
    "--cfg=miri",
    "-Cdebug-assertions=on",
    "-Zextra-const-ub-checks",
];
<|endoftext|>


<commit_before>use std::cmp;

extern crate kana;
use kana::Kana;

pub mod dict;
use dict::{Dict, KanaConversionTable};

pub enum ConvType {
    Auto(String),
    Hira(String),
    Kata(String),
}

pub fn to_kana(d: &Dict, s: ConvType) -> String {
    let s = match s {
        ConvType::Auto(s) => s,
        ConvType::Hira(s) => s.to_lowercase(),
        ConvType::Kata(s) => s.to_uppercase(),
    };
    convert(d, &s)
}

// Converts a String as is
fn convert(d: &Dict, s: &String) -> String {
    let mut ret: String = String::new();

    for w in normalize(s).split_whitespace() {
        let w: String = choose_kana(&w.to_string());
        let ss: Vec<String> = syllables(&d, &w)
            .iter()
            .map(|ref s| convert_syllable(d, &s))
            .collect();
        for syl in ss {
            ret.push_str(syl.as_str());
        }
    }
    ret
}

fn syllables(d: &Dict, original: &String) -> Vec<String> {
    if original.len() == 0 {
        return vec![];
    }

    let mut ret: Vec<String> = vec![];
    let maxlen = cmp::min(original.chars().count(), d.max_len()) + 1;

    for l in (1..maxlen).rev() {
        let tmp: String = original.chars().take(l).collect();

        if is_syllable(d, &tmp) {
            ret.push(tmp);
            let skipped: String = original.chars().skip(l).collect();
            let mut rest = syllables(d, &skipped);

            ret.append(&mut rest);

            return ret;
        }
    }

    // if a match wasn't found, add the first char to ret
    // let mut taken: Vec<String> = vec![original.chars().take(1).collect()];
    // ret.append(&mut taken);

    let taken: String = original.chars().take(1).collect();
    ret.push(taken);

    let skipped: String = original.chars().skip(1).collect();
    let mut rest = syllables(d, &skipped);
    ret.append(&mut rest);

    ret
}

// Given a String (expected to be normalized), returns `true` if it is a syllable and
// `false` otherwise.
fn is_syllable(d: &Dict, k: &String) -> bool {
    d.contains_key(k)
}

// Searches for uppercase characters in a String and, if it finds any, turns the whole String to
// uppercase.
fn choose_kana(s: &String) -> String {
    match s.chars().fold(false, |acc, c| acc || c.is_uppercase()) {
        true => s.to_uppercase(),
        false => s.to_string(),
    }
}

fn normalize(s: &String) -> String {
    let k = Kana::init();
    let mut ret: String = s.clone();

    ret = kana::nowidespace(ret.as_str());
    ret = kana::nowideyen(ret.as_str());
    ret = kana::wide2ascii(ret.as_str());

    ret = k.combine(ret.as_str());
    ret = k.half2kana(ret.as_str());

    ret
}

// Converts a String (expected to be a syllable) to kana.
fn convert_syllable(d: &Dict, ow: &String) -> String {
    // <pingveno> Because String impls Borrow<str>
    // `&ow.to_string()` => `ow`
    match d.get(ow) {
        Some(c) => c.clone(),
        None => ow.clone(),
    }
}
<commit_msg>Add a type param to `ConvType`<commit_after>use std::cmp;

extern crate kana;
use kana::Kana;

pub mod dict;
use dict::{Dict, KanaConversionTable};

pub enum ConvType<T> {
    Auto(T),
    Hira(T),
    Kata(T),
}

pub fn to_kana(d: &Dict, s: ConvType<String>) -> String {
    let s = match s {
        ConvType::Auto(s) => s,
        ConvType::Hira(s) => s.to_lowercase(),
        ConvType::Kata(s) => s.to_uppercase(),
    };
    convert(d, &s)
}

// Converts a String as is
fn convert(d: &Dict, s: &String) -> String {
    let mut ret: String = String::new();

    for w in normalize(s).split_whitespace() {
        let w: String = choose_kana(&w.to_string());
        let ss: Vec<String> = syllables(&d, &w)
            .iter()
            .map(|ref s| convert_syllable(d, &s))
            .collect();
        for syl in ss {
            ret.push_str(syl.as_str());
        }
    }
    ret
}

fn syllables(d: &Dict, original: &String) -> Vec<String> {
    if original.len() == 0 {
        return vec![];
    }

    let mut ret: Vec<String> = vec![];
    let maxlen = cmp::min(original.chars().count(), d.max_len()) + 1;

    for l in (1..maxlen).rev() {
        let tmp: String = original.chars().take(l).collect();

        if is_syllable(d, &tmp) {
            ret.push(tmp);
            let skipped: String = original.chars().skip(l).collect();
            let mut rest = syllables(d, &skipped);

            ret.append(&mut rest);

            return ret;
        }
    }

    // if a match wasn't found, add the first char to ret
    // let mut taken: Vec<String> = vec![original.chars().take(1).collect()];
    // ret.append(&mut taken);

    let taken: String = original.chars().take(1).collect();
    ret.push(taken);

    let skipped: String = original.chars().skip(1).collect();
    let mut rest = syllables(d, &skipped);
    ret.append(&mut rest);

    ret
}

// Given a String (expected to be normalized), returns `true` if it is a syllable and
// `false` otherwise.
fn is_syllable(d: &Dict, k: &String) -> bool {
    d.contains_key(k)
}

// Searches for uppercase characters in a String and, if it finds any, turns the whole String to
// uppercase.
fn choose_kana(s: &String) -> String {
    match s.chars().fold(false, |acc, c| acc || c.is_uppercase()) {
        true => s.to_uppercase(),
        false => s.to_string(),
    }
}

fn normalize(s: &String) -> String {
    let k = Kana::init();
    let mut ret: String = s.clone();

    ret = kana::nowidespace(ret.as_str());
    ret = kana::nowideyen(ret.as_str());
    ret = kana::wide2ascii(ret.as_str());

    ret = k.combine(ret.as_str());
    ret = k.half2kana(ret.as_str());

    ret
}

// Converts a String (expected to be a syllable) to kana.
fn convert_syllable(d: &Dict, ow: &String) -> String {
    // <pingveno> Because String impls Borrow<str>
    // `&ow.to_string()` => `ow`
    match d.get(ow) {
        Some(c) => c.clone(),
        None => ow.clone(),
    }
}
<|endoftext|>


<commit_before>pub fn quicksort<T: Ord>(numbers: &mut [T]) {
    let last: usize = numbers.len() - 1;
    q_sort(numbers, 0, last);
}

fn q_sort<T: Ord>(numbers: &mut [T], left: usize, right: usize) {
    let mut pivot_i = left;
    let mut l = left;
    let mut r = right;
    while l < r {
        while (numbers[pivot_i] <= numbers[r]) && (l < r) {
            r = r - 1;
        }
        if l != r {
            numbers.swap(pivot_i, r);
            pivot_i = r;
            l = l + 1;
        }
        while (numbers[l] <= numbers[pivot_i]) && (l < r) {
            l = l + 1;
        }
        if l != r {
            numbers.swap(pivot_i, l);
            pivot_i = l;
            r = r - 1;
        }
    }
    if left < l {
        q_sort(numbers, left, l - 1);
    }
    if right > l {
        q_sort(numbers, l + 1, right);
    }
}

#[cfg(test)]
mod tests {
    use super::*; // 外の定義にアクセスするため use

    #[test]
    fn test_quicksort(){
        let mut numbers = [5, 3, 1, 6, 8, 4, 7, 2];
        quicksort(&mut numbers);
        assert_eq!([1, 2, 3, 4, 5, 6, 7, 8], numbers);
    }
}
<commit_msg>select pivot middle of three values<commit_after>pub fn quicksort<T: Ord>(numbers: &mut [T]) {
    let last: usize = numbers.len() - 1;
    q_sort(numbers, 0, last);
}

fn q_sort<T: Ord>(numbers: &mut [T], left: usize, right: usize) {
    let mut l = left;
    let mut r = right;

    let p1_i = left;
    let p2_i = (left + right) / 2;
    let p3_i = right;
    let mut pivot_i = if numbers[p1_i] < numbers[p2_i] {
            if numbers[p3_i] < numbers[p2_i] {
                if numbers[p1_i] < numbers[p3_i] {
                    p3_i
                }else{
                    p1_i
                }
            }else{
                p2_i
            }
        }else{ // numbers[p2_i] <= numbers[p1_i]
            if numbers[p3_i] < numbers[p1_i] {
                if numbers[p2_i] < numbers[p3_i] {
                    p3_i
                }else{
                    p2_i
                }
            }else{
                p1_i
            }
        };

    while l < r {
        while (numbers[pivot_i] < numbers[r]) && (l < r) {
            r = r - 1;
        }
        if l != r {
            numbers.swap(pivot_i, r);
            pivot_i = r;
        }
        while (numbers[l] < numbers[pivot_i]) && (l < r) {
            l = l + 1;
        }
        if l != r {
            numbers.swap(pivot_i, l);
            pivot_i = l;
        }
    }
    if left < l {
        q_sort(numbers, left, l - 1);
    }
    if right > l {
        q_sort(numbers, l + 1, right);
    }
}

#[cfg(test)]
mod tests {
    use super::*; // 外の定義にアクセスするため use

    #[test]
    fn test_quicksort_number(){
        let mut numbers = [5, 3, 1, 6, 8, 4, 7, 2];
        quicksort(&mut numbers);
        assert_eq!([1, 2, 3, 4, 5, 6, 7, 8], numbers);
    }

    #[test]
    fn test_quicksort_str(){
        let mut strings = ["ccc", "eee", "aaa", "ddd", "bbb", "ggg", "fff"];
        quicksort(&mut strings);
        assert_eq!(["aaa", "bbb", "ccc", "ddd", "eee", "fff", "ggg"], strings);
    }
}
<|endoftext|>


<commit_before>extern crate klee;

#[test]
fn basic_test() {
  let a : i32 = 0;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let a : i32 = 0;
  let b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      panic!("bugger");
    }
  }
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    assert_eq!(b, 0);

    if b == 12 {
      panic!("This path should be unreachable");
    }

    assert_eq!(b, 101);
    assert_eq!(b, 150000);
  }
}
<commit_msg>Update simple.rs<commit_after>extern crate klee;

#[test]
fn basic_test() {
  let a : i32 = 0;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let a : i32 = 0;
  let b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      panic!("bugger");
    }
  }
}

#[test]
fn yant() {
  let a = klee::bool("a");
  let b = klee::int("b");
  let c = if a {
    if b > 50 && b < 100 {
      true
    } else {
      false
    }
  } else {
    true
  }

  assert_eq!(c, false);
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    assert_eq!(b, 0);

    if b == 12 {
      panic!("This path should be unreachable");
    }

    assert_eq!(b, 101);
    assert_eq!(b, 150000);
  }
}
<|endoftext|>


<commit_before>//! Helper crate around git2 with functions for common tasks related to git
//! repositories.

#![deny(missing_docs)]
#![warn(rust_2018_idioms)]

pub mod error;

pub use crate::error::Error;

use std::path::Path;

use git2::{
    self,
    Repository,
};
use walkdir::{
    DirEntry,
    WalkDir,
};

/// Commit current stage with given commit message.
pub fn commit<P: AsRef<Path>>(repo_path: P, message: &str) -> Result<(), Error> {
    let repository = Repository::open(&repo_path).map_err(Error::RepositoryOpen)?;
    let mut index = repository.index().map_err(Error::IndexOpen)?;
    let oid = index.write_tree().map_err(Error::IndexWriteTree)?;

    let mut parent_commit = vec![];
    if let Ok(head) = repository.head() {
        if let Ok(head_commit) = head.peel_to_commit() {
            parent_commit.push(head_commit);
        };
    };

    let tree = repository
        .find_tree(oid)
        .map_err(Error::RepositoryFindTree)?;

    let signature = repository.signature().map_err(Error::RepositorySignature)?;

    repository
        .commit(
            Some("HEAD"),
            &signature,
            &signature,
            message,
            &tree,
            &parent_commit.iter().collect::<Vec<_>>(),
        )
        .map_err(Error::RepositoryCommit)?;

    Ok(())
}

/// Create a new nonbare git repository in the given path.
pub fn init<P: AsRef<Path>>(repo_path: P) -> Result<(), Error> {
    let _ = Repository::init(&repo_path).map_err(Error::RepositoryInit)?;

    Ok(())
}

/// Push commits to upstream. By default this will try to push to origin. If
/// origin does not exist this function will fail with
/// Error::NoOriginConfigured.
pub fn push_to_origin<P: AsRef<Path>>(repo_path: P) -> Result<(), Error> {
    let repository = Repository::open(&repo_path).map_err(Error::RepositoryOpen)?;
    let mut remote = repository
        .find_remote("origin")
        .map_err(|_| Error::NoOriginConfigured)?;

    remote
        .connect(git2::Direction::Push)
        .map_err(Error::RemoteConnect)?;

    remote
        .push(&["refs/heads/master:refs/heads/master"], None)
        .map_err(Error::RemotePush)?;

    Ok(())
}

/// Stage given paths in the repository. Paths have to be relative to the
/// repo_path.
pub fn stage<P: AsRef<Path>, F: AsRef<Path>>(repo_path: P, paths: &[F]) -> Result<(), Error> {
    let repository = Repository::open(&repo_path).map_err(Error::RepositoryOpen)?;
    let mut index = repository.index().map_err(Error::IndexOpen)?;

    paths
        .iter()
        .filter(|path| {
            let fullpath = repo_path.as_ref().join(path);
            fullpath.exists() && fullpath.is_file()
        })
        .map(|path| index.add_path(path.as_ref()).map_err(Error::IndexAddPath))
        .collect::<Result<_, Error>>()?;

    index.write().map_err(Error::IndexWrite)?;

    Ok(())
}

/// Stage all paths in the repository.
pub fn stage_all<P: AsRef<Path>>(repo_path: P) -> Result<(), Error> {
    fn is_not_hidden(entry: &DirEntry) -> bool {
        entry
            .file_name()
            .to_str()
            .map(|s| entry.depth() == 0 || !s.starts_with('.'))
            .unwrap_or(false)
    };

    let paths = WalkDir::new(&repo_path)
        .into_iter()
        .filter_entry(|entry| is_not_hidden(entry))
        .filter_map(|v| v.ok())
        .filter(|entry| entry.path() != repo_path.as_ref())
        .map(|entry| {
            entry
                .into_path()
                .strip_prefix(&repo_path)
                .map(|path| path.to_path_buf())
                .map_err(Error::StripRepositoryPrefix)
        })
        .collect::<Result<Vec<_>, _>>()?;

    stage(repo_path, &paths)?;

    Ok(())
}

/// Return status of the repository.
pub fn status<P: AsRef<Path>>(_repo_path: P) -> Result<(), Error> {
    unimplemented!()
}

#[cfg(test)]
mod test {
    use std::{
        fs,
        path::PathBuf,
    };
    use tempfile::tempdir;

    #[test]
    fn init() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();
    }

    #[test]
    fn stage_nonexistent_file() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let files = vec![PathBuf::from("file_does_not_exist")];
        super::stage(&dir, &files).unwrap();
    }

    #[test]
    fn stage_directory() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let subdir = dir.path().join("subdir");
        std::fs::create_dir_all(&subdir).unwrap();

        let files = vec!["subdir"];
        super::stage(&dir, &files).unwrap();
    }

    #[test]
    fn stage_directory_with_subfile() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let subdir = dir.path().join("subdir");
        std::fs::create_dir_all(&subdir).unwrap();

        let subfile = subdir.join("subfile");
        fs::write(&subfile, "first data").unwrap();

        let files = vec!["subdir", "subdir/subfile"];
        super::stage(&dir, &files).unwrap();
    }

    #[test]
    fn stage_existing_new_file() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let first_file = dir.path().join("first_file");
        fs::write(&first_file, "first data").unwrap();

        let files = vec!["first_file"];
        super::stage(&dir, &files).unwrap();
    }

    #[test]
    fn commit_file_new_repo() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let first_file = dir.path().join("first_file");
        fs::write(&first_file, "first data").unwrap();

        let files = vec!["first_file"];
        super::stage(&dir, &files).unwrap();

        super::commit(&dir, "Added first_file").unwrap();
    }

    #[test]
    fn commit_file_existing_repo() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let first_file = dir.path().join("first_file");
        fs::write(&first_file, "first data").unwrap();

        let files = vec!["first_file"];
        super::stage(&dir, &files).unwrap();

        super::commit(&dir, "Added first_file").unwrap();

        let second_file = dir.path().join("second_file");
        fs::write(&second_file, "second data").unwrap();

        let files = vec!["second_file"];
        super::stage(&dir, &files).unwrap();

        super::commit(&dir, "Added second_file").unwrap();
    }

    #[test]
    fn commit_files_new_repo() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let files = vec!["first_file", "second_file", "third_file"];
        for file in &files {
            let path = dir.path().join(file);
            fs::write(&path, file).unwrap();
        }

        super::stage(&dir, &files).unwrap();
        super::commit(&dir, "Added files").unwrap();
    }

    #[test]
    fn stage_all_files() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let files = vec!["first_file", "second_file", "third_file"];
        for file in &files {
            let path = dir.path().join(file);
            fs::write(&path, file).unwrap();
        }

        super::stage_all(&dir).unwrap();
    }

    #[test]
    fn commit_all_files() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let files = vec!["first_file", "second_file", "third_file"];
        for file in &files {
            let path = dir.path().join(file);
            fs::write(&path, file).unwrap();
        }

        super::stage_all(&dir).unwrap();
        super::commit(&dir, "added all files").unwrap();
    }

    #[test]
    #[should_panic]
    fn status_not_a_repository() {
        let dir = tempdir().unwrap();
        super::status(&dir).unwrap();
    }
}
<commit_msg>Will not ignore dotfiles when staging all files. Instead will filter git folder<commit_after>//! Helper crate around git2 with functions for common tasks related to git
//! repositories.

#![deny(missing_docs)]
#![warn(rust_2018_idioms)]

pub mod error;

pub use crate::error::Error;

use std::path::Path;

use git2::{
    self,
    Repository,
};
use walkdir::{
    DirEntry,
    WalkDir,
};

/// Commit current stage with given commit message.
pub fn commit<P: AsRef<Path>>(repo_path: P, message: &str) -> Result<(), Error> {
    let repository = Repository::open(&repo_path).map_err(Error::RepositoryOpen)?;
    let mut index = repository.index().map_err(Error::IndexOpen)?;
    let oid = index.write_tree().map_err(Error::IndexWriteTree)?;

    let mut parent_commit = vec![];
    if let Ok(head) = repository.head() {
        if let Ok(head_commit) = head.peel_to_commit() {
            parent_commit.push(head_commit);
        };
    };

    let tree = repository
        .find_tree(oid)
        .map_err(Error::RepositoryFindTree)?;

    let signature = repository.signature().map_err(Error::RepositorySignature)?;

    repository
        .commit(
            Some("HEAD"),
            &signature,
            &signature,
            message,
            &tree,
            &parent_commit.iter().collect::<Vec<_>>(),
        )
        .map_err(Error::RepositoryCommit)?;

    Ok(())
}

/// Create a new nonbare git repository in the given path.
pub fn init<P: AsRef<Path>>(repo_path: P) -> Result<(), Error> {
    let _ = Repository::init(&repo_path).map_err(Error::RepositoryInit)?;

    Ok(())
}

/// Push commits to upstream. By default this will try to push to origin. If
/// origin does not exist this function will fail with
/// Error::NoOriginConfigured.
pub fn push_to_origin<P: AsRef<Path>>(repo_path: P) -> Result<(), Error> {
    let repository = Repository::open(&repo_path).map_err(Error::RepositoryOpen)?;
    let mut remote = repository
        .find_remote("origin")
        .map_err(|_| Error::NoOriginConfigured)?;

    remote
        .connect(git2::Direction::Push)
        .map_err(Error::RemoteConnect)?;

    remote
        .push(&["refs/heads/master:refs/heads/master"], None)
        .map_err(Error::RemotePush)?;

    Ok(())
}

/// Stage given paths in the repository. Paths have to be relative to the
/// repo_path.
pub fn stage<P: AsRef<Path>, F: AsRef<Path>>(repo_path: P, paths: &[F]) -> Result<(), Error> {
    let repository = Repository::open(&repo_path).map_err(Error::RepositoryOpen)?;
    let mut index = repository.index().map_err(Error::IndexOpen)?;

    paths
        .iter()
        .filter(|path| {
            let fullpath = repo_path.as_ref().join(path);
            fullpath.exists() && fullpath.is_file()
        })
        .filter(|entry| entry.as_ref() == std::path::PathBuf::from(".git"))
        .map(|path| index.add_path(path.as_ref()).map_err(Error::IndexAddPath))
        .collect::<Result<_, Error>>()?;

    index.write().map_err(Error::IndexWrite)?;

    Ok(())
}

/// Stage all paths in the repository.
pub fn stage_all<P: AsRef<Path>>(repo_path: P) -> Result<(), Error> {
    let paths = WalkDir::new(&repo_path)
        .into_iter()
        .filter_map(|v| v.ok())
        .filter(|entry| entry.path() != repo_path.as_ref())
        .map(|entry| {
            entry
                .into_path()
                .strip_prefix(&repo_path)
                .map(|path| path.to_path_buf())
                .map_err(Error::StripRepositoryPrefix)
        })
        .collect::<Result<Vec<_>, _>>()?;

    stage(repo_path, &paths)?;

    Ok(())
}

/// Return status of the repository.
pub fn status<P: AsRef<Path>>(_repo_path: P) -> Result<(), Error> {
    unimplemented!()
}

#[cfg(test)]
mod test {
    use std::{
        fs,
        path::PathBuf,
    };
    use tempfile::tempdir;

    #[test]
    fn init() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();
    }

    #[test]
    fn stage_nonexistent_file() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let files = vec![PathBuf::from("file_does_not_exist")];
        super::stage(&dir, &files).unwrap();
    }

    #[test]
    fn stage_directory() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let subdir = dir.path().join("subdir");
        std::fs::create_dir_all(&subdir).unwrap();

        let files = vec!["subdir"];
        super::stage(&dir, &files).unwrap();
    }

    #[test]
    fn stage_directory_with_subfile() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let subdir = dir.path().join("subdir");
        std::fs::create_dir_all(&subdir).unwrap();

        let subfile = subdir.join("subfile");
        fs::write(&subfile, "first data").unwrap();

        let files = vec!["subdir", "subdir/subfile"];
        super::stage(&dir, &files).unwrap();
    }

    #[test]
    fn stage_existing_new_file() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let first_file = dir.path().join("first_file");
        fs::write(&first_file, "first data").unwrap();

        let files = vec!["first_file"];
        super::stage(&dir, &files).unwrap();
    }

    #[test]
    fn commit_file_new_repo() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let first_file = dir.path().join("first_file");
        fs::write(&first_file, "first data").unwrap();

        let files = vec!["first_file"];
        super::stage(&dir, &files).unwrap();

        super::commit(&dir, "Added first_file").unwrap();
    }

    #[test]
    fn commit_file_existing_repo() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let first_file = dir.path().join("first_file");
        fs::write(&first_file, "first data").unwrap();

        let files = vec!["first_file"];
        super::stage(&dir, &files).unwrap();

        super::commit(&dir, "Added first_file").unwrap();

        let second_file = dir.path().join("second_file");
        fs::write(&second_file, "second data").unwrap();

        let files = vec!["second_file"];
        super::stage(&dir, &files).unwrap();

        super::commit(&dir, "Added second_file").unwrap();
    }

    #[test]
    fn commit_files_new_repo() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let files = vec!["first_file", "second_file", "third_file"];
        for file in &files {
            let path = dir.path().join(file);
            fs::write(&path, file).unwrap();
        }

        super::stage(&dir, &files).unwrap();
        super::commit(&dir, "Added files").unwrap();
    }

    #[test]
    fn stage_all_files() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let files = vec!["first_file", "second_file", "third_file"];
        for file in &files {
            let path = dir.path().join(file);
            fs::write(&path, file).unwrap();
        }

        super::stage_all(&dir).unwrap();
    }

    #[test]
    fn commit_all_files() {
        let dir = tempdir().unwrap();
        super::init(&dir).unwrap();

        let files = vec!["first_file", "second_file", "third_file"];
        for file in &files {
            let path = dir.path().join(file);
            fs::write(&path, file).unwrap();
        }

        super::stage_all(&dir).unwrap();
        super::commit(&dir, "added all files").unwrap();
    }

    #[test]
    #[should_panic]
    fn status_not_a_repository() {
        let dir = tempdir().unwrap();
        super::status(&dir).unwrap();
    }
}
<|endoftext|>


<commit_before>#[allow(dead_code)]
mod flaker {

    extern crate time;
    extern crate num;
    extern crate byteorder;
    use self::num::BigUint;
    use self::time::Timespec;
    use self::byteorder::{LittleEndian, WriteBytesExt};

    #[derive(Debug)]
    pub enum FlakeError {
        ClockIsRunningBackwards
    }

    pub trait HasFlakes {
        fn update(&mut self) -> Result<(), FlakeError>;
        fn get_id(&mut self) -> BigUint;
    }

    pub struct Flaker {
        identifier: Vec<u8>,
        last_generated_time_ms: u64,
        counter: u32,
    }

    impl Flaker {
        pub fn new_from_identifier(identifier: Vec<u8>) -> Flaker {
            let default_epoch_ts = Timespec::new(0, 0);
            let default_epoch_ms = default_epoch_ts.sec as u64 + (default_epoch_ts.nsec as u64 / 1000 / 1000);

            Flaker::new(identifier, false)
        }

        pub fn new(identifier: Vec<u8>, little_endian: bool) -> Flaker {
            let mut l_identifier = identifier.clone();

            if l_identifier.len() < 6 {
                panic!("Identifier must have a length of 6");
            }

            if !little_endian {
                l_identifier.reverse();
            }

            Flaker { identifier: l_identifier,
                    last_generated_time_ms: Flaker::current_time_in_ms(),
                    counter: 0
                }
        }

        fn current_time_in_ms() -> u64 {
            let now = time::now();
            let now_ts = now.to_timespec();

            // TODO should be `now_ts` minus `epoch`
            // changing this means we should rename this function, too
            now_ts.sec as u64 + (now_ts.nsec as u64 / 1000 / 1000)
        }
    }

    impl HasFlakes for Flaker {
        fn update(&mut self) -> Result<(), FlakeError> {
            let current_time_in_ms = Flaker::current_time_in_ms();

            if self.last_generated_time_ms > current_time_in_ms {
                return Result::Err(FlakeError::ClockIsRunningBackwards);
            }

            if self.last_generated_time_ms < current_time_in_ms {
                self.counter = 0;
            }
            else {
                self.counter += 1;
            }

            self.last_generated_time_ms = current_time_in_ms;

            Ok(())
        }

        // TODO signature needs to be changed to return a result
        fn get_id(&mut self) -> BigUint {
            // TODO check this for OK-ness
            if let Err(e) = self.update() {
                panic!(e);
            }

            // Create a new vec of bytes
            let mut bytes = Vec::new();

            // push the counter into bytes
            // TODO why did I use a u32 for counter if I only use 16 bits of it?
            bytes.push(self.counter as u8);
            bytes.push((self.counter >> 8) as u8);

            // next 6 bytes are the worker id
            for i in &self.identifier {
                bytes.push(*i);
            }

            let mut wtr = vec![];

            wtr.write_u64::<LittleEndian>(self.last_generated_time_ms).unwrap();

            for w in wtr {
                bytes.push(w);
            }

            BigUint::from_bytes_le(&bytes)
        }
    }

    #[test]
    fn ids_change_over_time() {
        let mut f1 = Flaker::new_from_identifier(vec![0, 1, 2, 3, 4, 5]);
        let id1 = f1.get_id();
        std::thread::sleep(Duration::from_millis(50));
        let id2 = f1.get_id();

        println!("{} < {}", id1, id2);

        assert!(id1 < id2);
    }

    #[test]
    fn ids_change_quickly() {
        let mut f1 = Flaker::new_from_identifier(vec![0, 1, 2, 3, 4, 5]);

        let id3 = f1.get_id();
        let id4 = f1.get_id();

        assert!(id3 < id4);
    }
}<commit_msg>Pruning dead code for epochs.<commit_after>#[allow(dead_code)]
mod flaker {

    extern crate time;
    extern crate num;
    extern crate byteorder;
    use self::num::BigUint;
    use self::byteorder::{LittleEndian, WriteBytesExt};

    #[derive(Debug)]
    pub enum FlakeError {
        ClockIsRunningBackwards
    }

    pub trait HasFlakes {
        fn update(&mut self) -> Result<(), FlakeError>;
        fn get_id(&mut self) -> BigUint;
    }

    pub struct Flaker {
        identifier: Vec<u8>,
        last_generated_time_ms: u64,
        counter: u32,
    }

    impl Flaker {
        pub fn new_from_identifier(identifier: Vec<u8>) -> Flaker {
            Flaker::new(identifier, false)
        }

        pub fn new(identifier: Vec<u8>, little_endian: bool) -> Flaker {
            let mut l_identifier = identifier.clone();

            if l_identifier.len() < 6 {
                panic!("Identifier must have a length of 6");
            }

            if !little_endian {
                l_identifier.reverse();
            }

            Flaker { identifier: l_identifier,
                    last_generated_time_ms: Flaker::current_time_in_ms(),
                    counter: 0
                }
        }

        fn current_time_in_ms() -> u64 {
            let now = time::now();
            let now_ts = now.to_timespec();

            // TODO should be `now_ts` minus `epoch`
            // changing this means we should rename this function, too
            now_ts.sec as u64 + (now_ts.nsec as u64 / 1000 / 1000)
        }
    }

    impl HasFlakes for Flaker {
        fn update(&mut self) -> Result<(), FlakeError> {
            let current_time_in_ms = Flaker::current_time_in_ms();

            if self.last_generated_time_ms > current_time_in_ms {
                return Result::Err(FlakeError::ClockIsRunningBackwards);
            }

            if self.last_generated_time_ms < current_time_in_ms {
                self.counter = 0;
            }
            else {
                self.counter += 1;
            }

            self.last_generated_time_ms = current_time_in_ms;

            Ok(())
        }

        // TODO signature needs to be changed to return a result
        fn get_id(&mut self) -> BigUint {
            // TODO check this for OK-ness
            if let Err(e) = self.update() {
                panic!(e);
            }

            // Create a new vec of bytes
            let mut bytes = Vec::new();

            // push the counter into bytes
            // TODO why did I use a u32 for counter if I only use 16 bits of it?
            bytes.push(self.counter as u8);
            bytes.push((self.counter >> 8) as u8);

            // next 6 bytes are the worker id
            for i in &self.identifier {
                bytes.push(*i);
            }

            let mut wtr = vec![];

            wtr.write_u64::<LittleEndian>(self.last_generated_time_ms).unwrap();

            for w in wtr {
                bytes.push(w);
            }

            BigUint::from_bytes_le(&bytes)
        }
    }

    #[test]
    fn ids_change_over_time() {
        let mut f1 = Flaker::new_from_identifier(vec![0, 1, 2, 3, 4, 5]);
        let id1 = f1.get_id();
        std::thread::sleep(Duration::from_millis(50));
        let id2 = f1.get_id();

        println!("{} < {}", id1, id2);

        assert!(id1 < id2);
    }

    #[test]
    fn ids_change_quickly() {
        let mut f1 = Flaker::new_from_identifier(vec![0, 1, 2, 3, 4, 5]);

        let id3 = f1.get_id();
        let id4 = f1.get_id();

        assert!(id3 < id4);
    }
}<|endoftext|>


<commit_before>//!This crate contains parser combinators, roughly based on the Haskell library [parsec](http://hackage.haskell.org/package/parsec).
//!
//!A parser in this library can be described as a function which takes some input and if it
//!is succesful, returns a value together with the remaining input.
//!A parser combinator is a function which takes one or more parsers and returns a new parser.
//!For instance the `many` parser can be used to convert a parser for single digits into one that
//!parses multiple digits.
//!
//!# Examples:
//!
//!```
//! extern crate parser_combinators as parser_combinators;
//! use parser_combinators::{spaces, many1, sep_by, digit, satisfy, Parser, ParserExt, ParseError};
//!
//! fn main() {
//!     let input = "1234, 45,78";
//!     let spaces = spaces();
//!     let integer = spaces.clone()//Parse spaces first and use the with method to only keep the result of the next parser
//!         .with(many1(digit()).map(|string: String| string.parse::<i32>().unwrap()));//parse a string of digits into an i32
//!     //Parse integers separated by commas, skipping whitespace
//!     let mut integer_list = sep_by(integer, spaces.skip(satisfy(|c| c == ',')));
//!
//!     //Call parse with the input to execute the parser
//!     let result: Result<(Vec<i32>, &str), ParseError> = integer_list.parse(input);
//!     match result {
//!         Ok((value, _remaining_input)) => println!("{:?}", value),
//!         Err(err) => println!("{}", err)
//!     }
//! }
//!```
//!
//!If we need a parser that is mutually recursive we can define a free function which internally
//!can in turn be used as a parser (Note that we need to explicitly cast the function, this should
//!not be necessary once changes in rustc to make orphan checking less restrictive gets implemented)
//!
//!`expr` is written fully general here which may not be necessary in a specific implementation
//!The `Stream` trait is predefined to work with array slices, string slices and iterators
//!meaning that in this case it could be defined as
//!`fn expr(input: State<&str>) -> ParseResult<Expr, &str>`
//!
//!```
//! extern crate parser_combinators as parser_combinators;
//! use parser_combinators::{between, spaces, many1, parser, sep_by, satisfy, Parser, ParserExt,
//! ParseResult};
//! use parser_combinators::primitives::{State, Stream};
//!
//! #[derive(Debug, PartialEq)]
//! enum Expr {
//!     Id(String),
//!     Array(Vec<Expr>),
//! }
//! fn expr<I>(input: State<I>) -> ParseResult<Expr, I>
//!     where I: Stream<Item=char> {
//!     let word = many1(satisfy(|c| c.is_alphabetic()));
//!     let comma_list = sep_by(parser(expr), satisfy(|c| c == ','));
//!     let array = between(satisfy(|c| c == '['), satisfy(|c| c == ']'), comma_list);
//!     let spaces = spaces();
//!     spaces.clone().with(
//!             word.map(Expr::Id)
//!             .or(array.map(Expr::Array))
//!         ).parse_state(input)
//! }
//!
//! fn main() {
//!     let result = parser(expr)
//!         .parse("[[], hello, [world]]");
//!     let expr = Expr::Array(vec![
//!           Expr::Array(Vec::new())
//!         , Expr::Id("hello".to_string())
//!         , Expr::Array(vec![Expr::Id("world".to_string())])
//!     ]);
//!     assert_eq!(result, Ok((expr, "")));
//! }
//!```

#[doc(inline)]
pub use primitives::{Parser, ParseResult, ParseError, from_iter};
#[doc(inline)]
pub use char::{
    any_char,
    digit,
    space,
    spaces,
    newline,
    crlf,
    tab,
    upper,
    lower,
    letter,
    alpha_num,
    hex_digit,
    oct_digit,
    string,
    satisfy,
};
#[doc(inline)]
pub use combinator::{
    between,
    chainl1,
    choice,
    many,
    many1,
    optional,
    parser,
    sep_by,
    skip_many,
    skip_many1,
    try,
    value,
    unexpected,
    not_followed_by,

    ParserExt
};

macro_rules! static_fn {
    (($($arg: pat, $arg_ty: ty),*) -> $ret: ty { $body: expr }) => { {
        fn temp($($arg: $arg_ty),*) -> $ret { $body }
        let temp: fn (_) -> _ = temp;
        temp
    } }
}

///Module containing the primitive types which is used to create and compose more advanced parsers
pub mod primitives;
///Module containing all specific parsers
pub mod combinator;
///Module containg parsers specialized on character streams
pub mod char;

#[cfg(test)]
mod tests {
    use super::*;
    use super::primitives::{SourcePosition, State, Stream, Error, Consumed};

    fn integer<'a, I>(input: State<I>) -> ParseResult<i64, I>
        where I: Stream<Item=char> {
        let (s, input) = try!(many1::<String, _>(digit())
            .expected("integer")
            .parse_state(input));
        let mut n = 0;
        for c in s.chars() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        Ok((n, input))
    }

    #[test]
    fn test_integer() {
        let result = parser(integer).parse("123");
        assert_eq!(result, Ok((123i64, "")));
    }
    #[test]
    fn list() {
        let mut p = sep_by(parser(integer), satisfy(|c| c == ','));
        let result = p.parse("123,4,56");
        assert_eq!(result, Ok((vec![123i64, 4, 56], "")));
    }
    #[test]
    fn iterator() {
        let result = parser(integer).parse(from_iter("123".chars()))
            .map(|(i, input)| (i, input.uncons().err()));
        assert_eq!(result, Ok((123i64, Some(()))));
    }
    #[test]
    fn field() {
        let word = many(satisfy(|c| c.is_alphanumeric()));
        let word2 = many(satisfy(|c| c.is_alphanumeric()));
        let spaces = spaces();
        let c_decl = word
            .skip(spaces.clone())
            .skip(satisfy(|c| c == ':'))
            .skip(spaces)
            .and(word2)
            .parse("x: int");
        assert_eq!(c_decl, Ok((("x".to_string(), "int".to_string()), "")));
    }
    #[test]
    fn source_position() {
        let source =
r"
123
";
        let result = spaces()
            .with(parser(integer))
            .skip(spaces())
            .parse_state(State::new(source));
        let state = Consumed::Consumed(State {
            position: SourcePosition { line: 3, column: 1 },
            input: ""
        });
        assert_eq!(result, Ok((123i64, state)));
    }

    #[derive(Debug, PartialEq)]
    enum Expr {
        Id(String),
        Int(i64),
        Array(Vec<Expr>),
        Plus(Box<Expr>, Box<Expr>),
        Times(Box<Expr>, Box<Expr>),
    }
    fn expr(input: State<&str>) -> ParseResult<Expr, &str> {
        let word = many1(satisfy(|c| c.is_alphabetic()))
            .expected("identifier");
        let integer = parser(integer);
        let array = between(satisfy(|c| c == '['), satisfy(|c| c == ']'), sep_by(parser(expr), satisfy(|c| c == ',')))
            .expected("[");
        let paren_expr = between(satisfy(|c| c == '('), satisfy(|c| c == ')'), parser(term))
            .expected("(");
        let spaces = spaces();
        spaces.clone().with(
                word.map(Expr::Id)
                .or(integer.map(Expr::Int))
                .or(array.map(Expr::Array))
                .or(paren_expr)
            ).skip(spaces)
            .parse_state(input)
    }

    #[test]
    fn expression() {
        let result = sep_by(parser(expr), satisfy(|c| c == ','))
            .parse("int, 100, [[], 123]");
        let exprs = vec![
              Expr::Id("int".to_string())
            , Expr::Int(100)
            , Expr::Array(vec![Expr::Array(vec![]), Expr::Int(123)])
        ];
        assert_eq!(result, Ok((exprs, "")));
    }

    #[test]
    fn expression_error() {
        let input =
r"
,123
";
        let result = parser(expr)
            .parse(input);
        let err = ParseError {
            position: SourcePosition { line: 2, column: 1 },
                errors: vec![
                    Error::Unexpected(','),
                    Error::Expected("identifier".into()),
                    Error::Expected("integer".into()),
                    Error::Expected("[".into()),
                    Error::Expected("(".into()),
                ]
        };
        assert_eq!(result, Err(err));
    }

    #[test]
    fn expression_error_message() {
        let input =
r"
,123
";
        let result = parser(expr)
            .parse(input);
        let m = format!("{}", result.unwrap_err());
let expected =
r"Parse error at line: 2, column: 1
Unexpected character ','
Expected 'identifier', 'integer', '[' or '('
";
        assert_eq!(m, expected);
    }

    fn term(input: State<&str>) -> ParseResult<Expr, &str> {

        let mul = satisfy(|c| c == '*')
            .map(|_| { let f: Box<FnMut(_, _) -> _> = Box::new(|l, r| Expr::Times(Box::new(l), Box::new(r))); f });
        let add = satisfy(|c| c == '+')
            .map(|_| { let f: Box<FnMut(_, _) -> _> = Box::new(|l, r| Expr::Plus(Box::new(l), Box::new(r))); f });
        let factor = chainl1(parser(expr), mul);
        chainl1(factor, add)
            .parse_state(input)
    }

    #[test]
    fn operators() {
        let input =
r"
1 * 2 + 3 * test
";
        let (result, _) = parser(term)
            .parse(input)
            .unwrap();

        let e1 = Expr::Times(Box::new(Expr::Int(1)), Box::new(Expr::Int(2)));
        let e2 = Expr::Times(Box::new(Expr::Int(3)), Box::new(Expr::Id("test".to_string())));
        assert_eq!(result, Expr::Plus(Box::new(e1), Box::new(e2)));
    }

    fn follow(input: State<&str>) -> ParseResult<(), &str> {
        match input.clone().uncons_char() {
            Ok((c, _)) => {
                if c.is_alphanumeric() {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                }
                else {
                    Ok(((), Consumed::Empty(input)))
                }
            }
            Err(_) => Ok(((), Consumed::Empty(input)))
        }
    }
    #[test]
    fn error_position() {
        let mut p = string("let").skip(parser(follow)).map(|x| x.to_string())
            .or(many1(satisfy(|c| c.is_digit(10))));
        match p.parse("le123") {
            Ok(_) => assert!(false),
            Err(err) => assert_eq!(err.position, SourcePosition { line: 1, column: 1 })
        }
    }

    #[test]
    fn sep_by_error_consume() {
        let mut p = sep_by::<Vec<_>, _, _>(string("abc"), satisfy(|c| c == ','));
        let err = p.parse("ab,abc")
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(err.position, SourcePosition { line: 1, column: 1});
    }

    #[test]
    fn optional_error_consume() {
        let mut p = optional(string("abc"));
        let err = p.parse("ab")
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(err.position, SourcePosition { line: 1, column: 1});
    }
    #[test]
    fn chainl1_error_consume() {
        let mut p = chainl1(string("abc"), satisfy(|c| c == ',').map(|_| {
            let f: Box<FnMut(_, _) -> _> = Box::new(|l, _| l);
            f
        }));
        assert!(p.parse("abc,ab").is_err());
    }

    #[test]
    fn inner_error_consume() {
        let mut p = many::<Vec<_>, _>(between(string("["), string("]"), satisfy(|c| c.is_digit(10))));
        let result = p.parse("[1][2][]");
        assert!(result.is_err(), format!("{:?}", result));
        let error = result
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(error.position, SourcePosition { line: 1, column: 8 });
    }

    #[test]
    fn infinite_recursion_in_box_parser() {
        let _: Result<(Vec<_>, _), _> = (many(Box::new(digit())))
            .parse("1");
    }

    #[test]
    fn unsized_parser() {
        let mut parser: Box<Parser<Input=&str, Output=char>> = Box::new(digit());
        let borrow_parser = &mut *parser;
        assert_eq!(borrow_parser.parse("1"), Ok(('1', "")));
    }

    #[test]
    fn choice_strings() {
        let mut fruits = [
            try(string("Apple")),
            try(string("Banana")),
            try(string("Cherry")),
            try(string("Date")),
            try(string("Fig")),
            try(string("Grape")),
        ];
        let mut parser = choice(&mut fruits);
        assert_eq!(parser.parse("Apple"), Ok(("Apple", "")));
        assert_eq!(parser.parse("Banana"), Ok(("Banana", "")));
        assert_eq!(parser.parse("Cherry"), Ok(("Cherry", "")));
        assert_eq!(parser.parse("DateABC"), Ok(("Date", "ABC")));
        assert_eq!(parser.parse("Fig123"), Ok(("Fig", "123")));
        assert_eq!(parser.parse("GrapeApple"), Ok(("Grape", "Apple")));
    }
}
<commit_msg>Added a brief overview to the toplevel docs<commit_after>//! This crate contains parser combinators, roughly based on the Haskell library [parsec](http://hackage.haskell.org/package/parsec).
//!
//! A parser in this library can be described as a function which takes some input and if it
//! is succesful, returns a value together with the remaining input.
//! A parser combinator is a function which takes one or more parsers and returns a new parser.
//! For instance the `many` parser can be used to convert a parser for single digits into one that
//! parses multiple digits.
//!
//!# Overview
//!
//! This library is currently split into three modules.
//!
//! * `primitives` contains the `Parser` trait as well as various structs dealing with input
//! streams and errors.
//!
//! * `combinator` contains the before mentioned parser combinators and thus contains the main
//! building blocks for creating any sort of more complex parsers. It consists of free functions as
//! well as a the `ParserExt` trait which provides a few functions which are more naturally used
//! through method calls.
//!
//! * `char` is the last module. It provides parsers specifically working with streams of
//! characters. As a few examples it has parsers for accepting digits, letters or whitespace.
//!
//!
//!# Examples
//!
//!```
//! extern crate parser_combinators as parser_combinators;
//! use parser_combinators::{spaces, many1, sep_by, digit, satisfy, Parser, ParserExt, ParseError};
//!
//! fn main() {
//!     let input = "1234, 45,78";
//!     let spaces = spaces();
//!     let integer = spaces.clone()//Parse spaces first and use the with method to only keep the result of the next parser
//!         .with(many1(digit()).map(|string: String| string.parse::<i32>().unwrap()));//parse a string of digits into an i32
//!     //Parse integers separated by commas, skipping whitespace
//!     let mut integer_list = sep_by(integer, spaces.skip(satisfy(|c| c == ',')));
//!
//!     //Call parse with the input to execute the parser
//!     let result: Result<(Vec<i32>, &str), ParseError> = integer_list.parse(input);
//!     match result {
//!         Ok((value, _remaining_input)) => println!("{:?}", value),
//!         Err(err) => println!("{}", err)
//!     }
//! }
//!```
//!
//! If we need a parser that is mutually recursive we can define a free function which internally
//! can in turn be used as a parser (Note that we need to explicitly cast the function, this should
//! not be necessary once changes in rustc to make orphan checking less restrictive gets implemented)
//!
//! `expr` is written fully general here which may not be necessary in a specific implementation
//! The `Stream` trait is predefined to work with array slices, string slices and iterators
//! meaning that in this case it could be defined as
//! `fn expr(input: State<&str>) -> ParseResult<Expr, &str>`
//!
//!```
//! extern crate parser_combinators as parser_combinators;
//! use parser_combinators::{between, spaces, many1, parser, sep_by, satisfy, Parser, ParserExt,
//! ParseResult};
//! use parser_combinators::primitives::{State, Stream};
//!
//! #[derive(Debug, PartialEq)]
//! enum Expr {
//!     Id(String),
//!     Array(Vec<Expr>),
//! }
//! fn expr<I>(input: State<I>) -> ParseResult<Expr, I>
//!     where I: Stream<Item=char> {
//!     let word = many1(satisfy(|c| c.is_alphabetic()));
//!     let comma_list = sep_by(parser(expr), satisfy(|c| c == ','));
//!     let array = between(satisfy(|c| c == '['), satisfy(|c| c == ']'), comma_list);
//!     let spaces = spaces();
//!     spaces.clone().with(
//!             word.map(Expr::Id)
//!             .or(array.map(Expr::Array))
//!         ).parse_state(input)
//! }
//!
//! fn main() {
//!     let result = parser(expr)
//!         .parse("[[], hello, [world]]");
//!     let expr = Expr::Array(vec![
//!           Expr::Array(Vec::new())
//!         , Expr::Id("hello".to_string())
//!         , Expr::Array(vec![Expr::Id("world".to_string())])
//!     ]);
//!     assert_eq!(result, Ok((expr, "")));
//! }
//!```

#[doc(inline)]
pub use primitives::{Parser, ParseResult, ParseError, from_iter};
#[doc(inline)]
pub use char::{
    any_char,
    digit,
    space,
    spaces,
    newline,
    crlf,
    tab,
    upper,
    lower,
    letter,
    alpha_num,
    hex_digit,
    oct_digit,
    string,
    satisfy,
};
#[doc(inline)]
pub use combinator::{
    between,
    chainl1,
    choice,
    many,
    many1,
    optional,
    parser,
    sep_by,
    skip_many,
    skip_many1,
    try,
    value,
    unexpected,
    not_followed_by,

    ParserExt
};

macro_rules! static_fn {
    (($($arg: pat, $arg_ty: ty),*) -> $ret: ty { $body: expr }) => { {
        fn temp($($arg: $arg_ty),*) -> $ret { $body }
        let temp: fn (_) -> _ = temp;
        temp
    } }
}

///Module containing the primitive types which is used to create and compose more advanced parsers
pub mod primitives;
///Module containing all specific parsers
pub mod combinator;
///Module containg parsers specialized on character streams
pub mod char;

#[cfg(test)]
mod tests {
    use super::*;
    use super::primitives::{SourcePosition, State, Stream, Error, Consumed};

    fn integer<'a, I>(input: State<I>) -> ParseResult<i64, I>
        where I: Stream<Item=char> {
        let (s, input) = try!(many1::<String, _>(digit())
            .expected("integer")
            .parse_state(input));
        let mut n = 0;
        for c in s.chars() {
            n = n * 10 + (c as i64 - '0' as i64);
        }
        Ok((n, input))
    }

    #[test]
    fn test_integer() {
        let result = parser(integer).parse("123");
        assert_eq!(result, Ok((123i64, "")));
    }
    #[test]
    fn list() {
        let mut p = sep_by(parser(integer), satisfy(|c| c == ','));
        let result = p.parse("123,4,56");
        assert_eq!(result, Ok((vec![123i64, 4, 56], "")));
    }
    #[test]
    fn iterator() {
        let result = parser(integer).parse(from_iter("123".chars()))
            .map(|(i, input)| (i, input.uncons().err()));
        assert_eq!(result, Ok((123i64, Some(()))));
    }
    #[test]
    fn field() {
        let word = many(satisfy(|c| c.is_alphanumeric()));
        let word2 = many(satisfy(|c| c.is_alphanumeric()));
        let spaces = spaces();
        let c_decl = word
            .skip(spaces.clone())
            .skip(satisfy(|c| c == ':'))
            .skip(spaces)
            .and(word2)
            .parse("x: int");
        assert_eq!(c_decl, Ok((("x".to_string(), "int".to_string()), "")));
    }
    #[test]
    fn source_position() {
        let source =
r"
123
";
        let result = spaces()
            .with(parser(integer))
            .skip(spaces())
            .parse_state(State::new(source));
        let state = Consumed::Consumed(State {
            position: SourcePosition { line: 3, column: 1 },
            input: ""
        });
        assert_eq!(result, Ok((123i64, state)));
    }

    #[derive(Debug, PartialEq)]
    enum Expr {
        Id(String),
        Int(i64),
        Array(Vec<Expr>),
        Plus(Box<Expr>, Box<Expr>),
        Times(Box<Expr>, Box<Expr>),
    }
    fn expr(input: State<&str>) -> ParseResult<Expr, &str> {
        let word = many1(satisfy(|c| c.is_alphabetic()))
            .expected("identifier");
        let integer = parser(integer);
        let array = between(satisfy(|c| c == '['), satisfy(|c| c == ']'), sep_by(parser(expr), satisfy(|c| c == ',')))
            .expected("[");
        let paren_expr = between(satisfy(|c| c == '('), satisfy(|c| c == ')'), parser(term))
            .expected("(");
        let spaces = spaces();
        spaces.clone().with(
                word.map(Expr::Id)
                .or(integer.map(Expr::Int))
                .or(array.map(Expr::Array))
                .or(paren_expr)
            ).skip(spaces)
            .parse_state(input)
    }

    #[test]
    fn expression() {
        let result = sep_by(parser(expr), satisfy(|c| c == ','))
            .parse("int, 100, [[], 123]");
        let exprs = vec![
              Expr::Id("int".to_string())
            , Expr::Int(100)
            , Expr::Array(vec![Expr::Array(vec![]), Expr::Int(123)])
        ];
        assert_eq!(result, Ok((exprs, "")));
    }

    #[test]
    fn expression_error() {
        let input =
r"
,123
";
        let result = parser(expr)
            .parse(input);
        let err = ParseError {
            position: SourcePosition { line: 2, column: 1 },
                errors: vec![
                    Error::Unexpected(','),
                    Error::Expected("identifier".into()),
                    Error::Expected("integer".into()),
                    Error::Expected("[".into()),
                    Error::Expected("(".into()),
                ]
        };
        assert_eq!(result, Err(err));
    }

    #[test]
    fn expression_error_message() {
        let input =
r"
,123
";
        let result = parser(expr)
            .parse(input);
        let m = format!("{}", result.unwrap_err());
let expected =
r"Parse error at line: 2, column: 1
Unexpected character ','
Expected 'identifier', 'integer', '[' or '('
";
        assert_eq!(m, expected);
    }

    fn term(input: State<&str>) -> ParseResult<Expr, &str> {

        let mul = satisfy(|c| c == '*')
            .map(|_| { let f: Box<FnMut(_, _) -> _> = Box::new(|l, r| Expr::Times(Box::new(l), Box::new(r))); f });
        let add = satisfy(|c| c == '+')
            .map(|_| { let f: Box<FnMut(_, _) -> _> = Box::new(|l, r| Expr::Plus(Box::new(l), Box::new(r))); f });
        let factor = chainl1(parser(expr), mul);
        chainl1(factor, add)
            .parse_state(input)
    }

    #[test]
    fn operators() {
        let input =
r"
1 * 2 + 3 * test
";
        let (result, _) = parser(term)
            .parse(input)
            .unwrap();

        let e1 = Expr::Times(Box::new(Expr::Int(1)), Box::new(Expr::Int(2)));
        let e2 = Expr::Times(Box::new(Expr::Int(3)), Box::new(Expr::Id("test".to_string())));
        assert_eq!(result, Expr::Plus(Box::new(e1), Box::new(e2)));
    }

    fn follow(input: State<&str>) -> ParseResult<(), &str> {
        match input.clone().uncons_char() {
            Ok((c, _)) => {
                if c.is_alphanumeric() {
                    Err(Consumed::Empty(ParseError::new(input.position, Error::Unexpected(c))))
                }
                else {
                    Ok(((), Consumed::Empty(input)))
                }
            }
            Err(_) => Ok(((), Consumed::Empty(input)))
        }
    }
    #[test]
    fn error_position() {
        let mut p = string("let").skip(parser(follow)).map(|x| x.to_string())
            .or(many1(satisfy(|c| c.is_digit(10))));
        match p.parse("le123") {
            Ok(_) => assert!(false),
            Err(err) => assert_eq!(err.position, SourcePosition { line: 1, column: 1 })
        }
    }

    #[test]
    fn sep_by_error_consume() {
        let mut p = sep_by::<Vec<_>, _, _>(string("abc"), satisfy(|c| c == ','));
        let err = p.parse("ab,abc")
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(err.position, SourcePosition { line: 1, column: 1});
    }

    #[test]
    fn optional_error_consume() {
        let mut p = optional(string("abc"));
        let err = p.parse("ab")
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(err.position, SourcePosition { line: 1, column: 1});
    }
    #[test]
    fn chainl1_error_consume() {
        let mut p = chainl1(string("abc"), satisfy(|c| c == ',').map(|_| {
            let f: Box<FnMut(_, _) -> _> = Box::new(|l, _| l);
            f
        }));
        assert!(p.parse("abc,ab").is_err());
    }

    #[test]
    fn inner_error_consume() {
        let mut p = many::<Vec<_>, _>(between(string("["), string("]"), satisfy(|c| c.is_digit(10))));
        let result = p.parse("[1][2][]");
        assert!(result.is_err(), format!("{:?}", result));
        let error = result
            .map(|x| format!("{:?}", x))
            .unwrap_err();
        assert_eq!(error.position, SourcePosition { line: 1, column: 8 });
    }

    #[test]
    fn infinite_recursion_in_box_parser() {
        let _: Result<(Vec<_>, _), _> = (many(Box::new(digit())))
            .parse("1");
    }

    #[test]
    fn unsized_parser() {
        let mut parser: Box<Parser<Input=&str, Output=char>> = Box::new(digit());
        let borrow_parser = &mut *parser;
        assert_eq!(borrow_parser.parse("1"), Ok(('1', "")));
    }

    #[test]
    fn choice_strings() {
        let mut fruits = [
            try(string("Apple")),
            try(string("Banana")),
            try(string("Cherry")),
            try(string("Date")),
            try(string("Fig")),
            try(string("Grape")),
        ];
        let mut parser = choice(&mut fruits);
        assert_eq!(parser.parse("Apple"), Ok(("Apple", "")));
        assert_eq!(parser.parse("Banana"), Ok(("Banana", "")));
        assert_eq!(parser.parse("Cherry"), Ok(("Cherry", "")));
        assert_eq!(parser.parse("DateABC"), Ok(("Date", "ABC")));
        assert_eq!(parser.parse("Fig123"), Ok(("Fig", "123")));
        assert_eq!(parser.parse("GrapeApple"), Ok(("Grape", "Apple")));
    }
}
<|endoftext|>


<commit_before>extern crate git2;
extern crate chrono;

#[macro_use]
extern crate nom;

use git2::{ObjectType, Oid, Repository};
use chrono::{UTC, TimeZone, Datelike};
use nom::{IResult, alpha, digit, newline, rest, space};

use std::fmt;
use std::str;

#[derive(Debug)]
pub enum GitJournalError {
    GitError(git2::Error),
    ParserError,
    CommitMessageLengthError,
}

pub struct GitJournal {
    repo: Repository,
    tags: Vec<(Oid, String)>,
}

impl From<git2::Error> for GitJournalError {
    fn from(err: git2::Error) -> GitJournalError {
        GitJournalError::GitError(err)
    }
}

impl fmt::Display for GitJournalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GitJournalError::GitError(ref err) => write!(f, "Git error: {}", err),
            GitJournalError::ParserError => write!(f, "Parser error."),
            GitJournalError::CommitMessageLengthError => write!(f, "Commit message length too small."),
        }
    }
}

impl GitJournal {
    /// Constructs a new `GitJournal`.
    pub fn new(path: &str) -> Result<GitJournal, GitJournalError> {
        // Open the repository
        let new_repo = try!(Repository::open(path));

        // Get all available tags in some vector of tuples
        let mut new_tags = vec![];
        for name in try!(new_repo.tag_names(None)).iter() {
            let name = try!(name.ok_or(git2::Error::from_str("Could not receive tag name")));
            let obj = try!(new_repo.revparse_single(name));
            if let Ok(tag) = obj.into_tag() {
                let tag_name = try!(tag.name().ok_or(git2::Error::from_str("Could not parse tag name"))).to_owned();
                new_tags.push((tag.target_id(), tag_name));
            }
        }

        // Return the git journal object
        Ok(GitJournal {
            repo: new_repo,
            tags: new_tags,
        })
    }

    /// Parses a revision range for a `GitJournal`.
    pub fn parse_log(&self,
                     revision_range: &str,
                     tag_skip_pattern: &str,
                     max_tags_count: &u32,
                     all: &bool)
                     -> Result<(), GitJournalError> {

        let mut revwalk = try!(self.repo.revwalk());
        revwalk.set_sorting(git2::SORT_TIME);

        // Fill the revwalk with the selected revisions.
        let revspec = try!(self.repo.revparse(&revision_range));
        if revspec.mode().contains(git2::REVPARSE_SINGLE) {
            // A single commit was given
            let from = try!(revspec.from().ok_or(git2::Error::from_str("Could not set revision range start")));
            try!(revwalk.push(from.id()));
        } else {
            // A specific commit range was given
            let from = try!(revspec.from().ok_or(git2::Error::from_str("Could not set revision range start")));
            let to = try!(revspec.to().ok_or(git2::Error::from_str("Could not set revision range end")));
            try!(revwalk.push(to.id()));
            if revspec.mode().contains(git2::REVPARSE_MERGE_BASE) {
                let base = try!(self.repo.merge_base(from.id(), to.id()));
                let o = try!(self.repo.find_object(base, Some(ObjectType::Commit)));
                try!(revwalk.push(o.id()));
            }
            try!(revwalk.hide(from.id()));
        }

        // Iterate over the git objects and collect them in a vector of tuples
        let mut result: Vec<(String, Vec<String>)> = vec![];
        let mut current_entries: Vec<String> = vec![];
        let today = UTC::today();
        let mut parsed_tags: u32 = 1;
        let mut current_tag = format!("Unreleased ({}-{}-{})",
                                      today.year(),
                                      today.month(),
                                      today.day());
        'revloop: for (index, id) in revwalk.enumerate() {
            let oid = try!(id);
            let commit = try!(self.repo.find_commit(oid));
            for tag in self.tags
                .iter()
                .filter(|tag| tag.0.as_bytes() == oid.as_bytes() && !tag.1.contains(tag_skip_pattern)) {

                // Parsing entries of the last tag done
                if !current_entries.is_empty() {
                    result.push((current_tag.clone(), current_entries.clone()));
                    current_entries.clear();
                }

                // If a single revision is given stop at the first seen tag
                if !all && index > 0 && parsed_tags > *max_tags_count {
                    break 'revloop;
                }

                // Format the tag and set as current
                parsed_tags += 1;
                let date = UTC.timestamp(commit.time().seconds(), 0).date();
                current_tag = format!("{} ({}-{}-{})",
                                      tag.1,
                                      date.year(),
                                      date.month(),
                                      date.day());
            }
            // Add the commit message to the current entries of the tag
            let message = try!(commit.message().ok_or(git2::Error::from_str("Could not parse commit message")));
            match self.parse_commit_message(message) {
                Ok(parsed_message) => current_entries.push(parsed_message),
                Err(e) => println!("Skip commit: {}", e),
            }
        }
        // Add the last processed items as well
        if !current_entries.is_empty() {
            result.push((current_tag, current_entries));
        }

        // Print for testing purposes
        for (tag, mut commits) in result {
            println!("\n{}:", tag);
            commits.sort();
            for commit in commits {
                println!("{}", commit);
            }
        }
        Ok(())
    }

    /// Parses a single commit message and returns a changelog ready form
    fn parse_commit_message(&self, message: &str) -> Result<String, GitJournalError> {
        named!(commit_parser<(&str, &str, Vec<&str>)>,
            chain!(
                separated_pair!(alpha, char!('-'), digit)? ~
                space? ~
                cat: map_res!(
                    alt!(
                        tag!("Added") |
                        tag!("Changed") |
                        tag!("Fixed") |
                        tag!("Improved") |
                        tag!("Removed") |
                        tag!("Changed")),
                str::from_utf8) ~
                sum: map_res!(
                    take_until!("\n"),
                    str::from_utf8
                ) ~
                many1!(newline) ~
                items: many0!(
                    map_res!(
                        chain!(
                            tag!("-") ~
                            space? ~
                            r: take_until!("\n") ~
                            many1!(newline),
                            || r
                        ),
                        str::from_utf8
                    )
                ) ~
                rest,
            || (cat, sum, items))
        );
        match commit_parser(message.as_bytes()) {
             IResult::Done(_, parsed) => {
                 return Ok(format!("- [{}]{}{}", parsed.0, parsed.1, parsed.2.join("\n    - ")));
             },
             _ => {
                 println!("Could not parse:\n{}\n", message.lines().nth(0).unwrap());
                 return Err(GitJournalError::ParserError);
             },
        };
    }
}
<commit_msg>Changed nom parsing to match only the summary<commit_after>extern crate git2;
extern crate chrono;

#[macro_use]
extern crate nom;

use git2::{ObjectType, Oid, Repository};
use chrono::{UTC, TimeZone, Datelike};
use nom::{IResult, alpha, digit, newline, rest, space};

use std::fmt;
use std::str;

#[derive(Debug)]
pub enum GitJournalError {
    Git(git2::Error),
    Parser,
    CommitMessageLength,
}

pub struct GitJournal {
    repo: Repository,
    tags: Vec<(Oid, String)>,
}

impl From<git2::Error> for GitJournalError {
    fn from(err: git2::Error) -> GitJournalError {
        GitJournalError::Git(err)
    }
}

impl fmt::Display for GitJournalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GitJournalError::Git(ref err) => write!(f, "Git error: {}", err),
            GitJournalError::Parser => write!(f, "Parser error."),
            GitJournalError::CommitMessageLength => write!(f, "Commit message length too small."),
        }
    }
}

impl GitJournal {
    /// Constructs a new `GitJournal`.
    pub fn new(path: &str) -> Result<GitJournal, GitJournalError> {
        // Open the repository
        let new_repo = try!(Repository::open(path));

        // Get all available tags in some vector of tuples
        let mut new_tags = vec![];
        for name in try!(new_repo.tag_names(None)).iter() {
            let name = try!(name.ok_or(git2::Error::from_str("Could not receive tag name")));
            let obj = try!(new_repo.revparse_single(name));
            if let Ok(tag) = obj.into_tag() {
                let tag_name = try!(tag.name().ok_or(git2::Error::from_str("Could not parse tag name"))).to_owned();
                new_tags.push((tag.target_id(), tag_name));
            }
        }

        // Return the git journal object
        Ok(GitJournal {
            repo: new_repo,
            tags: new_tags,
        })
    }

    /// Parses a revision range for a `GitJournal`.
    pub fn parse_log(&self,
                     revision_range: &str,
                     tag_skip_pattern: &str,
                     max_tags_count: &u32,
                     all: &bool)
                     -> Result<(), GitJournalError> {

        let mut revwalk = try!(self.repo.revwalk());
        revwalk.set_sorting(git2::SORT_TIME);

        // Fill the revwalk with the selected revisions.
        let revspec = try!(self.repo.revparse(&revision_range));
        if revspec.mode().contains(git2::REVPARSE_SINGLE) {
            // A single commit was given
            let from = try!(revspec.from().ok_or(git2::Error::from_str("Could not set revision range start")));
            try!(revwalk.push(from.id()));
        } else {
            // A specific commit range was given
            let from = try!(revspec.from().ok_or(git2::Error::from_str("Could not set revision range start")));
            let to = try!(revspec.to().ok_or(git2::Error::from_str("Could not set revision range end")));
            try!(revwalk.push(to.id()));
            if revspec.mode().contains(git2::REVPARSE_MERGE_BASE) {
                let base = try!(self.repo.merge_base(from.id(), to.id()));
                let o = try!(self.repo.find_object(base, Some(ObjectType::Commit)));
                try!(revwalk.push(o.id()));
            }
            try!(revwalk.hide(from.id()));
        }

        // Iterate over the git objects and collect them in a vector of tuples
        let mut result: Vec<(String, Vec<String>)> = vec![];
        let mut current_entries: Vec<String> = vec![];
        let today = UTC::today();
        let mut parsed_tags: u32 = 1;
        let mut current_tag = format!("Unreleased ({}-{}-{})",
                                      today.year(),
                                      today.month(),
                                      today.day());
        'revloop: for (index, id) in revwalk.enumerate() {
            let oid = try!(id);
            let commit = try!(self.repo.find_commit(oid));
            for tag in self.tags
                .iter()
                .filter(|tag| tag.0.as_bytes() == oid.as_bytes() && !tag.1.contains(tag_skip_pattern)) {

                // Parsing entries of the last tag done
                if !current_entries.is_empty() {
                    result.push((current_tag.clone(), current_entries.clone()));
                    current_entries.clear();
                }

                // If a single revision is given stop at the first seen tag
                if !all && index > 0 && parsed_tags > *max_tags_count {
                    break 'revloop;
                }

                // Format the tag and set as current
                parsed_tags += 1;
                let date = UTC.timestamp(commit.time().seconds(), 0).date();
                current_tag = format!("{} ({}-{}-{})",
                                      tag.1,
                                      date.year(),
                                      date.month(),
                                      date.day());
            }
            // Add the commit message to the current entries of the tag
            let message = try!(commit.message().ok_or(git2::Error::from_str("Could not parse commit message")));
            match self.parse_commit_message(message) {
                Ok(parsed_message) => current_entries.push(parsed_message),
                Err(e) => println!("Skip commit: {}", e),
            }
        }
        // Add the last processed items as well
        if !current_entries.is_empty() {
            result.push((current_tag, current_entries));
        }

        // Print for testing purposes
        for (tag, mut commits) in result {
            println!("\n{}:", tag);
            commits.sort();
            for commit in commits {
                println!("{}", commit);
            }
        }
        Ok(())
    }

    /// Parses a single commit message and returns a changelog ready form
    fn parse_commit_message(&self, message: &str) -> Result<String, GitJournalError> {
        named!(commit_parser<(&str, &str)>,
            chain!(
                separated_pair!(alpha, char!('-'), digit)? ~
                space? ~
                cat: map_res!(
                    alt!(
                        tag!("Added") |
                        tag!("Changed") |
                        tag!("Fixed") |
                        tag!("Improved") |
                        tag!("Removed") |
                        tag!("Changed")),
                str::from_utf8) ~
                sum: map_res!(
                    take_until!("\n"),
                    str::from_utf8
                ) ~
                many1!(newline),
            || (cat, sum))
        );

        let parsed = match commit_parser(message.as_bytes()) {
             IResult::Done(_, parsed) => parsed,
             _ => return Err(GitJournalError::Parser),
        };

        Ok(format!("- [{}]{}", parsed.0, parsed.1))
    }
}
<|endoftext|>