<commit_before>/// An implementation of mux in Rust.
/// See: https://github.com/twitter/finagle/blob/master/finagle-mux/src/main/scala/com/twitter/finagle/mux/package.scala
pub mod mux {

    // TODO
    // It's super lazy and inefficient to be using Vectors here (over, i.e. array slices),
    // but I'm not yet emotionally prepared to manage lifetimes, and ownership and what have you.
    // That'll come next.

    pub struct Path<'t>(&'t [&'t str]);

    pub struct Buf<'t>(&'t [u8]);

    /* TODO

    pub struct Request {
        destination: Path,
        body: Buf,
    }

    pub struct Response {
        body: Buf,
    }
     */

    pub struct Dentry<'t>(&'t str, &'t str);
    pub struct Dtab<'t>(&'t [Dentry<'t>]);

    pub struct Tag(u8, u8, u8);

    pub struct Context<'t>(Buf<'t>, Buf<'t>);
    pub struct Contexts<'t>(&'t [Context<'t>]);

    /*
    pub mod messages {
        pub struct Tdispatch(Tag, Contexts, Path, Dtab, Buf);
        pub struct RdispatchOk(Tag, Contexts, Buf);
        pub struct RdispatchErr(Tag, Contexts, String);
        pub struct RdispatchNack(Tag, Contexts);

        pub struct Tdrain(Tag);
        pub struct Rdrain(Tag);

        pub struct Tping(Tag);
        pub struct Rping(Tag);

        pub struct Tdiscarded(Tag, String);
        pub struct Tlease(u8, u64);

        pub struct Rerr(Tag, String);
    }
     */

    pub enum Message<'t> {
        // Treq(Tag, Option<TraceId>, Buf),
        // RreqOk(Tag, Buf),
        // RreqError(Tag, str),
        // RreqNack(Tag),

        Tdispatch(Tag, Contexts<'t>, Path<'t>, Dtab<'t>, Buf<'t>),
        RdispatchOk(Tag, Contexts<'t>, Buf<'t>),
        RdispatchError(Tag, Contexts<'t>, &'t str),
        RdispatchNack(Tag, Contexts<'t>),

        Tdrain(Tag),
        Rdrain(Tag),

        Tping(Tag),
        Rping(Tag),
        Tdiscarded(Tag, &'t str),
        Tlease(u8, u64),

        Rerr(Tag, &'t str),
    }

    pub enum DecodedMessage<'t> {
        Ok(Message<'t>),
        TooShort(uint),
        UnknownType(i8),
    }

    impl<'t> Message<'t> {
        pub fn decode(bytes: &'t [u8]) -> DecodedMessage {
            if bytes.len() < 4 {
                TooShort(bytes.len())
            } else {
                let tag_slice = bytes.slice(1, 4);
                let tag = Tag(tag_slice[0], tag_slice[1], tag_slice[2]);
                let rest = bytes.slice_from(4);
                match bytes[0] as i8 {
                    // 1 => Some(decodeTreq(tag, rest)),
                    //-1 => Some(decodeRreq(tag, rest)),
                    kind => UnknownType(kind),
                }
            }
        }

        pub fn encode(message: Message) -> Vec<u8> {
            match message {
                Tdispatch(tag, Contexts(contexts), path, dtab, buf) => {
                    let csz = (*contexts).iter().fold(0u, |sum, context| -> uint {
                        let Context(Buf(a), Buf(b)) = *context;
                        sum + a.len() + b.len()
                    });
                    Vec::with_capacity(csz)
                },

                _ => Vec::new(),
            }
        }
    }

    #[cfg(test)]
    mod test {
        use super::{Tag, Contexts, Path, Dtab, Buf, Tdispatch, Message};

        #[test]
        fn encode_tdispatch() {
            let tag = Tag(0,0,1);
            let contexts = Contexts(&[]);

            let p0 = ["foo", "bar", "bah"];
            let path = Path(&p0);

            let dtab = Dtab(&[]);
            let body = Buf(&[]);
            let tdispatch = Tdispatch(tag, contexts, path, dtab, body);
            Message::encode(tdispatch);
        }
    }
}

<commit_msg>test fails everything is good<commit_after>/// An implementation of mux in Rust.
/// See: https://github.com/twitter/finagle/blob/master/finagle-mux/src/main/scala/com/twitter/finagle/mux/package.scala
pub mod mux {

    // TODO these should be moved into other crates...
    pub mod misc {

        /// A simple wrapper type for an array of bytes.
        pub struct Buf<'t>(&'t [u8]);
        static EMPTY_BUF: Buf<'static> = Buf(&[]);
        impl<'t> Buf<'t> {
            pub fn empty() -> Buf<'t> { EMPTY_BUF }

            pub fn from_string(string: &'t str) -> Buf<'t> { Buf(string.as_bytes()) }

            pub fn as_bytes(&'t self) -> &'t [u8] {
                let Buf(bytes) = *self;
                bytes
            }
        }

        pub struct Path<'t>(pub &'t [Buf<'t>]);
        static EMPTY_PATH: Path<'static> = Path(&[]);
        impl<'t> Path<'t> {
            pub fn empty() -> Path<'t> { EMPTY_PATH }

            // TODO
            pub fn read(str: &'t [str]) -> Path<'t> { EMPTY_PATH }
        }

        pub struct Dentry<'t>(pub &'t str, pub &'t str);
        impl<'t> Dentry<'t> {
            pub fn source(&self) -> &'t str {
                let Dentry(source, _) = *self;
                source
            }

            pub fn target(&self) -> &'t str {
                let Dentry(_, target) = *self;
                target
            }
        }

        pub struct Dtab<'t>(pub &'t [Dentry<'t>]);
        static EMPTY_DTAB: Dtab<'static> = Dtab(&[]);
        impl<'t> Dtab<'t> {
            pub fn empty() -> Dtab<'t> { EMPTY_DTAB }

            pub fn dentries(&self) -> &'t [Dentry<'t>] {
                let Dtab(dentries) = *self;
                dentries
            }
        }

        pub struct Context<'t>(pub Buf<'t>, pub Buf<'t>);
        impl<'t> Context<'t> {
            pub fn key(&self) -> Buf<'t> {
                let Context(k, _) = *self;
                k
            }

            pub fn val(&self) -> Buf<'t> {
                let Context(_, v) = *self;
                v
            }
        }

        pub struct Contexts<'t>(pub &'t [Context<'t>]);
        static EMPTY_CONTEXTS: Contexts<'static> = Contexts(&[]);
        impl<'t> Contexts<'t> {
            pub fn empty() -> Contexts<'t> { EMPTY_CONTEXTS }
        }
    }

    /*
     * TODO

    pub struct Request {
        destination: Path,
        body: Buf,
    }

    pub struct Response {
        body: Buf,
    }
     */

    /// Mux protocol support for de/serializing mux messages.
    pub mod proto {
        use super::misc::{Buf, Context, Contexts, Path, Dentry, Dtab};

        pub struct Tag(u8, u8, u8);

        pub enum Message<'t> {
            // Treq(Tag, Option<TraceId>, Buf),
            // RreqOk(Tag, Buf),
            // RreqError(Tag, str),
            // RreqNack(Tag),

            Tdispatch(Tag, Contexts<'t>, Path<'t>, Dtab<'t>, Buf<'t>),
            RdispatchOk(Tag, Contexts<'t>, Buf<'t>),
            RdispatchError(Tag, Contexts<'t>, &'t str),
            RdispatchNack(Tag, Contexts<'t>),

            Tdrain(Tag),
            Rdrain(Tag),

            Tping(Tag),
            Rping(Tag),
            Tdiscarded(Tag, &'t str),
            Tlease(u8, u64),

            Rerr(Tag, &'t str),
        }

        pub enum DecodedMessage<'t> {
            Decoded(Message<'t>),
            TooShort(uint),
            UnknownType(i8),
        }

        impl<'t> Message<'t> {

            /// Decode a slice of bytes as a mux message.
            pub fn decode(bytes: &'t [u8]) -> DecodedMessage {
                if bytes.len() < 4 {
                    TooShort(bytes.len())
                } else {
                    let tag_slice = bytes.slice(1, 4);
                    let tag = Tag(tag_slice[0], tag_slice[1], tag_slice[2]);
                    let rest = bytes.slice_from(4);
                    match bytes[0] as i8 {
                        // 1 => Some(decodeTreq(tag, rest)),
                        //-1 => Some(decodeRreq(tag, rest)),
                        kind => UnknownType(kind),
                    }
                }
            }

            /// Encode a mux message as bytes.
            pub fn encode(&self) -> Vec<u8> {
                match *self {
                    Tdispatch(tag, Contexts(contexts), path, dtab, buf) => {
                        let csz = (*contexts).iter().fold(0u, |sum, context| -> uint {
                            let Context(kbuf, vbuf) = *context;
                            sum + kbuf.as_bytes().len() + vbuf.as_bytes().len()
                        });
                        Vec::with_capacity(csz)
                    },

                    _ => Vec::new(),
                }
            }
        }

        #[cfg(test)]
        mod test {
            use super::super::misc::{Contexts, Path, Dtab, Buf};
            use super::{Tag, Tdispatch, Message, Decoded};

            fn mk_tdispatch<'t>() -> Message<'t> {
                let tag = Tag(0,0,1);
                let contexts = Contexts::empty();
                let path = Path::empty();
                let dtab = Dtab::empty();
                let body = Buf::empty();
                Tdispatch(tag, contexts, path, dtab, body)
            }

            #[test]
            fn tdispatch() {
                let orig = mk_tdispatch();
                let bytes = orig.encode();

                match Message::decode(bytes.as_slice()) {
                    Decoded(Tdispatch(tag, contexts, path, dtab, body)) => (),

                    _ => fail!("could not decode a Tdispatch")
                }
            }
        }
    }
}

<|endoftext|>


<commit_before>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![feature(libc)]
#![feature(os)]
#![feature(core)]
#![feature(std_misc)]
#![feature(collections)]
#![feature(link_llvm_intrinsics)]

extern crate libc;
use std::{mem, ptr};

pub use self::gc_object::{GCHeader, GCRTTI, GCObject, GCObjectRef};

mod macros;
mod constants;
mod gc_object;
mod spaces;
mod stack;

pub struct RCImmixCons {
    spaces: spaces::Spaces,
}

impl RCImmixCons {
    pub fn new() -> RCImmixCons {
        return RCImmixCons {
            spaces: spaces::Spaces::new(),
        };
    }

    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        return self.spaces.allocate(rtti)
                   .or_else(|| { self.collect(true, true);
                                 self.spaces.allocate(rtti) });
    }

    pub fn collect(&mut self, evacuation: bool, cycle_collect: bool) {
        return self.spaces.collect(evacuation, cycle_collect);
    }

    pub fn write_barrier(&mut self, object: GCObjectRef) {
        return self.spaces.write_barrier(object);
    }
}

#[no_mangle]
pub extern fn rcx_create() -> *mut RCImmixCons {
    return unsafe { mem::transmute(Box::new(RCImmixCons::new())) };
}

#[no_mangle]
pub extern fn rcx_allocate(this: *mut RCImmixCons, rtti: *const GCRTTI)
    -> GCObjectRef {
    unsafe { return (*this).allocate(rtti).unwrap_or(ptr::null_mut()); }
}

#[no_mangle]
pub extern fn rcx_collect(this: *mut RCImmixCons, evacuation: bool, cycle_collect: bool) {
    unsafe { (*this).collect(evacuation, cycle_collect) };
}

#[no_mangle]
pub extern fn rcx_write_barrier(this: *mut RCImmixCons, object: GCObjectRef) {
    unsafe { (*this).write_barrier(object) };
}

#[no_mangle]
pub extern fn rcx_destroy(this: *mut RCImmixCons) {
    let _to_be_dropped: Box<RCImmixCons> = unsafe{ mem::transmute(this) };
}
<commit_msg>Add rustdoc for lib.rs<commit_after>// Copyright (c) <2015> <lummax>
// Licensed under MIT (http://opensource.org/licenses/MIT)

#![feature(libc)]
#![feature(os)]
#![feature(core)]
#![feature(std_misc)]
#![feature(collections)]
#![feature(link_llvm_intrinsics)]

extern crate libc;
use std::{mem, ptr};

pub use self::gc_object::{GCHeader, GCRTTI, GCObject, GCObjectRef};

mod macros;
mod constants;
mod gc_object;
mod spaces;
mod stack;

/// The `RCImmixCons` garbage collector.
///
/// This is the conservative reference counting garbage collector with the
/// immix heap partition schema.
///
/// The `allocate()` function will return a pointer to a `GCObject`. Please
/// see the documentation of `GCHeader`, `GCRTTI` and `GCObject` for details.
///
/// Always call `write_barrier()` on an object before modifying its members.
pub struct RCImmixCons {
    /// The different spaces of this garbage collector.
    spaces: spaces::Spaces,
}

impl RCImmixCons {
    /// Create a new `RCImmixCons`.
    pub fn new() -> RCImmixCons {
        return RCImmixCons {
            spaces: spaces::Spaces::new(),
        };
    }

    /// Allocate a new object described by the `rtti` or returns `None`.
    ///
    /// This may trigger a garbage collection if the allocation was not
    /// succussful. If there is still no memory to fullfill the allocation
    /// request return `None`.
    pub fn allocate(&mut self, rtti: *const GCRTTI) -> Option<GCObjectRef> {
        return self.spaces.allocate(rtti)
                   .or_else(|| { self.collect(true, true);
                                 self.spaces.allocate(rtti) });
    }

    /// Trigger a garbage collection.
    ///
    /// This will always run the referece counting collector. If `evacuation`
    /// is set the collectors will try to evacuate. If `cycle_collect` is set
    /// the immix tracing collector will be used.
    pub fn collect(&mut self, evacuation: bool, cycle_collect: bool) {
        return self.spaces.collect(evacuation, cycle_collect);
    }

    /// A write barrier for the given `object`.
    ///
    /// Call this function before modifying the members of this object!
    pub fn write_barrier(&mut self, object: GCObjectRef) {
        return self.spaces.write_barrier(object);
    }
}

#[no_mangle]
pub extern fn rcx_create() -> *mut RCImmixCons {
    return unsafe { mem::transmute(Box::new(RCImmixCons::new())) };
}

#[no_mangle]
pub extern fn rcx_allocate(this: *mut RCImmixCons, rtti: *const GCRTTI)
    -> GCObjectRef {
    unsafe { return (*this).allocate(rtti).unwrap_or(ptr::null_mut()); }
}

#[no_mangle]
pub extern fn rcx_collect(this: *mut RCImmixCons, evacuation: bool, cycle_collect: bool) {
    unsafe { (*this).collect(evacuation, cycle_collect) };
}

#[no_mangle]
pub extern fn rcx_write_barrier(this: *mut RCImmixCons, object: GCObjectRef) {
    unsafe { (*this).write_barrier(object) };
}

#[no_mangle]
pub extern fn rcx_destroy(this: *mut RCImmixCons) {
    let _to_be_dropped: Box<RCImmixCons> = unsafe{ mem::transmute(this) };
}
<|endoftext|>


<commit_before>//! # Configs
//!
//! There isn't just one type of Base64; that would be too simple. You need to choose a character
//! set (standard, URL-safe, etc) and padding suffix (yes/no).
//! The `Config` struct encapsulates this info. There are some common configs included: `STANDARD`,
//! `URL_SAFE`, etc. You can also make your own `Config` if needed.
//!
//! The functions that don't have `config` in the name (e.g. `encode()` and `decode()`) use the
//! `STANDARD` config .
//!
//! The functions that write to a slice (the ones that end in `_slice`) are generally the fastest
//! because they don't need to resize anything. If it fits in your workflow and you care about
//! performance, keep using the same buffer (growing as need be) and use the `_slice` methods for
//! the best performance.
//!
//! # Encoding
//!
//! Several different encoding functions are available to you depending on your desire for
//! convenience vs performance.
//!
//! | Function                | Output                       | Allocates                      |
//! | ----------------------- | ---------------------------- | ------------------------------ |
//! | `encode`                | Returns a new `String`       | Always                         |
//! | `encode_config`         | Returns a new `String`       | Always                         |
//! | `encode_config_buf`     | Appends to provided `String` | Only if `String` needs to grow |
//! | `encode_config_slice`   | Writes to provided `&[u8]`   | Never                          |
//!
//! All of the encoding functions that take a `Config` will pad as per the config.
//!
//! # Decoding
//!
//! Just as for encoding, there are different decoding functions available.
//!
//! | Function                | Output                        | Allocates                      |
//! | ----------------------- | ----------------------------- | ------------------------------ |
//! | `decode`                | Returns a new `Vec<u8>`       | Always                         |
//! | `decode_config`         | Returns a new `Vec<u8>`       | Always                         |
//! | `decode_config_buf`     | Appends to provided `Vec<u8>` | Only if `Vec` needs to grow    |
//! | `decode_config_slice`   | Writes to provided `&[u8]`    | Never                          |
//!
//! Unlike encoding, where all possible input is valid, decoding can fail (see `DecodeError`).
//!
//! Input can be invalid because it has invalid characters or invalid padding. (No padding at all is
//! valid, but excess padding is not.) Whitespace in the input is invalid.
//!
//! # Panics
//!
//! If length calculations result in overflowing `usize`, a panic will result.
//!
//! The `_slice` flavors of encode or decode will panic if the provided output slice is too small,

#![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))]
#![deny(
    missing_docs,
    trivial_casts,
    trivial_numeric_casts,
    unused_extern_crates,
    unused_import_braces,
    unused_results,
    variant_size_differences,
    warnings,
    unsafe_code
)]

#[cfg(test)]
#[macro_use]
extern crate doc_comment;

#[cfg(test)]
doctest!("../README.md");

mod chunked_encoder;
pub mod display;
mod tables;
pub mod write;

mod encode;
pub use crate::encode::{encode, encode_config, encode_config_buf, encode_config_slice};

mod decode;
pub use crate::decode::{
    decode, decode_config, decode_config_buf, decode_config_slice, DecodeError,
};

#[cfg(test)]
mod tests;

/// Available encoding character sets
#[derive(Clone, Copy, Debug)]
pub enum CharacterSet {
    /// The standard character set (uses `+` and `/`).
    ///
    /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-3).
    Standard,
    /// The URL safe character set (uses `-` and `_`).
    ///
    /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-4).
    UrlSafe,
    /// The `crypt(3)` character set (uses `./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`).
    ///
    /// Not standardized, but folk wisdom on the net asserts that this alphabet is what crypt uses.
    Crypt,
}

impl CharacterSet {
    fn encode_table(self) -> &'static [u8; 64] {
        match self {
            CharacterSet::Standard => tables::STANDARD_ENCODE,
            CharacterSet::UrlSafe => tables::URL_SAFE_ENCODE,
            CharacterSet::Crypt => tables::CRYPT_ENCODE,
        }
    }

    fn decode_table(self) -> &'static [u8; 256] {
        match self {
            CharacterSet::Standard => tables::STANDARD_DECODE,
            CharacterSet::UrlSafe => tables::URL_SAFE_DECODE,
            CharacterSet::Crypt => tables::CRYPT_DECODE,
        }
    }
}

/// Contains configuration parameters for base64 encoding
#[derive(Clone, Copy, Debug)]
pub struct Config {
    /// Character set to use
    char_set: CharacterSet,
    /// True to pad output with `=` characters
    pad: bool,
    /// True to ignore excess nonzero bits in the last few symbols, otherwise an error is returned.
    decode_allow_trailing_bits: bool,
}

impl Config {
    /// Create a new `Config`.
    pub fn new(char_set: CharacterSet, pad: bool) -> Config {
        Config {
            char_set,
            pad,
            decode_allow_trailing_bits: false,
        }
    }

    /// Sets whether to pad output with `=` characters.
    pub fn pad(self, pad: bool) -> Config {
        Config { pad, ..self }
    }

    /// Sets whether to emit errors for nonzero trailing bits.
    ///
    /// This is useful when implementing
    /// [forgiving-base64 decode](https://infra.spec.whatwg.org/#forgiving-base64-decode).
    pub fn decode_allow_trailing_bits(self, allow: bool) -> Config {
        Config {
            decode_allow_trailing_bits: allow,
            ..self
        }
    }
}

/// Standard character set with padding.
pub const STANDARD: Config = Config {
    char_set: CharacterSet::Standard,
    pad: true,
    decode_allow_trailing_bits: false,
};

/// Standard character set without padding.
pub const STANDARD_NO_PAD: Config = Config {
    char_set: CharacterSet::Standard,
    pad: false,
    decode_allow_trailing_bits: false,
};

/// URL-safe character set with padding
pub const URL_SAFE: Config = Config {
    char_set: CharacterSet::UrlSafe,
    pad: true,
    decode_allow_trailing_bits: false,
};

/// URL-safe character set without padding
pub const URL_SAFE_NO_PAD: Config = Config {
    char_set: CharacterSet::UrlSafe,
    pad: false,
    decode_allow_trailing_bits: false,
};

/// As per `crypt(3)` requirements
pub const CRYPT: Config = Config {
    char_set: CharacterSet::Crypt,
    pad: false,
    decode_allow_trailing_bits: false,
};
<commit_msg>Forbid, instead of just denying, unsafe. Addresses #100<commit_after>//! # Configs
//!
//! There isn't just one type of Base64; that would be too simple. You need to choose a character
//! set (standard, URL-safe, etc) and padding suffix (yes/no).
//! The `Config` struct encapsulates this info. There are some common configs included: `STANDARD`,
//! `URL_SAFE`, etc. You can also make your own `Config` if needed.
//!
//! The functions that don't have `config` in the name (e.g. `encode()` and `decode()`) use the
//! `STANDARD` config .
//!
//! The functions that write to a slice (the ones that end in `_slice`) are generally the fastest
//! because they don't need to resize anything. If it fits in your workflow and you care about
//! performance, keep using the same buffer (growing as need be) and use the `_slice` methods for
//! the best performance.
//!
//! # Encoding
//!
//! Several different encoding functions are available to you depending on your desire for
//! convenience vs performance.
//!
//! | Function                | Output                       | Allocates                      |
//! | ----------------------- | ---------------------------- | ------------------------------ |
//! | `encode`                | Returns a new `String`       | Always                         |
//! | `encode_config`         | Returns a new `String`       | Always                         |
//! | `encode_config_buf`     | Appends to provided `String` | Only if `String` needs to grow |
//! | `encode_config_slice`   | Writes to provided `&[u8]`   | Never                          |
//!
//! All of the encoding functions that take a `Config` will pad as per the config.
//!
//! # Decoding
//!
//! Just as for encoding, there are different decoding functions available.
//!
//! | Function                | Output                        | Allocates                      |
//! | ----------------------- | ----------------------------- | ------------------------------ |
//! | `decode`                | Returns a new `Vec<u8>`       | Always                         |
//! | `decode_config`         | Returns a new `Vec<u8>`       | Always                         |
//! | `decode_config_buf`     | Appends to provided `Vec<u8>` | Only if `Vec` needs to grow    |
//! | `decode_config_slice`   | Writes to provided `&[u8]`    | Never                          |
//!
//! Unlike encoding, where all possible input is valid, decoding can fail (see `DecodeError`).
//!
//! Input can be invalid because it has invalid characters or invalid padding. (No padding at all is
//! valid, but excess padding is not.) Whitespace in the input is invalid.
//!
//! # Panics
//!
//! If length calculations result in overflowing `usize`, a panic will result.
//!
//! The `_slice` flavors of encode or decode will panic if the provided output slice is too small,

#![cfg_attr(feature = "cargo-clippy", allow(clippy::cast_lossless))]
#![deny(
    missing_docs,
    trivial_casts,
    trivial_numeric_casts,
    unused_extern_crates,
    unused_import_braces,
    unused_results,
    variant_size_differences,
    warnings
)]
#![forbid(unsafe_code)]

#[cfg(test)]
#[macro_use]
extern crate doc_comment;

#[cfg(test)]
doctest!("../README.md");

mod chunked_encoder;
pub mod display;
mod tables;
pub mod write;

mod encode;
pub use crate::encode::{encode, encode_config, encode_config_buf, encode_config_slice};

mod decode;
pub use crate::decode::{
    decode, decode_config, decode_config_buf, decode_config_slice, DecodeError,
};

#[cfg(test)]
mod tests;

/// Available encoding character sets
#[derive(Clone, Copy, Debug)]
pub enum CharacterSet {
    /// The standard character set (uses `+` and `/`).
    ///
    /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-3).
    Standard,
    /// The URL safe character set (uses `-` and `_`).
    ///
    /// See [RFC 3548](https://tools.ietf.org/html/rfc3548#section-4).
    UrlSafe,
    /// The `crypt(3)` character set (uses `./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz`).
    ///
    /// Not standardized, but folk wisdom on the net asserts that this alphabet is what crypt uses.
    Crypt,
}

impl CharacterSet {
    fn encode_table(self) -> &'static [u8; 64] {
        match self {
            CharacterSet::Standard => tables::STANDARD_ENCODE,
            CharacterSet::UrlSafe => tables::URL_SAFE_ENCODE,
            CharacterSet::Crypt => tables::CRYPT_ENCODE,
        }
    }

    fn decode_table(self) -> &'static [u8; 256] {
        match self {
            CharacterSet::Standard => tables::STANDARD_DECODE,
            CharacterSet::UrlSafe => tables::URL_SAFE_DECODE,
            CharacterSet::Crypt => tables::CRYPT_DECODE,
        }
    }
}

/// Contains configuration parameters for base64 encoding
#[derive(Clone, Copy, Debug)]
pub struct Config {
    /// Character set to use
    char_set: CharacterSet,
    /// True to pad output with `=` characters
    pad: bool,
    /// True to ignore excess nonzero bits in the last few symbols, otherwise an error is returned.
    decode_allow_trailing_bits: bool,
}

impl Config {
    /// Create a new `Config`.
    pub fn new(char_set: CharacterSet, pad: bool) -> Config {
        Config {
            char_set,
            pad,
            decode_allow_trailing_bits: false,
        }
    }

    /// Sets whether to pad output with `=` characters.
    pub fn pad(self, pad: bool) -> Config {
        Config { pad, ..self }
    }

    /// Sets whether to emit errors for nonzero trailing bits.
    ///
    /// This is useful when implementing
    /// [forgiving-base64 decode](https://infra.spec.whatwg.org/#forgiving-base64-decode).
    pub fn decode_allow_trailing_bits(self, allow: bool) -> Config {
        Config {
            decode_allow_trailing_bits: allow,
            ..self
        }
    }
}

/// Standard character set with padding.
pub const STANDARD: Config = Config {
    char_set: CharacterSet::Standard,
    pad: true,
    decode_allow_trailing_bits: false,
};

/// Standard character set without padding.
pub const STANDARD_NO_PAD: Config = Config {
    char_set: CharacterSet::Standard,
    pad: false,
    decode_allow_trailing_bits: false,
};

/// URL-safe character set with padding
pub const URL_SAFE: Config = Config {
    char_set: CharacterSet::UrlSafe,
    pad: true,
    decode_allow_trailing_bits: false,
};

/// URL-safe character set without padding
pub const URL_SAFE_NO_PAD: Config = Config {
    char_set: CharacterSet::UrlSafe,
    pad: false,
    decode_allow_trailing_bits: false,
};

/// As per `crypt(3)` requirements
pub const CRYPT: Config = Config {
    char_set: CharacterSet::Crypt,
    pad: false,
    decode_allow_trailing_bits: false,
};
<|endoftext|>


<commit_before>
#![crate_name = "tcc"]
#![crate_type = "lib"]

extern crate time;
use std::default::Default;

pub static EPOCH: i64 = 864000;

pub struct Yearbase(pub Option<u64>);

pub struct Timestamp {
    ts: i64,
}

#[derive(Clone,Default)]
/// Object for formatting TCC timestamps
pub struct Calendar {
    /// Indicates if the sign (+/-) should always be displayed before the year feild.
    year_sign: bool,
    /// Delimiter that comes between the year and month
    delim_month: char,
    /// Delimiter that comes between the month and day
    delim_day: char,
    /// Delimiter that comes between the day and hour
    delim_hour: char,
    /// Delimiter that comes between the hour and minute
    delim_minute: char,
    /// Delimiter that comes between the minute and second
    delim_second: char,
    /// Delimiter that comes between the second and year base designator
    delim_desig: Option<char>,

    /// fields to hold the date mod
    mod_quarter: i64,
    mod_month: i64,
    mod_week: i64,
    mod_day: i64,
    mod_hour: i64,
    mod_minute: i64,
    mod_second: i64,
}

pub struct Time {
    year: i64,
    month: i8,
    day: i8,
    hour: i8,
    minute: i8,
    second: i8,
    nano_second: i32,
    year_base: Yearbase,
}

pub fn timestamp_now() -> Timestamp {
    let utc = time::get_time();
    Timestamp {ts:utc.sec - EPOCH}
}

pub fn timestamp_at(utc : time::Timespec) -> Timestamp {
    Timestamp {ts : utc.sec - EPOCH}
}

fn acceptable_delimiter(delim: char) -> bool {
    match delim {
        ','|'/'|' '|'_'|':'|'.' => true,
                              _ => false,
    }
}

impl Calendar {
    pub fn new() -> Calendar {
        let cal: Calendar = Default::default();
        cal
    }

    pub fn calendar_at(&self, t : Time) -> String {
        // TODO apply formatting
        t.to_string()
    }

    pub fn force_year_sign(&mut self, force : bool) -> Calendar {
        self.year_sign = force;
        (*self).clone()
    }

    pub fn month_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_month = delim;
        }
        (*self).clone()
    }

    pub fn day_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_day = delim;
        }
        (*self).clone()
    }

    pub fn hour_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_hour = delim;
        }
        (*self).clone()
    }

    pub fn minute_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_minute = delim;
        }
        (*self).clone()
    }

    pub fn second_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_second = delim;
        }
        (*self).clone()
    }

    pub fn designator_delimiter(&mut self, delim: Option<char>) -> Calendar {
        self.delim_desig = match delim {
            Some(d) => match acceptable_delimiter(d) {
                true => delim,
                false => self.delim_desig,
            },
            None => delim,
        };
        (*self).clone()
    }

}

impl Time {
    fn new(utc : time::Timespec, year_base : Yearbase) -> Time {
        let mut ts : i64 = utc.sec -864000;
        let year = ts / (60*60*24*28*13);
        ts = ts - year*13*28*24*60*60;
        let mon = ts / (60*60*24*28);
        ts = ts - mon*28*24*60*60;
        let day = ts / (60*60*24);
        ts = ts - day*24*60*60;
        let hour = ts / (60*60);
        ts = ts - hour*60*60;
        let min = ts / 60;
        ts = ts - min*60;

        // TODO factor in leaps based on yearbase

        Time{year: year as i64,
             month: mon as i8,
             day: day as i8,
             hour: hour as i8,
             minute: min as i8,
             second: ts as i8,
             nano_second: utc.nsec as i32,
             year_base: year_base}
    }

    pub fn time_now(year_base : Yearbase) -> Time {
        let utc = time::get_time();
        Time::new(utc,year_base)
    }

    pub fn time_at (utc : time::Timespec, year_base : Yearbase) -> Time {
        Time::new(utc,year_base)
    }
}

impl std::fmt::Display for Timestamp {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f,"TC+{}",self.ts)
    }
}

impl std::fmt::Display for Time {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {

        let Yearbase(ybo) = self.year_base;
        let yb = match ybo {
            Some(value) => format!("TC{}",value),
            None        => "".to_string(),
        };

        let sec = self.second as f64 + 1e-9*(self.nano_second as f64);

        write!(f,"{}.{}.{},{}.{}.{} TC{}",
                 self.year,
                 self.month,
                 self.day,
                 self.hour,
                 self.minute,
                 sec,
                 yb)
    }
}

impl std::fmt::Display for Calendar {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f,"{}",self.calendar_at(Time::time_at(time::Timespec{sec: EPOCH, nsec: 0},Yearbase(None))))
    }
}
<commit_msg>change subtraction to addition of EPOCH<commit_after>
#![crate_name = "tcc"]
#![crate_type = "lib"]

extern crate time;
use std::default::Default;

pub static EPOCH: i64 = 864000;

pub struct Yearbase(pub Option<u64>);

pub struct Timestamp {
    ts: i64,
}

#[derive(Clone,Default)]
/// Object for formatting TCC timestamps
pub struct Calendar {
    /// Indicates if the sign (+/-) should always be displayed before the year feild.
    year_sign: bool,
    /// Delimiter that comes between the year and month
    delim_month: char,
    /// Delimiter that comes between the month and day
    delim_day: char,
    /// Delimiter that comes between the day and hour
    delim_hour: char,
    /// Delimiter that comes between the hour and minute
    delim_minute: char,
    /// Delimiter that comes between the minute and second
    delim_second: char,
    /// Delimiter that comes between the second and year base designator
    delim_desig: Option<char>,

    /// fields to hold the date mod
    mod_quarter: i64,
    mod_month: i64,
    mod_week: i64,
    mod_day: i64,
    mod_hour: i64,
    mod_minute: i64,
    mod_second: i64,
}

pub struct Time {
    year: i64,
    month: i8,
    day: i8,
    hour: i8,
    minute: i8,
    second: i8,
    nano_second: i32,
    year_base: Yearbase,
}

pub fn timestamp_now() -> Timestamp {
    let utc = time::get_time();
    Timestamp {ts:utc.sec + EPOCH}
}

pub fn timestamp_at(utc : time::Timespec) -> Timestamp {
    Timestamp {ts : utc.sec + EPOCH}
}

fn acceptable_delimiter(delim: char) -> bool {
    match delim {
        ','|'/'|' '|'_'|':'|'.' => true,
                              _ => false,
    }
}

impl Calendar {
    pub fn new() -> Calendar {
        let cal: Calendar = Default::default();
        cal
    }

    pub fn calendar_at(&self, t : Time) -> String {
        // TODO apply formatting
        t.to_string()
    }

    pub fn force_year_sign(&mut self, force : bool) -> Calendar {
        self.year_sign = force;
        (*self).clone()
    }

    pub fn month_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_month = delim;
        }
        (*self).clone()
    }

    pub fn day_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_day = delim;
        }
        (*self).clone()
    }

    pub fn hour_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_hour = delim;
        }
        (*self).clone()
    }

    pub fn minute_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_minute = delim;
        }
        (*self).clone()
    }

    pub fn second_delimiter(&mut self, delim: char) -> Calendar {
        if acceptable_delimiter(delim) {
            self.delim_second = delim;
        }
        (*self).clone()
    }

    pub fn designator_delimiter(&mut self, delim: Option<char>) -> Calendar {
        self.delim_desig = match delim {
            Some(d) => match acceptable_delimiter(d) {
                true => delim,
                false => self.delim_desig,
            },
            None => delim,
        };
        (*self).clone()
    }

}

impl Time {
    fn new(utc : time::Timespec, year_base : Yearbase) -> Time {
        let mut ts : i64 = utc.sec -864000;
        let year = ts / (60*60*24*28*13);
        ts = ts - year*13*28*24*60*60;
        let mon = ts / (60*60*24*28);
        ts = ts - mon*28*24*60*60;
        let day = ts / (60*60*24);
        ts = ts - day*24*60*60;
        let hour = ts / (60*60);
        ts = ts - hour*60*60;
        let min = ts / 60;
        ts = ts - min*60;

        // TODO factor in leaps based on yearbase

        Time{year: year as i64,
             month: mon as i8,
             day: day as i8,
             hour: hour as i8,
             minute: min as i8,
             second: ts as i8,
             nano_second: utc.nsec as i32,
             year_base: year_base}
    }

    pub fn time_now(year_base : Yearbase) -> Time {
        let utc = time::get_time();
        Time::new(utc,year_base)
    }

    pub fn time_at (utc : time::Timespec, year_base : Yearbase) -> Time {
        Time::new(utc,year_base)
    }
}

impl std::fmt::Display for Timestamp {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f,"TC+{}",self.ts)
    }
}

impl std::fmt::Display for Time {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {

        let Yearbase(ybo) = self.year_base;
        let yb = match ybo {
            Some(value) => format!("TC{}",value),
            None        => "".to_string(),
        };

        let sec = self.second as f64 + 1e-9*(self.nano_second as f64);

        write!(f,"{}.{}.{},{}.{}.{} TC{}",
                 self.year,
                 self.month,
                 self.day,
                 self.hour,
                 self.minute,
                 sec,
                 yb)
    }
}

impl std::fmt::Display for Calendar {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f,"{}",self.calendar_at(Time::time_at(time::Timespec{sec: EPOCH, nsec: 0},Yearbase(None))))
    }
}
<|endoftext|>


<commit_before>//! Slow and basic handling of primes.

use std::{iter, cmp};
use std::collections::{Bitv, bitv};

/// Stores information about primes.
pub struct Primes {
    // This only stores odd numbers, since even numbers are mostly
    // non-prime.
    v: Bitv
}

/// Iterator over the primes stored in a sieve.
pub struct PrimeIterator<'a> {
    two: bool,
    iter: iter::Enumerate<bitv::Bits<'a>>,
}

impl Primes {
    /// Construct a `Primes` via a sieve, stopping at `upto`.
    pub fn sieve(upto: uint) -> Primes {
        // bad stuff happens for very small bounds.
        let upto = cmp::max(10, upto);

        let mut is_prime = Bitv::with_capacity((upto + 1) / 2, true);
        // 1 isn't prime
        is_prime.set(0, false);

        // multiples of 3 aren't prime (3 is handled separately, so
        // the ticking works properly)
        for i in iter::range_step(4, upto / 2, 3) {
            is_prime.set(i, false);
        }

        let mut check = 2; // 5
        let mut tick = 1; // step by 2 to get 7
        let bound = (upto as f64).sqrt() as uint + 1;
        while check <= bound {
            if is_prime[check] {
                let p = 2 * check + 1;
                for zero in iter::range_step(2 * check * (check + 1), upto / 2, p) {
                    is_prime.set(zero, false);
                }
            }

            check += tick;
            tick = 3 - tick;
        }

        Primes { v: is_prime }
    }

    /// The largest number stored.
    pub fn upper_bound(&self) -> uint {
        self.v.len() * 2 + 1
    }

    /// Check if `n` is prime, failing if `n` is larger than the upper
    /// bound of this Primes instance.
    pub fn is_prime(&self, n: uint) -> bool {
        assert!(n <= self.upper_bound());
        if n % 2 == 0 {
            // 2 is the evenest prime.
            n == 2
        } else {
            self.v[n / 2]
        }
    }

    /// Iterator over the primes stored in this map.
    pub fn primes<'a>(&'a self) -> PrimeIterator<'a> {
        PrimeIterator {
            two: true,
            iter: self.v.iter().enumerate()
        }
    }

    /// Factorise `n` into (prime, exponent) pairs.
    ///
    /// Returns None if `n` cannot be factored, specifically if `n` is
    /// zero, or if `n` has primes factors larger than the largest
    /// stored in this sieve.
    pub fn factor(&self, mut n: uint) -> Option<Vec<(uint, u32)>> {
        if n == 0 { return None }

        let mut ret = Vec::new();

        for p in self.primes() {
            if n == 1 { break }

            let mut count = 0;
            while n % p == 0 {
                n /= p;
                count += 1;
            }
            if count > 0 {
                ret.push((p,count));
            }
        }

        if n == 1 {
            Some(ret)
        } else {
            // large factors! :(
            None
        }
    }
}

/// Returns estimated bounds for π(n), the number of primes less than
/// or equal to `n`.
///
/// That is, if `(a, b) = estimate_prime_pi(n)`, `a ≤ π(n) ≤ b`.
pub fn estimate_prime_pi(n: uint) -> (uint, uint) {
    if n >= 55 {
        let n = n as f64;
        let lg = n.ln();

        ((n / (lg + 2.0)) as uint, (n / (lg - 4.0)) as uint)
    } else {
        static SMALL_PRIME_PI: [uint, .. 55] =
            [0, 0, /*2*/1, /*3*/2, 2, /*5*/3, 3, /*7*/ 4, 4, 4,
             4, /*11*/5, 5, /*13*/ 6, 6, 6, 6, /*17*/ 7, 7, /*19*/8,
             8, 8, 8, /*23*/9, 9, 9, 9, 9, 9, /*29*/10,
             10, /*31*/11, 11, 11, 11, 11, 11, /*37*/12, 12, 12,
             12, /*41*/13, 13, /*43*/14, 14, 14, 14, /*47*/15, 15, 15,
             15, 15, 15, /*53*/16, 16];
        let x = SMALL_PRIME_PI[n];
        (x, x)
    }
}

impl<'a> Iterator<uint> for PrimeIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<uint> {
        if self.two {
            self.two = false;
            Some(2)
        } else {
            for (i, is_prime) in self.iter {
                if is_prime {
                    return Some(2 * i + 1)
                }
            }
            None
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        // very loose bounds, could use prime number theorem etc. to
        // give more precise ones.
        let (_lo, hi) = self.iter.size_hint();
        (self.two as uint, hi)
    }
}

impl<'a> DoubleEndedIterator<uint> for PrimeIterator<'a> {
    #[inline]
    fn next_back(&mut self) -> Option<uint> {
        loop {
            match self.iter.next_back() {
                Some((i, true)) => return Some(2 * i + 1),
                Some((_, false)) => {/* continue */}
                None if self.two => {
                    self.two = false;
                    return Some(2)
                }
                None => return None
            }
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate test;

    use super::{Primes, estimate_prime_pi};
    use self::test::Bencher;

    #[test]
    fn is_prime() {
        let primes = Primes::sieve(1000);
        let tests = [
            (0, false),
            (1, false),
            (2, true),
            (3, true),
            (4, false),
            (5, true),
            (6, false),
            (7, true),
            (8, false),
            (9, false),
            (10, false),
            (11, true)
                ];

        for &(n, expected) in tests.iter() {
            assert_eq!(primes.is_prime(n), expected);
        }
    }

    #[test]
    fn primes_iterator() {
        let primes = Primes::sieve(50);
        let mut expected = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47];

        assert_eq!(primes.primes().collect::<Vec<uint>>().as_slice(),
                   expected.as_slice());

        expected.reverse();
        assert_eq!(primes.primes().rev().collect::<Vec<uint>>().as_slice(),
                   expected.as_slice());
    }

    #[test]
    fn factor() {
        let primes = Primes::sieve(1000);

        let tests: &[(uint, &[(uint, u32)])] = &[
            (1, &[]),
            (2, &[(2u, 1u32)]),
            (3, &[(3, 1)]),
            (4, &[(2, 2)]),
            (5, &[(5, 1)]),
            (6, &[(2, 1), (3, 1)]),
            (7, &[(7, 1)]),
            (8, &[(2, 3)]),
            (9, &[(3, 2)]),
            (10, &[(2, 1), (5, 1)]),
            ];
        for &(n, expected) in tests.iter() {
            assert_eq!(primes.factor(n), Some(expected.to_vec()));
        }
    }

    #[test]
    fn factor_failures() {
        let primes = Primes::sieve(30);

        assert_eq!(primes.factor(0), None);
        assert_eq!(primes.factor(97), None);
    }

    #[test]
    fn prime_pi() {
        let primes = Primes::sieve(1_000_000);

        let mut last = 0;
        for (i, p) in primes.primes().enumerate() {
            for j in range(last, p) {
                let (lo, hi) = estimate_prime_pi(j);
                assert!(lo <= i && i <= hi,
                        "found failing estimate at {}, should satisfy: {} <= {} <= {}",
                        j, lo, i, hi)
            }
            last = p;
        }
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        b.iter(|| Primes::sieve(100))
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        b.iter(|| Primes::sieve(10_000))
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        b.iter(|| Primes::sieve(100_000))
    }

    fn bench_iterate(b: &mut Bencher, upto: uint) {
        let sieve = Primes::sieve(upto);

        b.iter(|| {
            sieve.primes().count()
        })
    }

    #[bench]
    fn iterate_small(b: &mut Bencher) { bench_iterate(b, 100) }
    #[bench]
    fn iterate_large(b: &mut Bencher) { bench_iterate(b, 100_000) }
}
<commit_msg>Use estimate_prime_pi to give a more precise size_hint.<commit_after>//! Slow and basic handling of primes.

use std::{iter, cmp};
use std::collections::{Bitv, bitv};

/// Stores information about primes.
pub struct Primes {
    // This only stores odd numbers, since even numbers are mostly
    // non-prime.
    v: Bitv
}

/// Iterator over the primes stored in a sieve.
pub struct PrimeIterator<'a> {
    two: bool,
    iter: iter::Enumerate<bitv::Bits<'a>>,
}

impl Primes {
    /// Construct a `Primes` via a sieve, stopping at `upto`.
    pub fn sieve(upto: uint) -> Primes {
        // bad stuff happens for very small bounds.
        let upto = cmp::max(10, upto);

        let mut is_prime = Bitv::with_capacity((upto + 1) / 2, true);
        // 1 isn't prime
        is_prime.set(0, false);

        // multiples of 3 aren't prime (3 is handled separately, so
        // the ticking works properly)
        for i in iter::range_step(4, upto / 2, 3) {
            is_prime.set(i, false);
        }

        let mut check = 2; // 5
        let mut tick = 1; // step by 2 to get 7
        let bound = (upto as f64).sqrt() as uint + 1;
        while check <= bound {
            if is_prime[check] {
                let p = 2 * check + 1;
                for zero in iter::range_step(2 * check * (check + 1), upto / 2, p) {
                    is_prime.set(zero, false);
                }
            }

            check += tick;
            tick = 3 - tick;
        }

        Primes { v: is_prime }
    }

    /// The largest number stored.
    pub fn upper_bound(&self) -> uint {
        self.v.len() * 2 + 1
    }

    /// Check if `n` is prime, failing if `n` is larger than the upper
    /// bound of this Primes instance.
    pub fn is_prime(&self, n: uint) -> bool {
        assert!(n <= self.upper_bound());
        if n % 2 == 0 {
            // 2 is the evenest prime.
            n == 2
        } else {
            self.v[n / 2]
        }
    }

    /// Iterator over the primes stored in this map.
    pub fn primes<'a>(&'a self) -> PrimeIterator<'a> {
        PrimeIterator {
            two: true,
            iter: self.v.iter().enumerate()
        }
    }

    /// Factorise `n` into (prime, exponent) pairs.
    ///
    /// Returns None if `n` cannot be factored, specifically if `n` is
    /// zero, or if `n` has primes factors larger than the largest
    /// stored in this sieve.
    pub fn factor(&self, mut n: uint) -> Option<Vec<(uint, u32)>> {
        if n == 0 { return None }

        let mut ret = Vec::new();

        for p in self.primes() {
            if n == 1 { break }

            let mut count = 0;
            while n % p == 0 {
                n /= p;
                count += 1;
            }
            if count > 0 {
                ret.push((p,count));
            }
        }

        if n == 1 {
            Some(ret)
        } else {
            // large factors! :(
            None
        }
    }
}

/// Returns estimated bounds for π(n), the number of primes less than
/// or equal to `n`.
///
/// That is, if `(a, b) = estimate_prime_pi(n)`, `a ≤ π(n) ≤ b`.
pub fn estimate_prime_pi(n: uint) -> (uint, uint) {
    if n >= 55 {
        let n = n as f64;
        let lg = n.ln();

        ((n / (lg + 2.0)) as uint, (n / (lg - 4.0)) as uint)
    } else {
        static SMALL_PRIME_PI: [uint, .. 55] =
            [0, 0, /*2*/1, /*3*/2, 2, /*5*/3, 3, /*7*/ 4, 4, 4,
             4, /*11*/5, 5, /*13*/ 6, 6, 6, 6, /*17*/ 7, 7, /*19*/8,
             8, 8, 8, /*23*/9, 9, 9, 9, 9, 9, /*29*/10,
             10, /*31*/11, 11, 11, 11, 11, 11, /*37*/12, 12, 12,
             12, /*41*/13, 13, /*43*/14, 14, 14, 14, /*47*/15, 15, 15,
             15, 15, 15, /*53*/16, 16];
        let x = SMALL_PRIME_PI[n];
        (x, x)
    }
}

impl<'a> Iterator<uint> for PrimeIterator<'a> {
    #[inline]
    fn next(&mut self) -> Option<uint> {
        if self.two {
            self.two = false;
            Some(2)
        } else {
            for (i, is_prime) in self.iter {
                if is_prime {
                    return Some(2 * i + 1)
                }
            }
            None
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        let mut iter = *self;
        // TODO: this doesn't run in constant time, is it super-bad?
        match (iter.next(), iter.next_back()) {
            (Some(lo), Some(hi)) => {
                let (below_hi, above_hi) = estimate_prime_pi(hi);
                let (below_lo, above_lo) = estimate_prime_pi(lo);

                (below_hi - cmp::min(above_lo, below_hi),
                 Some(above_hi - below_lo + 1))
            }
            (Some(_), None) => (1, Some(1)),
            (None, _) => (0, Some(0))
        }
    }
}

impl<'a> DoubleEndedIterator<uint> for PrimeIterator<'a> {
    #[inline]
    fn next_back(&mut self) -> Option<uint> {
        loop {
            match self.iter.next_back() {
                Some((i, true)) => return Some(2 * i + 1),
                Some((_, false)) => {/* continue */}
                None if self.two => {
                    self.two = false;
                    return Some(2)
                }
                None => return None
            }
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate test;

    use std::iter::range_step;
    use super::{Primes, estimate_prime_pi};
    use self::test::Bencher;

    #[test]
    fn is_prime() {
        let primes = Primes::sieve(1000);
        let tests = [
            (0, false),
            (1, false),
            (2, true),
            (3, true),
            (4, false),
            (5, true),
            (6, false),
            (7, true),
            (8, false),
            (9, false),
            (10, false),
            (11, true)
                ];

        for &(n, expected) in tests.iter() {
            assert_eq!(primes.is_prime(n), expected);
        }
    }

    #[test]
    fn primes_iterator() {
        let primes = Primes::sieve(50);
        let mut expected = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47];

        assert_eq!(primes.primes().collect::<Vec<uint>>().as_slice(),
                   expected.as_slice());

        expected.reverse();
        assert_eq!(primes.primes().rev().collect::<Vec<uint>>().as_slice(),
                   expected.as_slice());
    }

    #[test]
    fn factor() {
        let primes = Primes::sieve(1000);

        let tests: &[(uint, &[(uint, u32)])] = &[
            (1, &[]),
            (2, &[(2u, 1u32)]),
            (3, &[(3, 1)]),
            (4, &[(2, 2)]),
            (5, &[(5, 1)]),
            (6, &[(2, 1), (3, 1)]),
            (7, &[(7, 1)]),
            (8, &[(2, 3)]),
            (9, &[(3, 2)]),
            (10, &[(2, 1), (5, 1)]),
            ];
        for &(n, expected) in tests.iter() {
            assert_eq!(primes.factor(n), Some(expected.to_vec()));
        }
    }

    #[test]
    fn factor_failures() {
        let primes = Primes::sieve(30);

        assert_eq!(primes.factor(0), None);
        assert_eq!(primes.factor(97), None);
    }

    #[test]
    fn size_hint() {
        for i in range_step(0, 1000, 100) {
            let sieve = Primes::sieve(i);

            let mut primes = sieve.primes();

            // check the size hint at each and every iteration
            loop {
                let (lo, hi) = primes.size_hint();

                let mut copy = primes;
                let len = copy.count();

                let next = primes.next();

                assert!(lo <= len && len <= hi.unwrap(),
                        "found failing size_hint for {} to {}, should satisfy: {} <= {} <= {}",
                        next, i, lo, len, hi);

                if next.is_none() {
                    break
                }
            }
        }
    }

    #[test]
    fn prime_pi() {
        let primes = Primes::sieve(1_000_000);

        let mut last = 0;
        for (i, p) in primes.primes().enumerate() {
            for j in range(last, p) {
                let (lo, hi) = estimate_prime_pi(j);
                assert!(lo <= i && i <= hi,
                        "found failing estimate at {}, should satisfy: {} <= {} <= {}",
                        j, lo, i, hi)
            }
            last = p;
        }
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        b.iter(|| Primes::sieve(100))
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        b.iter(|| Primes::sieve(10_000))
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        b.iter(|| Primes::sieve(100_000))
    }

    fn bench_iterate(b: &mut Bencher, upto: uint) {
        let sieve = Primes::sieve(upto);

        b.iter(|| {
            sieve.primes().count()
        })
    }

    #[bench]
    fn iterate_small(b: &mut Bencher) { bench_iterate(b, 100) }
    #[bench]
    fn iterate_large(b: &mut Bencher) { bench_iterate(b, 100_000) }
}
<|endoftext|>


<commit_before>#![no_std]
#![feature(alloc)]
#![feature(asm)]
#![feature(collections)]
#![feature(const_fn)]
#![feature(lang_items)]

#![allow(unknown_lints)]

extern crate alloc;
#[cfg(not(test))]
extern crate allocator;
extern crate spin;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate collections;
#[macro_use]
extern crate log;

mod cli;
pub mod dispatch_table;
pub mod gdt;
pub mod hash_map;
pub mod interrupts;
mod isr;
pub mod runtime;
pub mod vmx;
mod serial_logger;

include!(concat!(env!("OUT_DIR"), "/version.rs"));

#[no_mangle]
pub extern "C" fn rustyvisor_load(_heap: *mut u8, _heap_size: u64, _: *mut u8, _: u64) -> u32 {
    #[cfg(not(test))]
    {
        allocator::init(_heap_size, _heap);
        match serial_logger::init() {
            Ok(()) => {}
            Err(_e) => return 1,
        }
    }

    info!("{}", VERSION);

    #[cfg(feature = "runtime_tests")]
    runtime_tests();

    0
}

#[no_mangle]
pub extern "C" fn rustyvisor_unload() {
     let _ = serial_logger::fini();
}

#[cfg(feature = "runtime_tests")]
fn runtime_tests() {
    info!("Executing runtime tests...");

    gdt::runtime_tests::run();
    interrupts::runtime_tests::run();

    info!("Runtime tests succeeded");
}
<commit_msg>Fix indentation<commit_after>#![no_std]
#![feature(alloc)]
#![feature(asm)]
#![feature(collections)]
#![feature(const_fn)]
#![feature(lang_items)]

#![allow(unknown_lints)]

extern crate alloc;
#[cfg(not(test))]
extern crate allocator;
extern crate spin;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate collections;
#[macro_use]
extern crate log;

mod cli;
pub mod dispatch_table;
pub mod gdt;
pub mod hash_map;
pub mod interrupts;
mod isr;
pub mod runtime;
pub mod vmx;
mod serial_logger;

include!(concat!(env!("OUT_DIR"), "/version.rs"));

#[no_mangle]
pub extern "C" fn rustyvisor_load(_heap: *mut u8, _heap_size: u64, _: *mut u8, _: u64) -> u32 {
    #[cfg(not(test))]
    {
        allocator::init(_heap_size, _heap);
        match serial_logger::init() {
            Ok(()) => {}
            Err(_e) => return 1,
        }
    }

    info!("{}", VERSION);

    #[cfg(feature = "runtime_tests")]
    runtime_tests();

    0
}

#[no_mangle]
pub extern "C" fn rustyvisor_unload() {
    let _ = serial_logger::fini();
}

#[cfg(feature = "runtime_tests")]
fn runtime_tests() {
    info!("Executing runtime tests...");

    gdt::runtime_tests::run();
    interrupts::runtime_tests::run();

    info!("Runtime tests succeeded");
}
<|endoftext|>


<commit_before>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]

extern crate libc;
#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate kernel32;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    unsafe {
        let mut sysinfo: winapi::SYSTEM_INFO = ::std::mem::uninitialized();
        kernel32::GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(
    any(
        target_os = "freebsd",
        target_os = "dragonfly",
        target_os = "bitrig",
        target_os = "openbsd",
        target_os = "netbsd"
    )
)]
fn get_num_cpus() -> usize {
    use libc::{c_int, c_uint};
    use libc::funcs::bsd44::sysctl;
    use std::ptr;

    //XXX: uplift to libc?
    const CTL_HW: c_int = 6;
    const HW_AVAILCPU: c_int = 25;
    const HW_NCPU: c_int = 3;

    let mut cpus: c_uint = 0;
    let mut CPUS_SIZE = ::std::mem::size_of::<c_uint>();
    let mut mib: [c_int; 4] = [CTL_HW, HW_AVAILCPU, 0, 0];

    unsafe {
        sysctl(mib.as_mut_ptr(), 2,
               &mut cpus as *mut _ as *mut _, &mut CPUS_SIZE as *mut _ as *mut _,
               ptr::null_mut(), 0);
    }

    if cpus < 1 {
        mib[1] = HW_NCPU;
        unsafe {
            sysctl(mib.as_mut_ptr(), 2,
                   &mut cpus as *mut _ as *mut _, &mut CPUS_SIZE as *mut _ as *mut _,
                   ptr::null_mut(), 0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }

    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios"
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}

#[cfg(target_os= "android")]
fn get_num_cpus() -> usize {
    //to-do: replace with libc::_SC_NPROCESSORS_ONLN once available
    unsafe {
        libc::sysconf(97) as usize
    }
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
}
<commit_msg>Fixes compilation on *BSD for recent version of libc<commit_after>//! Replaces the deprecated functionality of std::os::num_cpus.
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![allow(non_snake_case)]

extern crate libc;
#[cfg(windows)]
extern crate winapi;
#[cfg(windows)]
extern crate kernel32;

/// Returns the number of CPUs of the current machine.
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    unsafe {
        let mut sysinfo: winapi::SYSTEM_INFO = ::std::mem::uninitialized();
        kernel32::GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(
    any(
        target_os = "freebsd",
        target_os = "dragonfly",
        target_os = "bitrig",
        target_os = "openbsd",
        target_os = "netbsd"
    )
)]
fn get_num_cpus() -> usize {
    use libc::{c_int, c_uint};
    use libc::sysctl;
    use std::ptr;

    //XXX: uplift to libc?
    const CTL_HW: c_int = 6;
    const HW_AVAILCPU: c_int = 25;
    const HW_NCPU: c_int = 3;

    let mut cpus: c_uint = 0;
    let mut CPUS_SIZE = ::std::mem::size_of::<c_uint>();
    let mut mib: [c_int; 4] = [CTL_HW, HW_AVAILCPU, 0, 0];

    unsafe {
        sysctl(mib.as_mut_ptr(), 2,
               &mut cpus as *mut _ as *mut _, &mut CPUS_SIZE as *mut _ as *mut _,
               ptr::null_mut(), 0);
    }

    if cpus < 1 {
        mib[1] = HW_NCPU;
        unsafe {
            sysctl(mib.as_mut_ptr(), 2,
                   &mut cpus as *mut _ as *mut _, &mut CPUS_SIZE as *mut _ as *mut _,
                   ptr::null_mut(), 0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }

    cpus as usize
}

#[cfg(
    any(
        target_os = "linux",
        target_os = "nacl",
        target_os = "macos",
        target_os = "ios"
    )
)]
fn get_num_cpus() -> usize {
    unsafe {
        libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as usize
    }
}

#[cfg(target_os= "android")]
fn get_num_cpus() -> usize {
    //to-do: replace with libc::_SC_NPROCESSORS_ONLN once available
    unsafe {
        libc::sysconf(97) as usize
    }
}

#[test]
fn lower_bound() {
    assert!(get() > 0);
}

#[test]
fn upper_bound() {
    assert!(get() < 236_451);
}
<|endoftext|>


<commit_before>//! A small library which provides convenient, non-panicking error handling for small CLI scripts.
#![deny(missing_docs)]
#![deny(unused)]

use std::borrow::Cow;
use std::env;
use std::error::Error as StdError;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::{self, Write};
use std::path::Path;
use std::process;

/// A minimalist error type to use in CLI scripts: it wraps an arbitrary cause which implements
/// `std::error::Error` and a description for the `Display` implementation.
#[derive(Debug)]
pub struct Error {
    description: Option<Cow<'static, str>>,
    cause: Option<Box<StdError>>,
}

impl Error {
    /// Creates a new `Error` with a description and a cause.
    ///
    /// In most cases you'll want to use the convenient `DescribeErr` trait or the `ctry`
    /// and `ccheck` macros.
    ///
    /// With a `&'static str`:
    ///
    /// ```
    ///    # use clierr::Error;
    ///    # let some_error = Error::with_description("x");
    /// Error::new("oh no!", some_error);
    /// ```
    ///
    /// With a `String`:
    ///
    /// ```
    ///    # use clierr::Error;
    ///    # let some_error = Error::with_description("x");
    ///    # let filename = "file.txt";
    /// Error::new(format!("should not have tried to open '{}'!", filename), some_error);
    /// ```
    pub fn new<S, E>(description: S, cause: E) -> Error
        where S: Into<Cow<'static, str>>,
              E: StdError + 'static
    {
        Error {
            description: Some(description.into()),
            cause: Some(Box::new(cause)),
        }
    }

    /// Creates a new error with a descrption but no cause. Useful for validation specific
    /// errors where there's no underlying error (e.g. CLI timeout argument must be
    /// greater than zero).
    pub fn with_description<S: Into<Cow<'static, str>>>(description: S) -> Error {
        Error {
            description: Some(description.into()),
            cause: None,
        }
    }

    /// Creates a new error with a cause, but no description. The `Display` implementation
    /// forwards to that of `cause` in this case.
    ///
    /// In most cases you'll want to use the convenient `DescribeErr` trait or the `ctry`
    /// and `ccheck` macros instead.
    pub fn caused_by<E: StdError + 'static>(cause: E) -> Error {
        Error {
            description: None,
            cause: Some(Box::new(cause)),
        }
    }
}

/// A trait which enables adding a description to any `Result` by wrapping its error type in an
/// `Error`
///
/// An implementation is provided for `Result<S, E: std::errror::Error` and it's not really meant to
/// be implemented for anything else (unless you're using some kind of custom `Result` type).
pub trait DescribeErr: Sized {
    /// The result of describing the `Result`'s error.
    type Described;

    /// Wraps the error contained by `Self` in an `Error` with the given description.
    fn describe_err<D>(self, description: D) -> Self::Described where D: Into<Cow<'static, str>>;

    /// Same as `describe_err`, but defer the construction of the description until it's actually
    /// needed (i.e. only in the error case for a `Result`).
    fn describe_err_with<F, D>(self, with: F) -> Self::Described
        where F: FnOnce() -> D,
              D: Into<Cow<'static, str>>;
}

impl<S, E: StdError + 'static> DescribeErr for Result<S, E> {
    type Described = Result<S, Error>;

    fn describe_err<D: Into<Cow<'static, str>>>(self, description: D) -> Result<S, Error> {
        self.map_err(|cause| Error::new(description, cause))
    }

    fn describe_err_with<F, D>(self, with: F) -> Result<S, Error>
        where F: FnOnce() -> D,
              D: Into<Cow<'static, str>>
    {
        self.map_err(|cause| Error::new(with(), cause))
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        if let Some(description) = self.description.as_ref() {
            write!(fmt, "{}", description)
        } else if let Some(cause) = self.cause() {
            write!(fmt, "{}", cause)
        } else {
            write!(fmt, "<unknown error>")
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        if let Some(description) = self.description.as_ref() {
            description
        } else if let Some(cause) = self.cause() {
            cause.description()
        } else {
            ""
        }
    }

    fn cause(&self) -> Option<&StdError> {
        self.cause.as_ref().map(|e| &**e)
    }
}

const MAX_CAUSE_RECURSION: usize = 32;

fn print_cause(prefix: &str, error: &StdError, max_recursion: usize) {
    if max_recursion == 0 {
        // We've recursed too many times; don't want to overflow so bail here. Ignore any errors.
        let _ = writeln!(io::stderr(), "{}:    ...", prefix);
    } else if let Some(cause) = error.cause() {
        // Display the current cause, and recurse if (a) the current cause is caused by another
        // error and (b) the write to stderr didn't fail the first time.
        if writeln!(io::stderr(), "{}:    caused by: {}", prefix, cause).is_err() {
            return;
        }

        // Hopefully tail recursive, but not a big deal if not.
        print_cause(prefix, cause, max_recursion - 1);
    }
}

fn run_impl<E, F>(main: F) -> i32
    where F: FnOnce() -> Result<(), E>,
          E: Into<Box<StdError>>
{
    if let Err(error) = main() {
        let error = error.into();
        let argv0 = env::args().next();
        let program_name = argv0.as_ref()
                                .and_then(|s| Path::new(s).file_name())
                                .map(|os| os.to_string_lossy());
        let prefix = program_name.as_ref().map(|s| &**s).unwrap_or("<unknown>");

        if writeln!(io::stderr(), "{}: {}", prefix, error).is_ok() {
            print_cause(prefix, &*error, MAX_CAUSE_RECURSION);
        }
        1
    } else {
        0
    }
}

/// Runs a `Result`-returning function and exits the process with 0 if successful.
///
/// If `main` returns an error, it displays it (and all its causes recursively) to `stderr` and
/// exists the process with 1.
pub fn run_and_exit<E, F>(main: F) -> !
    where F: FnOnce() -> Result<(), E>,
          E: Into<Box<StdError>>
{
    process::exit(run_impl(main))
}

/// Like `try!`, but in the error case the error is wrapped in an `Error` with a given description
/// (which can be specified using `format_args!` syntax).
///
/// Example:
///
/// ```norust
///     ctry!(File::open(filename), "could not open output file {}", filename)
/// ```
///
/// Note: If you don't like macros, the `DescribeErr` trait already cuts on a lot of verbosity.
#[macro_export]
macro_rules! ctry {
    ($e:expr, $fmt:expr) => {{
        use $crate::DescribeErr;
        try!($e.describe_err_with(|| $fmt))
    }};
    ($e:expr, $fmt:expr, $($arg:tt)*) => {{
        use $crate::DescribeErr;
        try!($e.describe_err_with(|| format!($fmt, $($arg)*)))
    }}
}

/// Like `assert!` but instead of panicking it early-returns an `Error` with a given description
/// (which can be specified using `format_args!` syntax).
///
/// Example:
///
/// ```norust
///     ccheck!(value(key) == 42, "value of {} was not 42 ({})", key, value(key))
/// ```
///
/// Note: If you don't like macros, the `DescribeErr` trait already cuts on a lot of verbosity.
#[macro_export]
macro_rules! ccheck {
    ($e:expr, $fmt:expr) => {{
        use $crate::Error;
        if !($e) {
            return Err(Error::with_description($fmt).into());
        }
    }};
    ($e:expr, $fmt:expr, $($arg:tt)*) => {{
        use $crate::Error;
        if !($e) {
            return Err(Error::with_description(format!($fmt, $($arg)*)).into());
        }
    }}
}

#[cfg(test)]
mod test {
    use super::{Error, DescribeErr, run_impl};
    use std::error::Error as StdError;
    use std::cell::Cell;

    fn ok() -> Result<(), Error> {
        Ok(())
    }

    fn err() -> Result<(), Error> {
        Err(Error::with_description("test"))
    }

    fn err_box() -> Result<(), Box<StdError>> {
        Err(Box::new(Error::with_description("test")))
    }

    #[test]
    fn error() {
        let with_static = Error::new("test", Error::with_description("cause"));
        let with_owned = Error::new("test2".to_owned(),
                                    Error::caused_by(Error::with_description("cause2")));

        assert_eq!(&format!("{}", with_static), "test");
        assert_eq!(&format!("{}", with_owned), "test2");
        assert_eq!(with_static.description(), "test");
        assert_eq!(with_owned.description(), "test2");

        assert_eq!(with_static.cause().map(|c| c.description()), Some("cause"));
        assert!(with_static.cause().unwrap().cause().is_none());

        assert_eq!(with_owned.cause().map(|c| c.description()), Some("cause2"));
        assert!(with_owned.cause().unwrap().cause().unwrap().cause().is_none());
        assert_eq!(with_owned.cause().map(|c| format!("{}", c)),
                   Some("cause2".to_owned()));
        assert_eq!(with_owned.cause().and_then(|c| c.cause()).map(|c| c.description()),
                   Some("cause2"));
    }

    #[test]
    fn describe_err() {
        let counter = Cell::new(0);
        let inc = || {
            counter.set(counter.get() + 1);
            "wrapper"
        };

        assert!(ok().describe_err("wrapper").is_ok());
        assert!(ok().describe_err_with(&inc).is_ok());
        assert_eq!(counter.get(), 0);

        let described = err().describe_err("wrapper");
        match described {
            Err(error) => {
                assert_eq!(error.description(), "wrapper");
                assert_eq!(error.cause().map(|c| c.description()), Some("test"));
            }
            Ok(()) => panic!("failed: {:?}", described),
        }

        let described = err().describe_err_with(&inc);
        assert_eq!(counter.get(), 1);
        match described {
            Err(error) => {
                assert_eq!(error.description(), "wrapper");
                assert_eq!(error.cause().map(|c| c.description()), Some("test"));
            }
            Ok(()) => panic!("failed: {:?}", described),
        }
    }

    #[test]
    fn ctry_ok() {
        fn foo() -> Result<u32, Error> {
            let _ = ctry!(ok(), "oh no!");
            Ok(42)
        }
        assert_eq!(foo().unwrap(), 42);
    }

    #[test]
    fn ctry_err() {
        fn foo() -> Result<u32, Error> {
            let _ = ctry!(err(), "help {}", "us");
            Ok(42)
        }
        match foo() {
            Err(e) => {
                assert_eq!(e.description(), "help us");
                assert_eq!(e.cause().unwrap().description(), "test");
            }
            Ok(x) => panic!("failed: {:?}", x),
        }
    }

    #[test]
    fn ccheck_ok() {
        fn foo() -> Result<u32, Error> {
            ccheck!(true, "oh no!");
            Ok(42)
        }
        assert_eq!(foo().unwrap(), 42);
    }

    #[test]
    fn ccheck_err() {
        fn foo() -> Result<u32, Error> {
            ccheck!(false, "help {}", "us");
            Ok(42)
        }
        match foo() {
            Err(e) => {
                assert_eq!(e.description(), "help us");
                assert!(e.cause().is_none());
            }
            Ok(x) => panic!("failed: {:?}", x),
        }
    }

    #[test]
    fn run_returns_zero_for_success() {
        assert_eq!(run_impl(ok), 0);
    }

    #[test]
    fn run_returns_one_for_error() {
        assert_eq!(run_impl(err), 1);
    }

    #[test]
    fn run_returns_one_for_error_box() {
        assert_eq!(run_impl(err_box), 1);
    }
}
<commit_msg>Moved cause printing to Error type.<commit_after>//! A small library which provides convenient, non-panicking error handling for small CLI scripts.
#![deny(missing_docs)]
#![deny(unused)]

use std::borrow::Cow;
use std::env;
use std::error::Error as StdError;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::{self, Write};
use std::path::Path;
use std::process;

/// A minimalist error type to use in CLI scripts: it wraps an arbitrary cause which implements
/// `std::error::Error` and a description for the `Display` implementation.
#[derive(Debug)]
pub struct Error {
    description: Option<Cow<'static, str>>,
    cause: Option<Box<StdError>>,
}

impl Error {
    /// Creates a new `Error` with a description and a cause.
    ///
    /// In most cases you'll want to use the convenient `DescribeErr` trait or the `ctry`
    /// and `ccheck` macros.
    ///
    /// With a `&'static str`:
    ///
    /// ```
    ///    # use clierr::Error;
    ///    # let some_error = Error::with_description("x");
    /// Error::new("oh no!", some_error);
    /// ```
    ///
    /// With a `String`:
    ///
    /// ```
    ///    # use clierr::Error;
    ///    # let some_error = Error::with_description("x");
    ///    # let filename = "file.txt";
    /// Error::new(format!("should not have tried to open '{}'!", filename), some_error);
    /// ```
    pub fn new<S, E>(description: S, cause: E) -> Error
        where S: Into<Cow<'static, str>>,
              E: StdError + 'static
    {
        Error {
            description: Some(description.into()),
            cause: Some(Box::new(cause)),
        }
    }

    /// Creates a new error with a descrption but no cause. Useful for validation specific
    /// errors where there's no underlying error (e.g. CLI timeout argument must be
    /// greater than zero).
    pub fn with_description<S: Into<Cow<'static, str>>>(description: S) -> Error {
        Error {
            description: Some(description.into()),
            cause: None,
        }
    }

    /// Creates a new error with a cause, but no description. The `Display` implementation
    /// forwards to that of `cause` in this case.
    ///
    /// In most cases you'll want to use the convenient `DescribeErr` trait or the `ctry`
    /// and `ccheck` macros instead.
    pub fn caused_by<E: StdError + 'static>(cause: E) -> Error {
        Error {
            description: None,
            cause: Some(Box::new(cause)),
        }
    }
}

/// A trait which enables adding a description to any `Result` by wrapping its error type in an
/// `Error`
///
/// An implementation is provided for `Result<S, E: std::errror::Error` and it's not really meant to
/// be implemented for anything else (unless you're using some kind of custom `Result` type).
pub trait DescribeErr: Sized {
    /// The result of describing the `Result`'s error.
    type Described;

    /// Wraps the error contained by `Self` in an `Error` with the given description.
    fn describe_err<D>(self, description: D) -> Self::Described where D: Into<Cow<'static, str>>;

    /// Same as `describe_err`, but defer the construction of the description until it's actually
    /// needed (i.e. only in the error case for a `Result`).
    fn describe_err_with<F, D>(self, with: F) -> Self::Described
        where F: FnOnce() -> D,
              D: Into<Cow<'static, str>>;
}

impl<S, E: StdError + 'static> DescribeErr for Result<S, E> {
    type Described = Result<S, Error>;

    fn describe_err<D: Into<Cow<'static, str>>>(self, description: D) -> Result<S, Error> {
        self.map_err(|cause| Error::new(description, cause))
    }

    fn describe_err_with<F, D>(self, with: F) -> Result<S, Error>
        where F: FnOnce() -> D,
              D: Into<Cow<'static, str>>
    {
        self.map_err(|cause| Error::new(with(), cause))
    }
}

impl Display for Error {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        if let Some(description) = self.description.as_ref() {
            write!(fmt, "{}", description).and_then(|_| {
                if let Some(cause) = self.cause() {
                    write!(fmt, "\n    caused by: {}", cause)
                } else {
                    Ok(())
                }
            })
        } else if let Some(cause) = self.cause() {
            write!(fmt, "{}", cause)
        } else {
            write!(fmt, "<unknown error>")
        }
    }
}

impl StdError for Error {
    fn description(&self) -> &str {
        if let Some(description) = self.description.as_ref() {
            description
        } else if let Some(cause) = self.cause() {
            cause.description()
        } else {
            ""
        }
    }

    fn cause(&self) -> Option<&StdError> {
        self.cause.as_ref().map(|e| &**e)
    }
}

fn run_impl<E, F>(main: F) -> i32
    where F: FnOnce() -> Result<(), E>,
          E: Into<Box<StdError>>
{
    if let Err(error) = main() {
        let error = error.into();
        let argv0 = env::args().next();
        let program_name = argv0.as_ref()
                                .and_then(|s| Path::new(s).file_name())
                                .map(|os| os.to_string_lossy());
        let prefix = program_name.as_ref().map(|s| &**s).unwrap_or("<unknown>");

        let _ = writeln!(io::stderr(), "{}: {}", prefix, error).is_ok();
        1
    } else {
        0
    }
}

/// Runs a `Result`-returning function and exits the process with 0 if successful.
///
/// If `main` returns an error, it displays it (and all its causes recursively) to `stderr` and
/// exists the process with 1.
pub fn run_and_exit<E, F>(main: F) -> !
    where F: FnOnce() -> Result<(), E>,
          E: Into<Box<StdError>>
{
    process::exit(run_impl(main))
}

/// Like `try!`, but in the error case the error is wrapped in an `Error` with a given description
/// (which can be specified using `format_args!` syntax).
///
/// Example:
///
/// ```norust
///     ctry!(File::open(filename), "could not open output file {}", filename)
/// ```
///
/// Note: If you don't like macros, the `DescribeErr` trait already cuts on a lot of verbosity.
#[macro_export]
macro_rules! ctry {
    ($e:expr, $fmt:expr) => {{
        use $crate::DescribeErr;
        try!($e.describe_err_with(|| $fmt))
    }};
    ($e:expr, $fmt:expr, $($arg:tt)*) => {{
        use $crate::DescribeErr;
        try!($e.describe_err_with(|| format!($fmt, $($arg)*)))
    }}
}

/// Like `assert!` but instead of panicking it early-returns an `Error` with a given description
/// (which can be specified using `format_args!` syntax).
///
/// Example:
///
/// ```norust
///     ccheck!(value(key) == 42, "value of {} was not 42 ({})", key, value(key))
/// ```
///
/// Note: If you don't like macros, the `DescribeErr` trait already cuts on a lot of verbosity.
#[macro_export]
macro_rules! ccheck {
    ($e:expr, $fmt:expr) => {{
        use $crate::Error;
        if !($e) {
            return Err(Error::with_description($fmt).into());
        }
    }};
    ($e:expr, $fmt:expr, $($arg:tt)*) => {{
        use $crate::Error;
        if !($e) {
            return Err(Error::with_description(format!($fmt, $($arg)*)).into());
        }
    }}
}

#[cfg(test)]
mod test {
    use super::{Error, DescribeErr, run_impl};
    use std::error::Error as StdError;
    use std::cell::Cell;

    fn ok() -> Result<(), Error> {
        Ok(())
    }

    fn err() -> Result<(), Error> {
        Err(Error::with_description("test"))
    }

    fn err_box() -> Result<(), Box<StdError>> {
        Err(Box::new(Error::with_description("test")))
    }

    #[test]
    fn error() {
        let with_static = Error::new("test", Error::with_description("cause"));
        let with_owned = Error::new("test2".to_owned(),
                                    Error::caused_by(Error::with_description("cause2")));

        assert_eq!(&format!("{}", with_static), "test\n    caused by: cause");
        assert_eq!(&format!("{}", with_owned), "test2\n    caused by: cause2");
        assert_eq!(with_static.description(), "test");
        assert_eq!(with_owned.description(), "test2");

        assert_eq!(with_static.cause().map(|c| c.description()), Some("cause"));
        assert!(with_static.cause().unwrap().cause().is_none());

        assert_eq!(with_owned.cause().map(|c| c.description()), Some("cause2"));
        assert!(with_owned.cause().unwrap().cause().unwrap().cause().is_none());
        assert_eq!(with_owned.cause().map(|c| format!("{}", c)),
                   Some("cause2".to_owned()));
        assert_eq!(with_owned.cause().and_then(|c| c.cause()).map(|c| c.description()),
                   Some("cause2"));
    }

    #[test]
    fn describe_err() {
        let counter = Cell::new(0);
        let inc = || {
            counter.set(counter.get() + 1);
            "wrapper"
        };

        assert!(ok().describe_err("wrapper").is_ok());
        assert!(ok().describe_err_with(&inc).is_ok());
        assert_eq!(counter.get(), 0);

        let described = err().describe_err("wrapper");
        match described {
            Err(error) => {
                assert_eq!(error.description(), "wrapper");
                assert_eq!(error.cause().map(|c| c.description()), Some("test"));
            }
            Ok(()) => panic!("failed: {:?}", described),
        }

        let described = err().describe_err_with(&inc);
        assert_eq!(counter.get(), 1);
        match described {
            Err(error) => {
                assert_eq!(error.description(), "wrapper");
                assert_eq!(error.cause().map(|c| c.description()), Some("test"));
            }
            Ok(()) => panic!("failed: {:?}", described),
        }
    }

    #[test]
    fn ctry_ok() {
        fn foo() -> Result<u32, Error> {
            let _ = ctry!(ok(), "oh no!");
            Ok(42)
        }
        assert_eq!(foo().unwrap(), 42);
    }

    #[test]
    fn ctry_err() {
        fn foo() -> Result<u32, Error> {
            let _ = ctry!(err(), "help {}", "us");
            Ok(42)
        }
        match foo() {
            Err(e) => {
                assert_eq!(e.description(), "help us");
                assert_eq!(e.cause().unwrap().description(), "test");
            }
            Ok(x) => panic!("failed: {:?}", x),
        }
    }

    #[test]
    fn ccheck_ok() {
        fn foo() -> Result<u32, Error> {
            ccheck!(true, "oh no!");
            Ok(42)
        }
        assert_eq!(foo().unwrap(), 42);
    }

    #[test]
    fn ccheck_err() {
        fn foo() -> Result<u32, Error> {
            ccheck!(false, "help {}", "us");
            Ok(42)
        }
        match foo() {
            Err(e) => {
                assert_eq!(e.description(), "help us");
                assert!(e.cause().is_none());
            }
            Ok(x) => panic!("failed: {:?}", x),
        }
    }

    #[test]
    fn run_returns_zero_for_success() {
        assert_eq!(run_impl(ok), 0);
    }

    #[test]
    fn run_returns_one_for_error() {
        assert_eq!(run_impl(err), 1);
    }

    #[test]
    fn run_returns_one_for_error_box() {
        assert_eq!(run_impl(err_box), 1);
    }
}
<|endoftext|>


<commit_before>use std::io::Command;
use std::os;
use std::str;

pub struct Options {
    pub statik: bool,
}

pub fn find_library(name: &str) -> Result<(), String> {
    find_library_opts(name, &default_options(name))
}

pub fn find_library_opts(name: &str, options: &Options) -> Result<(), String> {
    if os::getenv(format!("{}_NO_PKG_CONFIG", envify(name)).as_slice()).is_some() {
        return Err(format!("pkg-config requested to be aborted for {}", name))
    }
    let mut cmd = Command::new("pkg-config");
    if options.statik {
        cmd.arg("--static");
    }
    cmd.arg("--libs")
       .env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1")
       .arg(name);
    let out = try!(cmd.output().map_err(|e| {
        format!("failed to run `{}`: {}", cmd, e)
    }));
    let stdout = str::from_utf8(out.output.as_slice()).unwrap();
    let stderr = str::from_utf8(out.error.as_slice()).unwrap();
    if !out.status.success() {
        let mut msg = format!("`{}` did not exit successfully: {}", cmd,
                              out.status);
        if stdout.len() > 0 {
            msg.push_str("\n--- stdout\n");
            msg.push_str(stdout);
        }
        if stderr.len() > 0 {
            msg.push_str("\n--- stderr\n");
            msg.push_str(stderr);
        }
        return Err(msg)
    }

    for arg in stdout.split(' ').filter(|l| !l.is_empty()) {
        let val = arg.slice_from(2);
        if arg.starts_with("-l") {
            if options.statik {
                println!("cargo:rustc-args=-l {}:static", val);
            } else {
                println!("cargo:rustc-args=-l {}", val);
            }
        } else if arg.starts_with("-L") {
            println!("cargo:rustc-args=-L {}", val);
        }
    }
    Ok(())
}

pub fn default_options(name: &str) -> Options {
    let name = envify(name);
    let statik = if os::getenv(format!("{}_STATIC", name).as_slice()).is_some() {
        true
    } else if os::getenv(format!("{}_DYNAMIC", name).as_slice()).is_some() {
        false
    } else if os::getenv("PKG_CONFIG_ALL_STATIC").is_some() {
        true
    } else if os::getenv("PKG_CONFIG_ALL_DYNAMIC").is_some() {
        false
    } else {
        true
    };
    Options { statik: statik }
}

fn envify(name: &str) -> String {
    name.chars().map(|c| c.to_uppercase()).map(|c| if c == '-' {'_'} else {c})
        .collect()
}
<commit_msg>Fix an indexing error<commit_after>use std::io::Command;
use std::os;
use std::str;

pub struct Options {
    pub statik: bool,
}

pub fn find_library(name: &str) -> Result<(), String> {
    find_library_opts(name, &default_options(name))
}

pub fn find_library_opts(name: &str, options: &Options) -> Result<(), String> {
    if os::getenv(format!("{}_NO_PKG_CONFIG", envify(name)).as_slice()).is_some() {
        return Err(format!("pkg-config requested to be aborted for {}", name))
    }
    let mut cmd = Command::new("pkg-config");
    if options.statik {
        cmd.arg("--static");
    }
    cmd.arg("--libs")
       .env("PKG_CONFIG_ALLOW_SYSTEM_LIBS", "1")
       .arg(name);
    let out = try!(cmd.output().map_err(|e| {
        format!("failed to run `{}`: {}", cmd, e)
    }));
    let stdout = str::from_utf8(out.output.as_slice()).unwrap();
    let stderr = str::from_utf8(out.error.as_slice()).unwrap();
    if !out.status.success() {
        let mut msg = format!("`{}` did not exit successfully: {}", cmd,
                              out.status);
        if stdout.len() > 0 {
            msg.push_str("\n--- stdout\n");
            msg.push_str(stdout);
        }
        if stderr.len() > 0 {
            msg.push_str("\n--- stderr\n");
            msg.push_str(stderr);
        }
        return Err(msg)
    }

    for arg in stdout.split(' ').filter(|l| !l.is_empty() && l.len() > 2) {
        let val = arg.slice_from(2);
        if arg.starts_with("-l") {
            if options.statik {
                println!("cargo:rustc-args=-l {}:static", val);
            } else {
                println!("cargo:rustc-args=-l {}", val);
            }
        } else if arg.starts_with("-L") {
            println!("cargo:rustc-args=-L {}", val);
        }
    }
    Ok(())
}

pub fn default_options(name: &str) -> Options {
    let name = envify(name);
    let statik = if os::getenv(format!("{}_STATIC", name).as_slice()).is_some() {
        true
    } else if os::getenv(format!("{}_DYNAMIC", name).as_slice()).is_some() {
        false
    } else if os::getenv("PKG_CONFIG_ALL_STATIC").is_some() {
        true
    } else if os::getenv("PKG_CONFIG_ALL_DYNAMIC").is_some() {
        false
    } else {
        true
    };
    Options { statik: statik }
}

fn envify(name: &str) -> String {
    name.chars().map(|c| c.to_uppercase()).map(|c| if c == '-' {'_'} else {c})
        .collect()
}
<|endoftext|>