<commit_before>use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::collections::HashMap;
use std::fmt::Debug;
use std::ops::Deref;
use std::str::FromStr;

use error::*;
use ser::ConfigSerializer;
use source::Source;

use path;
use value::{Table, Value, ValueKind};

#[derive(Clone, Debug)]
enum ConfigKind {
    // A mutable configuration. This is the default.
    Mutable {
        defaults: HashMap<path::Expression, Value>,
        overrides: HashMap<path::Expression, Value>,
        sources: Vec<Box<dyn Source + Send + Sync>>,
    },

    // A frozen configuration.
    // Configuration can no longer be mutated.
    Frozen,
}

impl Default for ConfigKind {
    fn default() -> Self {
        ConfigKind::Mutable {
            defaults: HashMap::new(),
            overrides: HashMap::new(),
            sources: Vec::new(),
        }
    }
}

/// A prioritized configuration repository. It maintains a set of
/// configuration sources, fetches values to populate those, and provides
/// them according to the source's priority.
#[derive(Clone, Debug)]
pub struct Config {
    kind: ConfigKind,

    /// Root of the cached configuration.
    pub cache: Value,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            kind: ConfigKind::default(),
            cache: Value::new(None, Table::new()),
        }
    }
}

impl Config {
    /// Merge in a configuration property source.
    pub fn merge<T>(&mut self, source: T) -> Result<&mut Config>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()
    }

    /// Merge in a configuration property source.
    pub fn with_merged<T>(mut self, source: T) -> Result<Self>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()?;
        Ok(self)
    }

    /// Refresh the configuration cache with fresh
    /// data from added sources.
    ///
    /// Configuration is automatically refreshed after a mutation
    /// operation (`set`, `merge`, `set_default`, etc.).
    pub fn refresh(&mut self) -> Result<&mut Config> {
        self.cache = match self.kind {
            // TODO: We need to actually merge in all the stuff
            ConfigKind::Mutable {
                ref overrides,
                ref sources,
                ref defaults,
            } => {
                let mut cache: Value = HashMap::<String, Value>::new().into();

                // Add defaults
                for (key, val) in defaults {
                    key.set(&mut cache, val.clone());
                }

                // Add sources
                sources.collect_to(&mut cache)?;

                // Add overrides
                for (key, val) in overrides {
                    key.set(&mut cache, val.clone());
                }

                cache
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        };

        Ok(self)
    }

    /// Set a default `value` at `key`
    pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut defaults, ..
            } => {
                defaults.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    /// Set an overwrite
    ///
    /// This function sets an overwrite value.
    /// The overwrite `value` is written to the `key` location on every `refresh()`
    ///
    /// # Warning
    ///
    /// Errors if config is frozen
    pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut overrides, ..
            } => {
                overrides.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    pub fn set_once(&mut self, key: &str, value: Value) -> Result<()> {
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        if let Some(ref mut val) = expr.get_mut(&mut self.cache) {
            **val = value;
        } else {
            expr.set(&mut self.cache, value);
        }
        Ok(())
    }

    pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
        // Parse the key into a path expression
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        let value = expr.get(&self.cache).cloned();

        match value {
            Some(value) => {
                // Deserialize the received value into the requested type
                T::deserialize(value).map_err(|e| e.extend_with_key(key))
            }

            None => Err(ConfigError::NotFound(key.into())),
        }
    }

    pub fn get_string(&self, key: &str) -> Result<String> {
        self.get(key).and_then(Value::into_string)
    }

    pub fn get_int(&self, key: &str) -> Result<i64> {
        self.get(key).and_then(Value::into_int)
    }

    pub fn get_float(&self, key: &str) -> Result<f64> {
        self.get(key).and_then(Value::into_float)
    }

    pub fn get_bool(&self, key: &str) -> Result<bool> {
        self.get(key).and_then(Value::into_bool)
    }

    pub fn get_table(&self, key: &str) -> Result<HashMap<String, Value>> {
        self.get(key).and_then(Value::into_table)
    }

    pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
        self.get(key).and_then(Value::into_array)
    }

    /// Attempt to deserialize the entire configuration into the requested type.
    pub fn try_into<'de, T: Deserialize<'de>>(self) -> Result<T> {
        T::deserialize(self)
    }

    /// Attempt to serialize the entire configuration from the given type.
    pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
        let mut serializer = ConfigSerializer::default();
        from.serialize(&mut serializer)?;
        Ok(serializer.output)
    }

    #[deprecated(since = "0.7.0", note = "please use 'try_into' instead")]
    pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
        self.try_into()
    }
}

impl Source for Config {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<HashMap<String, Value>> {
        self.cache.clone().into_table()
    }
}
<commit_msg>Fix: Add missing Config::freeze() function<commit_after>use serde::de::{Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::collections::HashMap;
use std::fmt::Debug;
use std::ops::Deref;
use std::str::FromStr;

use error::*;
use ser::ConfigSerializer;
use source::Source;

use path;
use value::{Table, Value, ValueKind};

#[derive(Clone, Debug)]
enum ConfigKind {
    // A mutable configuration. This is the default.
    Mutable {
        defaults: HashMap<path::Expression, Value>,
        overrides: HashMap<path::Expression, Value>,
        sources: Vec<Box<dyn Source + Send + Sync>>,
    },

    // A frozen configuration.
    // Configuration can no longer be mutated.
    Frozen,
}

impl Default for ConfigKind {
    fn default() -> Self {
        ConfigKind::Mutable {
            defaults: HashMap::new(),
            overrides: HashMap::new(),
            sources: Vec::new(),
        }
    }
}

/// A prioritized configuration repository. It maintains a set of
/// configuration sources, fetches values to populate those, and provides
/// them according to the source's priority.
#[derive(Clone, Debug)]
pub struct Config {
    kind: ConfigKind,

    /// Root of the cached configuration.
    pub cache: Value,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            kind: ConfigKind::default(),
            cache: Value::new(None, Table::new()),
        }
    }
}

impl Config {
    pub fn freeze(&mut self) {
        self.kind = ConfigKind::Frozen
    }

    /// Merge in a configuration property source.
    pub fn merge<T>(&mut self, source: T) -> Result<&mut Config>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()
    }

    /// Merge in a configuration property source.
    pub fn with_merged<T>(mut self, source: T) -> Result<Self>
    where
        T: 'static,
        T: Source + Send + Sync,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut sources, ..
            } => {
                sources.push(Box::new(source));
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        }

        self.refresh()?;
        Ok(self)
    }

    /// Refresh the configuration cache with fresh
    /// data from added sources.
    ///
    /// Configuration is automatically refreshed after a mutation
    /// operation (`set`, `merge`, `set_default`, etc.).
    pub fn refresh(&mut self) -> Result<&mut Config> {
        self.cache = match self.kind {
            // TODO: We need to actually merge in all the stuff
            ConfigKind::Mutable {
                ref overrides,
                ref sources,
                ref defaults,
            } => {
                let mut cache: Value = HashMap::<String, Value>::new().into();

                // Add defaults
                for (key, val) in defaults {
                    key.set(&mut cache, val.clone());
                }

                // Add sources
                sources.collect_to(&mut cache)?;

                // Add overrides
                for (key, val) in overrides {
                    key.set(&mut cache, val.clone());
                }

                cache
            }

            ConfigKind::Frozen => {
                return Err(ConfigError::Frozen);
            }
        };

        Ok(self)
    }

    /// Set a default `value` at `key`
    pub fn set_default<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut defaults, ..
            } => {
                defaults.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    /// Set an overwrite
    ///
    /// This function sets an overwrite value.
    /// The overwrite `value` is written to the `key` location on every `refresh()`
    ///
    /// # Warning
    ///
    /// Errors if config is frozen
    pub fn set<T>(&mut self, key: &str, value: T) -> Result<&mut Config>
    where
        T: Into<Value>,
    {
        match self.kind {
            ConfigKind::Mutable {
                ref mut overrides, ..
            } => {
                overrides.insert(key.parse()?, value.into());
            }

            ConfigKind::Frozen => return Err(ConfigError::Frozen),
        };

        self.refresh()
    }

    pub fn set_once(&mut self, key: &str, value: Value) -> Result<()> {
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        if let Some(ref mut val) = expr.get_mut(&mut self.cache) {
            **val = value;
        } else {
            expr.set(&mut self.cache, value);
        }
        Ok(())
    }

    pub fn get<'de, T: Deserialize<'de>>(&self, key: &str) -> Result<T> {
        // Parse the key into a path expression
        let expr: path::Expression = key.parse()?;

        // Traverse the cache using the path to (possibly) retrieve a value
        let value = expr.get(&self.cache).cloned();

        match value {
            Some(value) => {
                // Deserialize the received value into the requested type
                T::deserialize(value).map_err(|e| e.extend_with_key(key))
            }

            None => Err(ConfigError::NotFound(key.into())),
        }
    }

    pub fn get_string(&self, key: &str) -> Result<String> {
        self.get(key).and_then(Value::into_string)
    }

    pub fn get_int(&self, key: &str) -> Result<i64> {
        self.get(key).and_then(Value::into_int)
    }

    pub fn get_float(&self, key: &str) -> Result<f64> {
        self.get(key).and_then(Value::into_float)
    }

    pub fn get_bool(&self, key: &str) -> Result<bool> {
        self.get(key).and_then(Value::into_bool)
    }

    pub fn get_table(&self, key: &str) -> Result<HashMap<String, Value>> {
        self.get(key).and_then(Value::into_table)
    }

    pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
        self.get(key).and_then(Value::into_array)
    }

    /// Attempt to deserialize the entire configuration into the requested type.
    pub fn try_into<'de, T: Deserialize<'de>>(self) -> Result<T> {
        T::deserialize(self)
    }

    /// Attempt to serialize the entire configuration from the given type.
    pub fn try_from<T: Serialize>(from: &T) -> Result<Self> {
        let mut serializer = ConfigSerializer::default();
        from.serialize(&mut serializer)?;
        Ok(serializer.output)
    }

    #[deprecated(since = "0.7.0", note = "please use 'try_into' instead")]
    pub fn deserialize<'de, T: Deserialize<'de>>(self) -> Result<T> {
        self.try_into()
    }
}

impl Source for Config {
    fn clone_into_box(&self) -> Box<dyn Source + Send + Sync> {
        Box::new((*self).clone())
    }

    fn collect(&self) -> Result<HashMap<String, Value>> {
        self.cache.clone().into_table()
    }
}
<|endoftext|>


<commit_before>#[phase(plugin, link)] extern crate log;
extern crate std;

use std::io;
use std::io::fs::PathExtensions;
use std::str;

const MESSAGE_SIZE: uint = 4096;
const LINE_END: u8 = '\n' as u8;

/// Result of PeekCommand, when it was successful
/// Contains message and new offset to specify to peek command
/// for continuous peeking
pub struct PeekResult {
    /// Contains message
    pub message: String,
    /// Contains next offset to be specified to read next message from river
    pub offset: uint
}

impl Clone for PeekResult {
    fn clone(&self) -> PeekResult {
        PeekResult {
            message: self.message.clone(),
            offset: self.offset.clone()
        }
    }

    fn clone_from(&mut self, source: &PeekResult) {
        self.message = source.message.clone();
        self.offset = source.offset.clone();
    }
}

pub struct River {
    path: Path,
    name: String
}

impl River {
    pub fn new(river: &str) -> River {
        River {
            name: river.to_string(),
            path: Path::new(format!("./tmp/rivers/{}", river))
        }
    }

    pub fn push(&self, message: &str) {
        let mut file = self.get_file_for_append();
        let bytes = message.as_bytes();

        match file.write(bytes) {
            Ok(_) => self.write_abundant_bytes(&mut file, bytes.len()),
            Err(err) => self.error("Unable to push message", &err)
        }
    }

    pub fn create_unless_exists(&self) {
        if ! self.path.exists() {
            match io::File::create(&self.path) {
                Ok(_) => {},
                Err(err) => self.error("Unable to create river", &err)
            }
        }
    }

    pub fn peek_at(&self, offset: Option < uint >) -> Option < PeekResult > {
        match self.get_line(offset) {
            Some((actual_offset, message)) => self.form_peek_result(message, actual_offset, offset),
            _ => None
        }
    }

    pub fn destroy(&self) {
        match io::fs::unlink(&self.path) {
            Ok(_) => {},
            Err(err) => self.error(format!("Unable to clear river {}", self.name).as_slice(), &err)
        }
    }

    fn form_peek_result(&self, message: String, actual_offset: uint, offset: Option < uint >) -> Option < PeekResult > {
        match self.are_offsets_match(actual_offset, offset) {
            true => Some(PeekResult {
                message: message.replace("\n", ""),
                offset: actual_offset + 2
            }),
            false => None
        }
    }

    fn get_file_for_append(&self) -> io::IoResult < io::File > {
        self.create_unless_exists();
        io::File::open_mode(&self.path, io::Append, io::Write)
    }

    fn get_file_for_peek(&self) -> io::IoResult < io::File > {
        self.create_unless_exists();
        io::File::open(&self.path)
    }

    fn get_line(&self, offset: Option < uint >) -> Option < (uint, String) > {
        let mut file = self.get_file_for_peek();

        match self.seek_and_read_line(&mut file, offset) {
            Some(string) => Some((self.get_actual_offset(offset).unwrap(), string)),
            _ => None
        }
    }

    fn read_line(&self, file: &mut io::IoResult < io::File >) -> Option < String > {
        let mut buf: Vec < u8 > = vec![];

        loop {
            match file.read_byte() {
                Ok(LINE_END) => break,
                Ok(byte) => {
                    buf.push(byte);
                },
                _ => break
            }
        }

        match str::from_utf8(buf.as_slice()) {
            Some(string) => Some(string.to_string()),
            _ => None
        }
    }

    fn are_offsets_match(&self, actual_offset: uint, offset: Option < uint >) -> bool {
        match offset {
            Some(offset) => actual_offset == offset - 1,
            None => true
        }
    }

    fn abundant_bytes(&self, count: uint) -> Vec < u8 > {
        let mut abundant_bytes: Vec < u8 > = range(0, MESSAGE_SIZE - count).map(|_| { 0 }).collect();
        abundant_bytes[0] = '\n' as u8;
        abundant_bytes
    }

    fn write_abundant_bytes(&self, file: &mut io::IoResult < io::File >, count: uint) {
        match file.write(self.abundant_bytes(count).as_slice()) {
            Ok(_) => {},
            Err(err) => self.error("Unable to push message", &err)
        }
    }

    fn size(&self) -> uint {
        match self.path.stat() {
            Ok(stat) => (stat.size.to_uint().unwrap() + MESSAGE_SIZE - 1) / MESSAGE_SIZE,
            Err(err) => { self.error("unable to get size of river", &err); 0 }
        }
    }

    fn get_actual_offset(&self, offset: Option < uint >) -> Option < uint > {
        let size = self.size();
        let adjusted_offset = match offset {
            Some(offset) => std::cmp::min(size, offset),
            None => size
        };

        match adjusted_offset {
            0 => None,
            offset => Some(offset - 1)
        }
    }

    fn get_seek_offset(&self, offset: Option < uint >) -> Option < i64 > {
        match self.get_actual_offset(offset) {
            Some(offset) => match (offset * MESSAGE_SIZE).to_i64() {
                Some(seek_offset) => Some(seek_offset),
                _ => None
            },
            _ => None
        }
    }

    fn seek_and_read_line(&self, file: &mut io::IoResult < io::File >, offset: Option < uint >) -> Option < String > {
        match self.get_seek_offset(offset) {
            Some(seek_offset) => match file.seek(seek_offset, io::SeekSet) {
                Ok(_) => self.read_line(file),
                _ => None
            },
            _ => None
        }
    }

    #[allow(unused_variables)]
    fn error(&self, message: &str, err: &std::fmt::Show) {
        ()
    }

    #[allow(dead_code)]
    #[allow(unused_variables)]
    fn debug(&self, message: &std::fmt::Show) {
        println!("DEBUG: {}", message);
        ()
    }
}
<commit_msg>refactor: improved some River's private methods<commit_after>#[phase(plugin, link)] extern crate log;
extern crate std;

use std::io;
use std::io::fs::PathExtensions;
use std::str;

const MESSAGE_SIZE: uint = 4096;
const LINE_END: u8 = '\n' as u8;

/// Result of PeekCommand, when it was successful
/// Contains message and new offset to specify to peek command
/// for continuous peeking
pub struct PeekResult {
    /// Contains message
    pub message: String,
    /// Contains next offset to be specified to read next message from river
    pub offset: uint
}

impl Clone for PeekResult {
    fn clone(&self) -> PeekResult {
        PeekResult {
            message: self.message.clone(),
            offset: self.offset.clone()
        }
    }

    fn clone_from(&mut self, source: &PeekResult) {
        self.message = source.message.clone();
        self.offset = source.offset.clone();
    }
}

pub struct River {
    path: Path,
    name: String
}

impl River {
    pub fn new(river: &str) -> River {
        River {
            name: river.to_string(),
            path: Path::new(format!("./tmp/rivers/{}", river))
        }
    }

    pub fn push(&self, message: &str) {
        let mut file = self.get_file_for_append();
        let bytes = message.as_bytes();

        match file.write(bytes) {
            Ok(_) => self.write_abundant_bytes(&mut file, bytes.len()),
            Err(err) => self.error("Unable to push message", &err)
        }
    }

    pub fn create_unless_exists(&self) {
        if ! self.path.exists() {
            match io::File::create(&self.path) {
                Ok(_) => {},
                Err(err) => self.error("Unable to create river", &err)
            }
        }
    }

    pub fn peek_at(&self, offset: Option < uint >) -> Option < PeekResult > {
        match self.get_line(offset) {
            Some((actual_offset, message)) => self.form_peek_result(message, actual_offset, offset),
            _ => None
        }
    }

    pub fn destroy(&self) {
        match io::fs::unlink(&self.path) {
            Ok(_) => {},
            Err(err) => self.error(format!("Unable to clear river {}", self.name).as_slice(), &err)
        }
    }

    fn form_peek_result(&self, message: String, actual_offset: uint, offset: Option < uint >) -> Option < PeekResult > {
        match self.are_offsets_match(actual_offset, offset) {
            true => Some(PeekResult {
                message: message.replace("\n", ""),
                offset: actual_offset + 2
            }),
            false => None
        }
    }

    fn get_file_for_append(&self) -> io::IoResult < io::File > {
        self.create_unless_exists();
        io::File::open_mode(&self.path, io::Append, io::Write)
    }

    fn get_file_for_peek(&self) -> io::IoResult < io::File > {
        self.create_unless_exists();
        io::File::open(&self.path)
    }

    fn get_line(&self, offset: Option < uint >) -> Option < (uint, String) > {
        let mut file = self.get_file_for_peek();

        match self.seek_and_read_line(&mut file, offset) {
            Some(string) => Some((self.get_actual_offset(offset).unwrap(), string)),
            _ => None
        }
    }

    fn read_line(&self, file: &mut io::IoResult < io::File >) -> Option < String > {
        let mut buf: Vec < u8 > = vec![];

        self.read_to_buf_until_eol(file, &mut buf);
        self.convert_buf_to_string(buf)
    }

    fn are_offsets_match(&self, actual_offset: uint, offset: Option < uint >) -> bool {
        match offset {
            Some(offset) => actual_offset == offset - 1,
            None => true
        }
    }

    fn abundant_bytes(&self, count: uint) -> Vec < u8 > {
        let mut abundant_bytes: Vec < u8 > = range(0, MESSAGE_SIZE - count).map(|_| { 0 }).collect();
        abundant_bytes[0] = '\n' as u8;
        abundant_bytes
    }

    fn write_abundant_bytes(&self, file: &mut io::IoResult < io::File >, count: uint) {
        match file.write(self.abundant_bytes(count).as_slice()) {
            Ok(_) => {},
            Err(err) => self.error("Unable to push message", &err)
        }
    }

    fn size(&self) -> uint {
        match self.path.stat() {
            Ok(stat) => (stat.size.to_uint().unwrap() + MESSAGE_SIZE - 1) / MESSAGE_SIZE,
            Err(err) => { self.error("unable to get size of river", &err); 0 }
        }
    }

    fn get_actual_offset(&self, offset: Option < uint >) -> Option < uint > {
        let size = self.size();
        let adjusted_offset = match offset {
            Some(offset) => std::cmp::min(size, offset),
            None => size
        };

        match adjusted_offset {
            0 => None,
            offset => Some(offset - 1)
        }
    }

    fn get_seek_offset(&self, offset: Option < uint >) -> Option < i64 > {
        match self.get_actual_offset(offset) {
            Some(offset) => match (offset * MESSAGE_SIZE).to_i64() {
                Some(seek_offset) => Some(seek_offset),
                _ => None
            },
            _ => None
        }
    }

    fn seek_and_read_line(&self, file: &mut io::IoResult < io::File >, offset: Option < uint >) -> Option < String > {
        match self.get_seek_offset(offset) {
            Some(seek_offset) => match file.seek(seek_offset, io::SeekSet) {
                Ok(_) => self.read_line(file),
                _ => None
            },
            _ => None
        }
    }

    fn read_to_buf_until_eol(&self, file: &mut io::IoResult < io::File >, buf: &mut Vec < u8 >) {
        loop {
            if ! self.read_one_byte_to_buf(file, buf) {
                break
            }
        }
    }

    fn read_one_byte_to_buf(&self, file: &mut io::IoResult < io::File >, buf: &mut Vec < u8 >) -> bool {
        match file.read_byte() {
            Ok(LINE_END) => false,
            Ok(byte) => {
                buf.push(byte);
                true
            },
            _ => false
        }
    }

    fn convert_buf_to_string(&self, buf: Vec < u8 >) -> Option < String > {
        match str::from_utf8(buf.as_slice()) {
            Some(string) => Some(string.to_string()),
            _ => None
        }
    }

    #[allow(unused_variables)]
    fn error(&self, message: &str, err: &std::fmt::Show) {
        ()
    }

    #[allow(dead_code)]
    #[allow(unused_variables)]
    fn debug(&self, message: &std::fmt::Show) {
        ()
    }
}
<|endoftext|>


<commit_before>/// The Toml Delete extensions

use toml::Value;

use tokenizer::Token;
use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueDeleteExt {

    /// Extension function for deleting a value in the current toml::Value document
    /// using a custom seperator.
    ///
    /// # Semantics
    ///
    /// The function does _not_ delete non-empty data structures. So deleting `array` from
    ///
    /// ```toml
    /// array = [ 1 ]
    /// ```
    ///
    /// does _not_ work.
    ///
    /// # Return value
    ///
    /// If the delete operation worked correctly, `Ok(Option<Value>)` is returned.
    ///
    /// The `Option<Value>` part is `None` if no value was actually removed as there was no value
    /// there. For example, if you're deleting `table.a` and the Table `table` has no key `a`, then
    /// `Ok(None)` is returned. Also, if you're deleting from an Array, but there is nothing in the
    /// array, or the array is shorter than the index you're deleting.
    /// If the delete operation actually removed something from the toml document, this value is
    /// returned as `Ok(Some(Value))`.
    ///
    /// On failure, `Err(e)` is returned
    ///
    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>>;

    /// Extension function for inserting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueinsertExt::insert_with_seperator`
    fn delete(&mut self, query: &String) -> Result<Option<Value>> {
        self.delete_with_seperator(query, '.')
    }

}

impl TomlValueDeleteExt for Value {

    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last_token = tokens.pop_last();

        /// Check whether a structure (Table/Array) is empty. If the Value has not these types,
        /// the default value is returned
        #[inline]
        fn is_empty(val: Option<&Value>, default: bool) -> bool {
            val.map(|v| match v {
                    &Value::Table(ref tab) => tab.is_empty(),
                    &Value::Array(ref arr) => arr.is_empty(),
                    _                      => default
                })
                .unwrap_or(default)
        }

        #[inline]
        fn is_table(val: Option<&Value>) -> bool {
            val.map(|v| is_match!(v, &Value::Table(_))).unwrap_or(false)
        }

        #[inline]
        fn is_array(val: Option<&Value>) -> bool {
            val.map(|v| is_match!(v, &Value::Array(_))).unwrap_or(false)
        }

        #[inline]
        fn name_of_val(val: Option<&Value>) -> &'static str {
            val.map(|v| match v {
                &Value::Array(_)    => "Array",
                &Value::Boolean(_)  => "Boolean",
                &Value::Datetime(_) => "Datetime",
                &Value::Float(_)    => "Float",
                &Value::Integer(_)  => "Integer",
                &Value::String(_)   => "String",
                &Value::Table(_)    => "Table",
            }).unwrap_or("None")
        }

        if last_token.is_none() {
            match self {
                &mut Value::Table(ref mut tab) => {
                    match tokens {
                        Token::Identifier { ident, .. } => {
                            if is_empty(tab.get(&ident), true) {
                                Ok(tab.remove(&ident))
                            } else {
                                if is_table(tab.get(&ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyTable(ident.clone());
                                    Err(Error::from(kind))
                                } else if is_array(tab.get(&ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyArray(ident.clone());
                                    Err(Error::from(kind))
                                } else {
                                    let act = name_of_val(tab.get(&ident));
                                    let tbl = "table";
                                    let k   = ErrorKind::CannotAccessBecauseTypeMismatch(tbl, act);
                                    Err(Error::from(k))
                                }
                            }
                        },
                        _ => Ok(None)
                    }
                },
                _ => unimplemented!()
            }
        } else {
            let mut val = try!(resolve(self, &tokens));
            Ok(None)
        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use error::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_delete_from_empty_document() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.delete_with_seperator(&String::from("a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_from_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_integer() {
        let mut toml : Value = toml_from_str(r#"
        value = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(1)));
    }

    #[test]
    fn test_delete_string() {
        let mut toml : Value = toml_from_str(r#"
        value = "foo"
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::String(_)));
        match res {
            Value::String(ref s) => assert_eq!("foo", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Table(_)));
        match res {
            Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Array(_)));
        match res {
            Value::Array(ref a) => assert!(a.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_nonempty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyTable(_)));
    }

    #[test]
    fn test_delete_nonempty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyArray(_)));
    }

    #[test]
    fn test_delete_int_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        int = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.int"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_array_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Array(_))));
    }

    #[test]
    fn test_delete_int_from_array_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.array.[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_int_from_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_int_from_table_from_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ { table = { int = 1 } } ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0].table.int"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

}

<commit_msg>Impl Value::delete_with_seperator to fix test_delete_int_from_table<commit_after>/// The Toml Delete extensions

use toml::Value;

use tokenizer::Token;
use tokenizer::tokenize_with_seperator;
use error::*;

pub trait TomlValueDeleteExt {

    /// Extension function for deleting a value in the current toml::Value document
    /// using a custom seperator.
    ///
    /// # Semantics
    ///
    /// The function does _not_ delete non-empty data structures. So deleting `array` from
    ///
    /// ```toml
    /// array = [ 1 ]
    /// ```
    ///
    /// does _not_ work.
    ///
    /// # Return value
    ///
    /// If the delete operation worked correctly, `Ok(Option<Value>)` is returned.
    ///
    /// The `Option<Value>` part is `None` if no value was actually removed as there was no value
    /// there. For example, if you're deleting `table.a` and the Table `table` has no key `a`, then
    /// `Ok(None)` is returned. Also, if you're deleting from an Array, but there is nothing in the
    /// array, or the array is shorter than the index you're deleting.
    /// If the delete operation actually removed something from the toml document, this value is
    /// returned as `Ok(Some(Value))`.
    ///
    /// On failure, `Err(e)` is returned
    ///
    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>>;

    /// Extension function for inserting a value from the current toml::Value document
    ///
    /// See documentation of `TomlValueinsertExt::insert_with_seperator`
    fn delete(&mut self, query: &String) -> Result<Option<Value>> {
        self.delete_with_seperator(query, '.')
    }

}

impl TomlValueDeleteExt for Value {

    fn delete_with_seperator(&mut self, query: &String, sep: char) -> Result<Option<Value>> {
        use resolver::mut_resolver::resolve;

        let mut tokens = try!(tokenize_with_seperator(query, sep));
        let last_token = tokens.pop_last();

        /// Check whether a structure (Table/Array) is empty. If the Value has not these types,
        /// the default value is returned
        #[inline]
        fn is_empty(val: Option<&Value>, default: bool) -> bool {
            val.map(|v| match v {
                    &Value::Table(ref tab) => tab.is_empty(),
                    &Value::Array(ref arr) => arr.is_empty(),
                    _                      => default
                })
                .unwrap_or(default)
        }

        #[inline]
        fn is_table(val: Option<&Value>) -> bool {
            val.map(|v| is_match!(v, &Value::Table(_))).unwrap_or(false)
        }

        #[inline]
        fn is_array(val: Option<&Value>) -> bool {
            val.map(|v| is_match!(v, &Value::Array(_))).unwrap_or(false)
        }

        #[inline]
        fn name_of_val(val: Option<&Value>) -> &'static str {
            val.map(|v| match v {
                &Value::Array(_)    => "Array",
                &Value::Boolean(_)  => "Boolean",
                &Value::Datetime(_) => "Datetime",
                &Value::Float(_)    => "Float",
                &Value::Integer(_)  => "Integer",
                &Value::String(_)   => "String",
                &Value::Table(_)    => "Table",
            }).unwrap_or("None")
        }

        if last_token.is_none() {
            match self {
                &mut Value::Table(ref mut tab) => {
                    match tokens {
                        Token::Identifier { ident, .. } => {
                            if is_empty(tab.get(&ident), true) {
                                Ok(tab.remove(&ident))
                            } else {
                                if is_table(tab.get(&ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyTable(ident.clone());
                                    Err(Error::from(kind))
                                } else if is_array(tab.get(&ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyArray(ident.clone());
                                    Err(Error::from(kind))
                                } else {
                                    let act = name_of_val(tab.get(&ident));
                                    let tbl = "table";
                                    let k   = ErrorKind::CannotAccessBecauseTypeMismatch(tbl, act);
                                    Err(Error::from(k))
                                }
                            }
                        },
                        _ => Ok(None)
                    }
                },
                _ => unimplemented!()
            }
        } else {
            let mut val = try!(resolve(self, &tokens));
            match val {
                &mut Value::Table(ref mut tab) => {
                    let last_token = last_token.unwrap();
                    match *last_token {
                        Token::Identifier { ref ident, .. } => {
                            if is_empty(tab.get(ident), true) {
                                Ok(tab.remove(ident))
                            } else {
                                if is_table(tab.get(ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyTable(ident.clone());
                                    Err(Error::from(kind))
                                } else if is_array(tab.get(ident)) {
                                    let kind = ErrorKind::CannotDeleteNonEmptyArray(ident.clone());
                                    Err(Error::from(kind))
                                } else {
                                    let act = name_of_val(tab.get(ident));
                                    let tbl = "table";
                                    let k   = ErrorKind::CannotAccessBecauseTypeMismatch(tbl, act);
                                    Err(Error::from(k))
                                }
                            }
                        },
                        Token::Index { idx, .. } => {
                            unimplemented!()
                        },
                    }
                },
                &mut Value::Array(ref mut arr) => {
                    unimplemented!()
                },
                _ => {
                    unimplemented!()
                }
            }
        }
    }

}

#[cfg(test)]
mod test {
    use super::*;
    use error::*;
    use toml::Value;
    use toml::from_str as toml_from_str;

    #[test]
    fn test_delete_from_empty_document() {
        let mut toml : Value = toml_from_str("").unwrap();

        let res = toml.delete_with_seperator(&String::from("a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_from_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.a"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_none());
    }

    #[test]
    fn test_delete_integer() {
        let mut toml : Value = toml_from_str(r#"
        value = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Integer(1)));
    }

    #[test]
    fn test_delete_string() {
        let mut toml : Value = toml_from_str(r#"
        value = "foo"
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("value"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::String(_)));
        match res {
            Value::String(ref s) => assert_eq!("foo", s),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Table(_)));
        match res {
            Value::Table(ref t) => assert!(t.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_empty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(res.is_some());
        let res = res.unwrap();
        assert!(is_match!(res, Value::Array(_)));
        match res {
            Value::Array(ref a) => assert!(a.is_empty()),
            _ => panic!("What just happened?"),
        }
    }

    #[test]
    fn test_delete_nonempty_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        a = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyTable(_)));
    }

    #[test]
    fn test_delete_nonempty_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array"), '.');

        assert!(res.is_err());

        let res = res.unwrap_err();
        assert!(is_match!(res.kind(), &ErrorKind::CannotDeleteNonEmptyArray(_)));
    }

    #[test]
    fn test_delete_int_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        int = 1
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.int"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_array_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        array = []
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.array"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Array(_))));
    }

    #[test]
    fn test_delete_int_from_array_from_table() {
        let mut toml : Value = toml_from_str(r#"
        [table]
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("table.array.[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_int_from_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ 1 ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0]"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

    #[test]
    fn test_delete_int_from_table_from_array() {
        let mut toml : Value = toml_from_str(r#"
        array = [ { table = { int = 1 } } ]
        "#).unwrap();

        let res = toml.delete_with_seperator(&String::from("array.[0].table.int"), '.');

        assert!(res.is_ok());

        let res = res.unwrap();
        assert!(is_match!(res, Some(Value::Integer(1))));
    }

}

<|endoftext|>


<commit_before>pub struct Node<T> {
    val: T,
    next: Option<Box<Node<T>>>,
}

pub struct Stack<T> {
    s: Option<Box<Node<T>>>
}

impl<T> Stack<T> {
    pub fn new() -> Stack<T> {
        Stack { s: None }
    }

    pub fn push(&mut self, val: T) {
        let next = self.s.take();
        self.s = Some(Box::new(Node { val: val, next: next }))
    }

    pub fn pop(&mut self) -> Option<T> {
        let mut top = self.s.take();
        self.s = top.as_mut().map(|t| t.next.take()).unwrap_or(None);
        top.map(|n| n.val)
    }

    pub fn len(&mut self) -> usize {
        let mut sz = 0;
        let mut p = self.s.as_ref();
        while p.is_some() {
            p = p.map(|n| n.next.as_ref()).unwrap_or(None);
            sz += 1;
        }
        sz
    }

    pub fn peek(&self) -> Option<&T> {
        self.s.as_ref().map(|n| &n.val)
    }

    pub fn peek_mut(&mut self) -> Option<&mut T> {
        self.s.as_mut().map(|n| &mut n.val)
    }
}

#[test]
fn test_stack() {
    let mut s = Stack::new();
    assert_eq!(s.len(), 0);
    s.push(1000);
    assert_eq!(s.len(), 1);
    s.push(2000);
    assert_eq!(s.len(), 2);
    assert_eq!(s.peek(), Some(&2000));
    assert_eq!(s.pop(), Some(2000));
    assert_eq!(s.len(), 1);
    assert_eq!(s.pop(), Some(1000));
    assert_eq!(s.len(), 0);
    assert_eq!(s.pop(), None);
    assert_eq!(s.len(), 0);

    s.push(250);
    s.peek_mut().map(|val| *val = 100);
    assert_eq!(s.pop(), Some(100));
}
<commit_msg>stack: implement IntoIterator for Stack<commit_after>pub struct Node<T> {
    val: T,
    next: Option<Box<Node<T>>>,
}

pub struct Stack<T> {
    s: Option<Box<Node<T>>>
}

impl<T> Stack<T> {
    pub fn new() -> Stack<T> {
        Stack { s: None }
    }

    pub fn push(&mut self, val: T) {
        let next = self.s.take();
        self.s = Some(Box::new(Node { val: val, next: next }))
    }

    pub fn pop(&mut self) -> Option<T> {
        let mut top = self.s.take();
        self.s = top.as_mut().map(|t| t.next.take()).unwrap_or(None);
        top.map(|n| n.val)
    }

    pub fn len(&self) -> usize {
        let mut sz = 0;
        let mut p = self.s.as_ref();
        while p.is_some() {
            p = p.map(|n| n.next.as_ref()).unwrap_or(None);
            sz += 1;
        }
        sz
    }

    pub fn peek(&self) -> Option<&T> {
        self.s.as_ref().map(|n| &n.val)
    }

    pub fn peek_mut(&mut self) -> Option<&mut T> {
        self.s.as_mut().map(|n| &mut n.val)
    }
}

pub struct IntoIter<T> {
    stack: Stack<T>
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.stack.pop()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let len = self.stack.len();
        (len, Some(len))
    }
}

impl<T> ExactSizeIterator for IntoIter<T> {
    fn len(&self) -> usize {
        self.stack.len()
    }
}

impl<T> IntoIterator for Stack<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter { stack: self }
    }
}

#[test]
fn test_stack() {
    let mut s = Stack::new();
    assert_eq!(s.len(), 0);
    s.push(1000);
    assert_eq!(s.len(), 1);
    s.push(2000);
    assert_eq!(s.len(), 2);
    assert_eq!(s.peek(), Some(&2000));
    assert_eq!(s.pop(), Some(2000));
    assert_eq!(s.len(), 1);
    assert_eq!(s.pop(), Some(1000));
    assert_eq!(s.len(), 0);
    assert_eq!(s.pop(), None);
    assert_eq!(s.len(), 0);

    s.push(250);
    s.peek_mut().map(|val| *val = 100);
    assert_eq!(s.pop(), Some(100));
}

#[test]
fn test_stack_into_iter() {
    let mut s = Stack::new();
    s.push(100);
    s.push(200);
    s.push(300);

    let mut result = vec![300, 200, 100].into_iter();
    for i in s {
        assert_eq!(i, result.next().unwrap());
    }
}
<|endoftext|>


<commit_before>use config::{Benchmark, parse_config};
use repo::Workspace;

use std::collections::HashMap;
use std::path::Path;
use std::process::{Command, ExitStatus};
use std::str;
use std::sync::Mutex;

/// `(val, percentage_change)`
#[derive(Debug, Clone)]
pub enum BenchmarkResult<T> {
    Improvement(T, i64),
    Regression(T, i64),
    Neutral(T, i64),
}

#[derive(Debug, Clone)]
pub struct TastingResult {
    pub commit_id: String,
    pub commit_msg: String,
    pub build: bool,
    pub bench: bool,
    pub results: Vec<HashMap<String, BenchmarkResult<String>>>,
}

fn benchmark(workdir: &str,
             cfg: &Benchmark)
             -> (ExitStatus, HashMap<String, BenchmarkResult<String>>) {
    let mut cmd = Command::new("cargo");
    cmd.current_dir(workdir)
        .arg(&cfg.cmd)
        .args(cfg.args.as_slice());

    let output = cmd.output()
        .expect(&format!("Failed to execute benchmark '{}'!", cfg.name));

    let lines = str::from_utf8(output.stdout.as_slice()).unwrap().lines();
    let mut res = HashMap::new();
    for l in lines {
        for (i, regex) in cfg.result_expr.iter().enumerate() {
            for cap in regex.captures_iter(l) {
                println!("{:#?}", cap);
                for c in cap.iter() {
                    res.insert(format!("{}/{}", cfg.name, i),
                               BenchmarkResult::Neutral(String::from(c.unwrap()), 0));
                }
            }
        }
    }
    println!("{:#?}", res);
    (output.status, res)
}

fn build(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("build")
        .arg("--release")
        .status()
        .expect("Failed to execute 'cargo build'!")
}

pub fn taste_commit(wsl: &Mutex<Workspace>, id: &str, msg: &str) -> TastingResult {
    println!("Tasting commit {}", id);
    let ws = wsl.lock().unwrap();
    ws.checkout_commit(id);

    let cfg = parse_config(Path::new(&format!("{}/taster.toml", ws.path)));

    let build_success = update(&ws.path).success() && build(&ws.path).success();
    let bench_out = cfg.unwrap()
        .iter()
        .map(|b| benchmark(&ws.path, b))
        .collect::<Vec<(ExitStatus, HashMap<String, BenchmarkResult<String>>)>>();
    let bench_success = bench_out.iter().all(|x| x.0.success());
    let bench_results = bench_out.iter().map(|x| x.1.clone()).collect();

    TastingResult {
        commit_id: String::from(id),
        commit_msg: String::from(msg),
        build: build_success,
        bench: bench_success,
        results: bench_results,
    }
}

fn update(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("update")
        .status()
        .expect("Failed to execute 'cargo update'!")
}
<commit_msg>Less debug noise<commit_after>use config::{Benchmark, parse_config};
use repo::Workspace;

use std::collections::HashMap;
use std::path::Path;
use std::process::{Command, ExitStatus};
use std::str;
use std::sync::Mutex;

/// `(val, percentage_change)`
#[derive(Debug, Clone)]
pub enum BenchmarkResult<T> {
    Improvement(T, i64),
    Regression(T, i64),
    Neutral(T, i64),
}

#[derive(Debug, Clone)]
pub struct TastingResult {
    pub commit_id: String,
    pub commit_msg: String,
    pub build: bool,
    pub bench: bool,
    pub results: Vec<HashMap<String, BenchmarkResult<String>>>,
}

fn benchmark(workdir: &str,
             cfg: &Benchmark)
             -> (ExitStatus, HashMap<String, BenchmarkResult<String>>) {
    let mut cmd = Command::new("cargo");
    cmd.current_dir(workdir)
        .arg(&cfg.cmd)
        .args(cfg.args.as_slice());

    let output = cmd.output()
        .expect(&format!("Failed to execute benchmark '{}'!", cfg.name));

    let lines = str::from_utf8(output.stdout.as_slice()).unwrap().lines();
    let mut res = HashMap::new();
    for l in lines {
        for (i, regex) in cfg.result_expr.iter().enumerate() {
            for cap in regex.captures_iter(l) {
                for c in cap.iter() {
                    res.insert(format!("{}/{}", cfg.name, i),
                               BenchmarkResult::Neutral(String::from(c.unwrap()), 0));
                }
            }
        }
    }
    (output.status, res)
}

fn build(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("build")
        .arg("--release")
        .status()
        .expect("Failed to execute 'cargo build'!")
}

pub fn taste_commit(wsl: &Mutex<Workspace>, id: &str, msg: &str) -> TastingResult {
    println!("Tasting commit {}", id);
    let ws = wsl.lock().unwrap();
    ws.checkout_commit(id);

    let cfg = parse_config(Path::new(&format!("{}/taster.toml", ws.path)));

    let build_success = update(&ws.path).success() && build(&ws.path).success();
    let bench_out = cfg.unwrap()
        .iter()
        .map(|b| benchmark(&ws.path, b))
        .collect::<Vec<(ExitStatus, HashMap<String, BenchmarkResult<String>>)>>();
    let bench_success = bench_out.iter().all(|x| x.0.success());
    let bench_results = bench_out.iter().map(|x| x.1.clone()).collect();

    TastingResult {
        commit_id: String::from(id),
        commit_msg: String::from(msg),
        build: build_success,
        bench: bench_success,
        results: bench_results,
    }
}

fn update(workdir: &str) -> ExitStatus {
    Command::new("cargo")
        .current_dir(workdir)
        .arg("update")
        .status()
        .expect("Failed to execute 'cargo update'!")
}
<|endoftext|>


<commit_before>use std;
use std::thread;
use std::sync::mpsc;

pub fn prime_filter(iter_size: usize) -> Vec<bool>{
    if iter_size<100{
        slow_prime_filter(iter_size)
    }else{
        prime_filter_section(0, iter_size)
    }
}

fn case_1(y_sq: usize, iter_size: usize)
    -> Vec<usize> {
    //n_1 = 4x^2 + y^2 === 1 (mod 4)
    let (mut n_1, mut to_next_n_1) = (y_sq, 4);    let mut ret_stack: Vec<usize> = Vec::new();
    loop{
        n_1 += to_next_n_1;
        to_next_n_1 += 8;
        match n_1%60{
            _ if n_1 >= iter_size => break,
            1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
            _ => continue,
        };

        // println!("1: {}", n_1);
        ret_stack.push(n_1);
    };
    ret_stack
}
fn case_2(y_sq: usize, iter_size: usize)
    -> Vec<usize> {
    //n_2 = 3x^2 + y^2 === 1 (mod 6)
    let (mut n_2, mut to_next_n_2) = (y_sq, 3);
    let mut ret_stack: Vec<usize> = Vec::new();
    loop {
        n_2 += to_next_n_2;
        to_next_n_2 += 6;
        match n_2%60{
            _ if n_2 >= iter_size => break,
            7 | 19 | 31 | 43 => (),
            _ => continue,
        };
        // println!("2: {}", n_2);
        ret_stack.push(n_2);
    };
    ret_stack
}
fn case_3(y_sq: usize, to_next_y_sq: usize, iter_size: usize)
    -> Vec<usize> {
    //n_3 = 3x^2 - y^2 === 11 (mod 12)
    let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
    let mut ret_stack: Vec<usize> = Vec::new();
    loop {
        n_3 += to_next_n_3;
        to_next_n_3 += 6;
        match n_3%60{
            _ if n_3 >= iter_size => break,
            11 | 23 | 47 | 59 => (),
            _ => continue,
        };
        // println!("3: {}", n_3);
        ret_stack.push(n_3);
    };
    ret_stack
}

fn prime_filter_section(min:usize, max: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min<max);
    let mut prime_filter = vec![false; max-min];
    if (min <= 2) & (max > 2) {prime_filter[2-min] = true;}
    if (min <= 3) & (max > 3) {prime_filter[3-min] = true;}
    if (min <= 5) & (max > 5) {prime_filter[5-min] = true;}

    let (mut y_sq, mut to_next_y_sq) = match min {
        0|1 => (1, 3),
        _ => (min*min, 2*min + 1),
    };
    let mut spawned_threads = 0;
    let (tx, rx) = mpsc::channel();
    while y_sq<max {
        if y_sq%2 == 1 {
            spawned_threads += 1;
            let (y_sq, tx) = (y_sq, tx.clone());
            thread::spawn(move || {
                tx.send(case_1(y_sq, max)).unwrap();
            });
        };
        if y_sq%3 == 1 {

            spawned_threads += 1;
            let (y_sq, to_next_y_sq, tx1) = (y_sq, to_next_y_sq, tx.clone());
            thread::spawn(move || {
                tx1.send(case_2(y_sq, max)).unwrap();
            });
            if y_sq*2<max{
                spawned_threads += 1;
                let tx2 = tx.clone();
                thread::spawn(move || {
                    tx2.send(case_3(y_sq, to_next_y_sq, max)).unwrap();
                });
            }
        };
    };
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };

    while spawned_threads!=0{
        for mes in rx.try_iter(){
            spawned_threads -= 1;
            for flip_i in mes{
                prime_filter[flip_i - min] ^= true;
            }
        }
    };
    //Eliminate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < max {
        let mut non_sq_free = n_sq;
        while non_sq_free < max {
            if non_sq_free >= min {
                prime_filter[non_sq_free - min] = false;
            }
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            n_sq += next_n_sq;
            next_n_sq += 8;
            (n_sq%3==0) | (n_sq%5 == 0)
        } {};
    }
    prime_filter
}
#[cfg(test)]
pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)
}

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<commit_msg>Missed a bracket<commit_after>use std;
use std::thread;
use std::sync::mpsc;

pub fn prime_filter(iter_size: usize) -> Vec<bool>{
    if iter_size<100{
        slow_prime_filter(iter_size)
    }else{
        prime_filter_section(0, iter_size)
    }
}

fn case_1(y_sq: usize, iter_size: usize)
    -> Vec<usize> {
    //n_1 = 4x^2 + y^2 === 1 (mod 4)
    let (mut n_1, mut to_next_n_1) = (y_sq, 4);    let mut ret_stack: Vec<usize> = Vec::new();
    loop{
        n_1 += to_next_n_1;
        to_next_n_1 += 8;
        match n_1%60{
            _ if n_1 >= iter_size => break,
            1 | 13 | 17 | 29 | 37 | 41 | 49 | 53 => (),
            _ => continue,
        };

        // println!("1: {}", n_1);
        ret_stack.push(n_1);
    };
    ret_stack
}
fn case_2(y_sq: usize, iter_size: usize)
    -> Vec<usize> {
    //n_2 = 3x^2 + y^2 === 1 (mod 6)
    let (mut n_2, mut to_next_n_2) = (y_sq, 3);
    let mut ret_stack: Vec<usize> = Vec::new();
    loop {
        n_2 += to_next_n_2;
        to_next_n_2 += 6;
        match n_2%60{
            _ if n_2 >= iter_size => break,
            7 | 19 | 31 | 43 => (),
            _ => continue,
        };
        // println!("2: {}", n_2);
        ret_stack.push(n_2);
    };
    ret_stack
}
fn case_3(y_sq: usize, to_next_y_sq: usize, iter_size: usize)
    -> Vec<usize> {
    //n_3 = 3x^2 - y^2 === 11 (mod 12)
    let (mut n_3, mut to_next_n_3) = (2*y_sq, 3*to_next_y_sq);
    let mut ret_stack: Vec<usize> = Vec::new();
    loop {
        n_3 += to_next_n_3;
        to_next_n_3 += 6;
        match n_3%60{
            _ if n_3 >= iter_size => break,
            11 | 23 | 47 | 59 => (),
            _ => continue,
        };
        // println!("3: {}", n_3);
        ret_stack.push(n_3);
    };
    ret_stack
}

fn prime_filter_section(min:usize, max: usize) -> Vec<bool>{
    //Sieve of Atkin
    assert!(min<max);
    let mut prime_filter = vec![false; max-min];
    if (min <= 2) & (max > 2) {prime_filter[2-min] = true;}
    if (min <= 3) & (max > 3) {prime_filter[3-min] = true;}
    if (min <= 5) & (max > 5) {prime_filter[5-min] = true;}

    let (mut y_sq, mut to_next_y_sq) = match min {
        0|1 => (1, 3),
        _ => (min*min, 2*min + 1),
    };
    let mut spawned_threads = 0;
    let (tx, rx) = mpsc::channel();
    while y_sq<max {
        if y_sq%2 == 1 {
            spawned_threads += 1;
            let (y_sq, tx) = (y_sq, tx.clone());
            thread::spawn(move || {
                tx.send(case_1(y_sq, max)).unwrap();
            });
        };
        if y_sq%3 == 1 {

            spawned_threads += 1;
            let (y_sq, to_next_y_sq, tx1) = (y_sq, to_next_y_sq, tx.clone());
            thread::spawn(move || {
                tx1.send(case_2(y_sq, max)).unwrap();
            });
            if y_sq*2<max{
                spawned_threads += 1;
                let tx2 = tx.clone();
                thread::spawn(move || {
                    tx2.send(case_3(y_sq, to_next_y_sq, max)).unwrap();
                });
            }
        };
        while{ //Do-while
            y_sq += to_next_y_sq;
            to_next_y_sq += 2;
            y_sq%6 == 0
        } {};
    };

    while spawned_threads!=0{
        for mes in rx.try_iter(){
            spawned_threads -= 1;
            for flip_i in mes{
                prime_filter[flip_i - min] ^= true;
            }
        }
    };
    //Eliminate non-squarefree numbers
    let mut n_sq = 49; // 7^2
    let mut next_n_sq = 32; //9^2 - 7^2, skip even numbers.
    while n_sq < max {
        let mut non_sq_free = n_sq;
        while non_sq_free < max {
            if non_sq_free >= min {
                prime_filter[non_sq_free - min] = false;
            }
            while{ //Do-while
                non_sq_free += n_sq + n_sq;
                (non_sq_free%3==0) | (non_sq_free%5==0)
            } {};
        };
        while{ //Do-while
            n_sq += next_n_sq;
            next_n_sq += 8;
            (n_sq%3==0) | (n_sq%5 == 0)
        } {};
    }
    prime_filter
}
#[cfg(test)]
pub fn old_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    slow_prime_filter(iter_size)
}

fn slow_prime_filter(iter_size: usize) -> std::vec::Vec<bool>{
    if iter_size < 5 {
         let mut ret = vec![false, false, true, true];
         ret.truncate(iter_size);
         return ret
     }
    let mut prime_filter = vec![true; iter_size];
    prime_filter[0] = false;
    prime_filter[1] = false;
    let mut cur_num = 2;
    'outer: loop{
        for i in (cur_num+1)..iter_size{
            if 0 == i%cur_num { prime_filter[i] = false; }
        }
        cur_num += 1;
        while !prime_filter[cur_num]{
            if cur_num*cur_num > iter_size {
                break 'outer
            }
            cur_num += 1;
        }
    };
    prime_filter
}
<|endoftext|>


<commit_before>/// Formatting macro for constructing [`Ident`]s.
///
/// [`Ident`]: `proc_macro2::Ident`
///
/// # Syntax
///
/// Syntax is copied from the [`format!`] macro, supporting both positional and
/// named arguments.
///
/// Only a limited set of formatting traits are supported. The current mapping
/// of format types to traits is:
///
/// * `{}` ⇒ [`IdentFragment`]
/// * `{:o}` ⇒ [`Octal`](`std::fmt::Octal`)
/// * `{:x}` ⇒ [`LowerHex`](`std::fmt::LowerHex`)
/// * `{:X}` ⇒ [`UpperHex`](`std::fmt::UpperHex`)
/// * `{:b}` ⇒ [`Binary`](`std::fmt::Binary`)
///
/// See [`std::fmt`] for more information.
///
/// # IdentFragment
///
/// Unlike [`format!`], this macro uses the [`IdentFragment`] formatting trait
/// by default. This trait is like `Display`, with a few differences:
///
/// * `IdentFragment` is only implemented for a limited set of types, such as
///    unsigned integers and strings.
/// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.
///
/// # Hygiene
///
/// The [`Span`] of the first [`Ident`] argument is used as the span of the
/// final identifier, falling back to [`Span::call_site`] when no identifiers
/// are provided.
///
/// ```
/// # use quote::format_ident;
/// # let ident = format_ident!("Ident");
/// // If `ident` is an Ident, the span of `my_ident` will be inherited from it.
/// let my_ident = format_ident!("My{}{}", ident, "IsCool");
/// assert_eq!(my_ident, "MyIdentIsCool");
/// ```
///
/// Alternatively, the span can be overridden by passing the `span` named
/// argument.
///
/// ```
/// # use quote::format_ident;
/// # const IGNORE_TOKENS: &'static str = stringify! {
/// let my_span = /* ... */;
/// # };
/// # let my_span = proc_macro2::Span::call_site();
/// format_ident!("MyIdent", span = my_span);
/// ```
///
/// [`Span`]: `proc_macro2::Span`
/// [`Span::call_site`]: `proc_macro2::Span::call_site`
///
/// # Panics
///
/// This method will panic if the formatted string is not a valid identifier, or
/// a formatting trait implementation returned an error.
///
/// # Examples
///
/// Composing raw and non-raw identifiers:
/// ```
/// # use quote::format_ident;
/// let my_ident = format_ident!("My{}", "Ident");
/// assert_eq!(my_ident, "MyIdent");
///
/// let raw = format_ident!("r#Raw");
/// assert_eq!(raw, "r#Raw");
///
/// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw);
/// assert_eq!(my_ident_raw, "MyIdentIsRaw");
/// ```
///
/// Integer formatting options:
/// ```
/// # use quote::format_ident;
/// let num: u32 = 10;
///
/// let decimal = format_ident!("Id_{}", num);
/// assert_eq!(decimal, "Id_10");
///
/// let octal = format_ident!("Id_{:o}", num);
/// assert_eq!(octal, "Id_12");
///
/// let binary = format_ident!("Id_{:b}", num);
/// assert_eq!(binary, "Id_1010");
///
/// let lower_hex = format_ident!("Id_{:x}", num);
/// assert_eq!(lower_hex, "Id_a");
///
/// let upper_hex = format_ident!("Id_{:X}", num);
/// assert_eq!(upper_hex, "Id_A");
/// ```
#[macro_export]
macro_rules! format_ident {
    ($fmt:expr) => {
        $crate::format_ident_impl!([
            ::std::option::Option::None,
            $fmt
        ])
    };

    ($fmt:expr, $($rest:tt)*) => {
        $crate::format_ident_impl!([
            ::std::option::Option::None,
            $fmt
        ] $($rest)*)
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! format_ident_impl {
    // Final state
    ([$span:expr, $($fmt:tt)*]) => {
        $crate::__rt::mk_ident(&format!($($fmt)*), $span)
    };

    // Span argument
    ([$old:expr, $($fmt:tt)*] span = $span:expr) => {
        $crate::format_ident_impl!([$old, $($fmt)*] span = $span,)
    };
    ([$old:expr, $($fmt:tt)*] span = $span:expr, $($rest:tt)*) => {
        $crate::format_ident_impl!([
            ::std::option::Option::Some::<$crate::__rt::Span>($span),
            $($fmt)*
        ] $($rest)*)
    };

    // Named argument
    ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr) => {
        $crate::format_ident_impl!([$span, $($fmt)*] $name = $arg,)
    };
    ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr, $($rest:tt)*) => {
        match $crate::__rt::IdentFragmentAdapter(&$arg) {
            arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, $name = arg] $($rest)*),
        }
    };

    // Positional argument
    ([$span:expr, $($fmt:tt)*] $arg:expr) => {
        $crate::format_ident_impl!([$span, $($fmt)*] $arg,)
    };
    ([$span:expr, $($fmt:tt)*] $arg:expr, $($rest:tt)*) => {
        match $crate::__rt::IdentFragmentAdapter(&$arg) {
            arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, arg] $($rest)*),
        }
    };
}
<commit_msg>Remove format_ident panic case from doc<commit_after>/// Formatting macro for constructing [`Ident`]s.
///
/// [`Ident`]: `proc_macro2::Ident`
///
/// # Syntax
///
/// Syntax is copied from the [`format!`] macro, supporting both positional and
/// named arguments.
///
/// Only a limited set of formatting traits are supported. The current mapping
/// of format types to traits is:
///
/// * `{}` ⇒ [`IdentFragment`]
/// * `{:o}` ⇒ [`Octal`](`std::fmt::Octal`)
/// * `{:x}` ⇒ [`LowerHex`](`std::fmt::LowerHex`)
/// * `{:X}` ⇒ [`UpperHex`](`std::fmt::UpperHex`)
/// * `{:b}` ⇒ [`Binary`](`std::fmt::Binary`)
///
/// See [`std::fmt`] for more information.
///
/// # IdentFragment
///
/// Unlike [`format!`], this macro uses the [`IdentFragment`] formatting trait
/// by default. This trait is like `Display`, with a few differences:
///
/// * `IdentFragment` is only implemented for a limited set of types, such as
///    unsigned integers and strings.
/// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.
///
/// # Hygiene
///
/// The [`Span`] of the first [`Ident`] argument is used as the span of the
/// final identifier, falling back to [`Span::call_site`] when no identifiers
/// are provided.
///
/// ```
/// # use quote::format_ident;
/// # let ident = format_ident!("Ident");
/// // If `ident` is an Ident, the span of `my_ident` will be inherited from it.
/// let my_ident = format_ident!("My{}{}", ident, "IsCool");
/// assert_eq!(my_ident, "MyIdentIsCool");
/// ```
///
/// Alternatively, the span can be overridden by passing the `span` named
/// argument.
///
/// ```
/// # use quote::format_ident;
/// # const IGNORE_TOKENS: &'static str = stringify! {
/// let my_span = /* ... */;
/// # };
/// # let my_span = proc_macro2::Span::call_site();
/// format_ident!("MyIdent", span = my_span);
/// ```
///
/// [`Span`]: `proc_macro2::Span`
/// [`Span::call_site`]: `proc_macro2::Span::call_site`
///
/// # Panics
///
/// This method will panic if the resulting formatted string is not a valid
/// identifier.
///
/// # Examples
///
/// Composing raw and non-raw identifiers:
/// ```
/// # use quote::format_ident;
/// let my_ident = format_ident!("My{}", "Ident");
/// assert_eq!(my_ident, "MyIdent");
///
/// let raw = format_ident!("r#Raw");
/// assert_eq!(raw, "r#Raw");
///
/// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw);
/// assert_eq!(my_ident_raw, "MyIdentIsRaw");
/// ```
///
/// Integer formatting options:
/// ```
/// # use quote::format_ident;
/// let num: u32 = 10;
///
/// let decimal = format_ident!("Id_{}", num);
/// assert_eq!(decimal, "Id_10");
///
/// let octal = format_ident!("Id_{:o}", num);
/// assert_eq!(octal, "Id_12");
///
/// let binary = format_ident!("Id_{:b}", num);
/// assert_eq!(binary, "Id_1010");
///
/// let lower_hex = format_ident!("Id_{:x}", num);
/// assert_eq!(lower_hex, "Id_a");
///
/// let upper_hex = format_ident!("Id_{:X}", num);
/// assert_eq!(upper_hex, "Id_A");
/// ```
#[macro_export]
macro_rules! format_ident {
    ($fmt:expr) => {
        $crate::format_ident_impl!([
            ::std::option::Option::None,
            $fmt
        ])
    };

    ($fmt:expr, $($rest:tt)*) => {
        $crate::format_ident_impl!([
            ::std::option::Option::None,
            $fmt
        ] $($rest)*)
    };
}

#[macro_export]
#[doc(hidden)]
macro_rules! format_ident_impl {
    // Final state
    ([$span:expr, $($fmt:tt)*]) => {
        $crate::__rt::mk_ident(&format!($($fmt)*), $span)
    };

    // Span argument
    ([$old:expr, $($fmt:tt)*] span = $span:expr) => {
        $crate::format_ident_impl!([$old, $($fmt)*] span = $span,)
    };
    ([$old:expr, $($fmt:tt)*] span = $span:expr, $($rest:tt)*) => {
        $crate::format_ident_impl!([
            ::std::option::Option::Some::<$crate::__rt::Span>($span),
            $($fmt)*
        ] $($rest)*)
    };

    // Named argument
    ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr) => {
        $crate::format_ident_impl!([$span, $($fmt)*] $name = $arg,)
    };
    ([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr, $($rest:tt)*) => {
        match $crate::__rt::IdentFragmentAdapter(&$arg) {
            arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, $name = arg] $($rest)*),
        }
    };

    // Positional argument
    ([$span:expr, $($fmt:tt)*] $arg:expr) => {
        $crate::format_ident_impl!([$span, $($fmt)*] $arg,)
    };
    ([$span:expr, $($fmt:tt)*] $arg:expr, $($rest:tt)*) => {
        match $crate::__rt::IdentFragmentAdapter(&$arg) {
            arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, arg] $($rest)*),
        }
    };
}
<|endoftext|>


<commit_before>
use std::io::Read;  // Trait providing read_to_string()

use std::env;

use hyper;
use serde;
use serde_json;

use Version;
use Projects;
use Groups;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Debug)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,
}

impl GitLab {

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                },
                Err(_) => hyper::Client::new(),
            },
            pagination: Pagination {page: 1, per_page: 20},
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}&page={}&per_page={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token,
                                self.pagination.page,
                                self.pagination.per_page)
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        // self.get("version")
        let url = self.build_url("version");
        // Close connections after each GET.
        let res = self.client.get(&url).header(hyper::header::Connection::close()).send();

        res
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn get<T>(&self, command: &str) -> Result<T, serde_json::Error>
            where T: serde::Deserialize {

        let url = self.build_url(command);
        let mut res: hyper::client::Response =
                        self.client
                        .get(&url)
                        .header(hyper::header::Connection::close())
                        .send()
                        .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        serde_json::from_str(&body.as_str())
    }

    pub fn version(&self) -> Result<Version, serde_json::Error> {
        self.get("version")
    }

    pub fn groups(&self) -> Result<Groups, serde_json::Error> {
        self.get("groups")
    }

    pub fn projects(&self) -> Result<Projects, serde_json::Error> {
        self.get("projects")
    }
}

#[cfg(test)]
mod tests {
    use std::env;
    use gitlab::GitLab;
    use gitlab::Pagination;

    #[test]
    fn list_groups() {
        let token = match env::var("GITLAB_TOKEN") {
            Ok(val) => val,
            Err(_)  => panic!("Please set environment variable 'GITLAB_TOKEN'"),
        };

        let mut gl = GitLab::new_https("gitlab.com", &token);
        gl.set_pagination(Pagination{page: 1, per_page: 100});
        println!("gl: {:?}", gl);

        let groups = gl.groups().unwrap();
        println!("groups: {:?}", groups);
    }

    #[test]
    fn list_projects() {
        let token = match env::var("GITLAB_TOKEN") {
            Ok(val) => val,
            Err(_)  => panic!("Please set environment variable 'GITLAB_TOKEN'"),
        };

        let mut gl = GitLab::new_https("gitlab.com", &token);
        // for i in 1..82 {
        //     gl.set_pagination(Pagination{page: i, per_page: 1});
        //     println!("projects: {:?}", gl.projects().unwrap());
        // }
        gl.set_pagination(Pagination{page: 1, per_page: 100});
        let projects = gl.projects().unwrap();
        for project in projects {
            println!("{:?}", project.path_with_namespace);
        }
    }
}
<commit_msg>Cleanup<commit_after>
use std::io::Read;  // Trait providing read_to_string()

use std::env;

use hyper;
use serde;
use serde_json;

use Version;
use Projects;
use Groups;

pub const API_VERSION: u16 = 3;

#[derive(Debug)]
pub struct Pagination {
    pub page: u16,
    pub per_page: u16,
}

#[derive(Debug)]
pub struct GitLab {
    scheme: String,
    domain: String,
    port: u16,
    private_token: String,
    client: hyper::Client,
    pagination: Pagination,
}

impl GitLab {

    pub fn new(scheme: &str, domain: &str, port: u16, private_token: &str) -> GitLab {
        GitLab {
            scheme: scheme.to_string(),
            domain: domain.to_string(),
            port:   port,
            private_token: private_token.to_string(),
            client: match env::var("HTTP_PROXY") {
                Ok(proxy) => {
                    let proxy: Vec<&str> = proxy.trim_left_matches("http://").split(':').collect();
                    let hostname = proxy[0].to_string();
                    let port = proxy[1];

                    hyper::Client::with_http_proxy(hostname, port.parse().unwrap())
                },
                Err(_) => hyper::Client::new(),
            },
            pagination: Pagination {page: 1, per_page: 20},
        }
    }

    pub fn new_http(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("http", &domain, 80, &private_token)
    }

    pub fn new_https(domain: &str, private_token: &str) -> GitLab {
        GitLab::new("https", &domain, 443, &private_token)
    }

    pub fn build_url(&self, command: &str) -> String {
        format!("{}://{}:{}/api/v{}/{}?private_token={}&page={}&per_page={}",
                                self.scheme,
                                self.domain,
                                self.port,
                                API_VERSION,
                                command,
                                self.private_token,
                                self.pagination.page,
                                self.pagination.per_page)
    }

    pub fn attempt_connection(&self) -> Result<hyper::client::Response, hyper::Error> {
        let url = self.build_url("version");
        // Close connections after each GET.
        let res = self.client.get(&url).header(hyper::header::Connection::close()).send();

        res
    }

    pub fn set_pagination(&mut self, pagination: Pagination) {
        self.pagination = pagination;
    }

    pub fn get<T>(&self, command: &str) -> Result<T, serde_json::Error>
            where T: serde::Deserialize {

        let url = self.build_url(command);
        let mut res: hyper::client::Response =
                        self.client
                        .get(&url)
                        .header(hyper::header::Connection::close())
                        .send()
                        .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        serde_json::from_str(&body.as_str())
    }

    pub fn version(&self) -> Result<Version, serde_json::Error> {
        self.get("version")
    }

    pub fn groups(&self) -> Result<Groups, serde_json::Error> {
        self.get("groups")
    }

    pub fn projects(&self) -> Result<Projects, serde_json::Error> {
        self.get("projects")
    }
}

#[cfg(test)]
mod tests {
    use std::env;
    use gitlab::GitLab;
    use gitlab::Pagination;

    #[test]
    fn list_groups() {
        let token = match env::var("GITLAB_TOKEN") {
            Ok(val) => val,
            Err(_)  => panic!("Please set environment variable 'GITLAB_TOKEN'"),
        };

        let mut gl = GitLab::new_https("gitlab.com", &token);
        gl.set_pagination(Pagination{page: 1, per_page: 100});
        println!("gl: {:?}", gl);

        let groups = gl.groups().unwrap();
        println!("groups: {:?}", groups);
    }

    #[test]
    fn list_projects() {
        let token = match env::var("GITLAB_TOKEN") {
            Ok(val) => val,
            Err(_)  => panic!("Please set environment variable 'GITLAB_TOKEN'"),
        };

        let mut gl = GitLab::new_https("gitlab.com", &token);
        // for i in 1..82 {
        //     gl.set_pagination(Pagination{page: i, per_page: 1});
        //     println!("projects: {:?}", gl.projects().unwrap());
        // }
        gl.set_pagination(Pagination{page: 1, per_page: 100});
        let projects = gl.projects().unwrap();
        for project in projects {
            println!("{:?}", project.path_with_namespace);
        }
    }
}
<|endoftext|>


<commit_before>use std::default::Default;
use std::hash::Hasher;
use rand::{self,Rng};
use super::murmur_hash64a;
use std::hash::BuildHasher;

/// MurmurHash2 can also be used as the hash algorithm in a HashMap
/// (or similar). For this it implements the std::hash::Hasher trait.
///
/// # Basic Example
///
/// ```rust
/// # #![feature(hashmap_hasher)]
/// # use std::collections::HashMap;
/// # use std::default::Default;
/// # use murmurhash64::{MurmurHasher,RandomMurmurState};
/// # use std::collections::hash_state::DefaultState;
/// let mut hashmap : HashMap<_, _, DefaultState<MurmurHasher>> = Default::default();
/// hashmap.insert("abc", 123);
/// hashmap.insert("def", 456);
/// assert_eq!(Some(&123), hashmap.get("abc"));
/// assert_eq!(Some(&456), hashmap.get("def"));
///
/// let mut hashmap : HashMap<_, _, RandomMurmurState> = Default::default();
/// hashmap.insert("abc", 123);
/// hashmap.insert("def", 456);
/// assert_eq!(Some(&123), hashmap.get("abc"));
/// assert_eq!(Some(&456), hashmap.get("def"));
/// ```

pub struct MurmurHasher {
    state: u64
}

impl MurmurHasher {
    pub fn new() -> MurmurHasher {
        MurmurHasher { state: 0 }
    }

    pub fn with_seed(seed: u64) -> MurmurHasher {
        MurmurHasher { state: seed }
    }
}

impl Default for MurmurHasher {
    fn default() -> MurmurHasher {
        MurmurHasher::new()
    }
}

impl Hasher for MurmurHasher {
    fn finish(&self) -> u64 {
        self.state
    }

    fn write(&mut self, buf: &[u8]) {
        self.state = murmur_hash64a(buf, self.state)
    }
}

pub struct MurmurState(u64);

impl MurmurState {
    pub fn new() -> MurmurState {
        MurmurState(0)
    }
}

impl Default for MurmurState {
    fn default() -> MurmurState { MurmurState::new() }
}

impl BuildHasher for MurmurState {
    type Hasher = MurmurHasher;
    fn build_hasher(&self) -> MurmurHasher {
        MurmurHasher::with_seed(self.0)
    }
}

pub struct RandomMurmurState(u64);

impl RandomMurmurState {
    fn new() -> RandomMurmurState {
        RandomMurmurState(rand::thread_rng().gen())
    }
}

impl Default for RandomMurmurState {
    fn default() -> RandomMurmurState { RandomMurmurState::new() }
}

impl BuildHasher for RandomMurmurState {
    type Hasher = MurmurHasher;
    fn build_hasher(&self) -> MurmurHasher {
        MurmurHasher::with_seed(self.0)
    }
}

#[cfg(test)]
mod test {
    use super::{MurmurState,MurmurHasher,RandomMurmurState};
    use std::collections::HashMap;

    #[test]
    fn hashmap_str() {
        let s = MurmurState::new();
        let mut hashmap : HashMap<_, _, MurmurState> = HashMap::with_hasher(s);
        hashmap.insert("abc", 123);
        hashmap.insert("def", 456);
        assert_eq!(Some(&123), hashmap.get("abc"));
        assert_eq!(Some(&456), hashmap.get("def"));
    }

    #[test]
    fn hashmap_uint() {
        let s = MurmurState::new();
        let mut hashmap : HashMap<_, _, MurmurState> = HashMap::with_hasher(s);
        hashmap.insert(123, "abc");
        hashmap.insert(456, "def");
        assert_eq!(Some(&"abc"), hashmap.get(&123));
        assert_eq!(Some(&"def"), hashmap.get(&456));
    }

    #[test]
    fn hashmap_default() {
        use std::hash::BuildHasherDefault;

        let mut hash: HashMap<_, _, BuildHasherDefault<MurmurHasher>> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));

        let mut hash: HashMap<_, _, RandomMurmurState> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }
}

<commit_msg>docs: Fix documentation tests<commit_after>use std::default::Default;
use std::hash::Hasher;
use rand::{self,Rng};
use super::murmur_hash64a;
use std::hash::BuildHasher;

/// MurmurHash2 can also be used as the hash algorithm in a HashMap
/// (or similar).
/// It implements the necessary traits.
///
/// # Basic Example
///
/// ```rust
/// # use std::collections::HashMap;
/// # use std::default::Default;
/// # use murmurhash64::{MurmurHasher, MurmurState, RandomMurmurState};
/// let mut hashmap : HashMap<_, _, MurmurState> = Default::default();
/// hashmap.insert("abc", 123);
/// hashmap.insert("def", 456);
/// assert_eq!(Some(&123), hashmap.get("abc"));
/// assert_eq!(Some(&456), hashmap.get("def"));
///
/// let mut hashmap : HashMap<_, _, RandomMurmurState> = Default::default();
/// hashmap.insert("abc", 123);
/// hashmap.insert("def", 456);
/// assert_eq!(Some(&123), hashmap.get("abc"));
/// assert_eq!(Some(&456), hashmap.get("def"));
/// ```

pub struct MurmurHasher {
    state: u64
}

impl MurmurHasher {
    pub fn new() -> MurmurHasher {
        MurmurHasher { state: 0 }
    }

    pub fn with_seed(seed: u64) -> MurmurHasher {
        MurmurHasher { state: seed }
    }
}

impl Default for MurmurHasher {
    fn default() -> MurmurHasher {
        MurmurHasher::new()
    }
}

impl Hasher for MurmurHasher {
    fn finish(&self) -> u64 {
        self.state
    }

    fn write(&mut self, buf: &[u8]) {
        self.state = murmur_hash64a(buf, self.state)
    }
}

pub struct MurmurState(u64);

impl MurmurState {
    pub fn new() -> MurmurState {
        MurmurState(0)
    }
}

impl Default for MurmurState {
    fn default() -> MurmurState { MurmurState::new() }
}

impl BuildHasher for MurmurState {
    type Hasher = MurmurHasher;
    fn build_hasher(&self) -> MurmurHasher {
        MurmurHasher::with_seed(self.0)
    }
}

pub struct RandomMurmurState(u64);

impl RandomMurmurState {
    fn new() -> RandomMurmurState {
        RandomMurmurState(rand::thread_rng().gen())
    }
}

impl Default for RandomMurmurState {
    fn default() -> RandomMurmurState { RandomMurmurState::new() }
}

impl BuildHasher for RandomMurmurState {
    type Hasher = MurmurHasher;
    fn build_hasher(&self) -> MurmurHasher {
        MurmurHasher::with_seed(self.0)
    }
}

#[cfg(test)]
mod test {
    use super::{MurmurState,MurmurHasher,RandomMurmurState};
    use std::collections::HashMap;

    #[test]
    fn hashmap_str() {
        let s = MurmurState::new();
        let mut hashmap : HashMap<_, _, MurmurState> = HashMap::with_hasher(s);
        hashmap.insert("abc", 123);
        hashmap.insert("def", 456);
        assert_eq!(Some(&123), hashmap.get("abc"));
        assert_eq!(Some(&456), hashmap.get("def"));
    }

    #[test]
    fn hashmap_uint() {
        let s = MurmurState::new();
        let mut hashmap : HashMap<_, _, MurmurState> = HashMap::with_hasher(s);
        hashmap.insert(123, "abc");
        hashmap.insert(456, "def");
        assert_eq!(Some(&"abc"), hashmap.get(&123));
        assert_eq!(Some(&"def"), hashmap.get(&456));
    }

    #[test]
    fn hashmap_default() {
        use std::hash::BuildHasherDefault;

        let mut hash: HashMap<_, _, BuildHasherDefault<MurmurHasher>> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));

        let mut hash: HashMap<_, _, RandomMurmurState> = Default::default();
        hash.insert(42, "the answer");
        assert_eq!(hash.get(&42), Some(&"the answer"));
    }

    #[test]
    fn hashmap_build_hasher_default() {
        use std::hash::BuildHasherDefault;
        type MyHasher = BuildHasherDefault<MurmurHasher>;

        let mut map: HashMap<_, _, MyHasher> = HashMap::default();
        map.insert(42, "the answer");
        assert_eq!(map.get(&42), Some(&"the answer"));
    }
}

<|endoftext|>