<commit_before>use super::*;

use std::collections::BTreeMap;

#[derive(Serialize)]
pub struct Entry {
    pub title: String,
    pub guid: String,
    pub feed_name: Option<String>,
    pub description: Option<String>,
    pub link: Option<String>,
    pub color: Option<String>,
    pub image_url: Option<String>,
    pub timestamp: Option<u64>,
    pub extra: Option<Json>,
}

impl Entry {
    pub fn new(title: &str, guid: &str) -> Entry {
        Entry{
            title: title.to_string(),
            guid: guid.to_string(),
            feed_name: None,
            description: None,
            link: None,
            color: None,
            image_url: None,
            timestamp: None,
            extra: None,
        }
    }

    pub fn description(mut self, description: &str) -> Entry {
        self.description = Some(description.to_string());
        self
    }

    pub fn link(mut self, link: &str) -> Entry {
        self.link = Some(link.to_string());
        self
    }

    pub fn color(mut self, color: &str) -> Entry {
        self.color = Some(color.to_string());
        self
    }

    pub fn image_url(mut self, image_url: &str) -> Entry {
        self.image_url = Some(image_url.to_string());
        self
    }

    pub fn timestamp(mut self, timestamp: u64) -> Entry {
        self.timestamp = Some(timestamp);
        self
    }

    pub fn extra(mut self, extra: Json) -> Entry {
        self.extra = Some(extra);
        self
    }

    pub fn set_description(mut self, description: Option<String>) -> Entry {
        self.description = description;
        self
    }

    pub fn set_link(mut self, link: Option<String>) -> Entry {
        self.link = link;
        self
    }

    pub fn set_color(mut self, color: Option<String>) -> Entry {
        self.color = color;
        self
    }

    pub fn set_image_url(mut self, image_url: Option<String>) -> Entry {
        self.image_url = image_url;
        self
    }

    pub fn set_timestamp(mut self, timestamp: Option<u64>) -> Entry {
        self.timestamp = timestamp;
        self
    }

    pub fn set_extra(mut self, extra: Option<Json>) -> Entry {
        self.extra = extra;
        self
    }
}

#[derive(Serialize)]
pub struct Feed {
    pub status: Vec<Entry>,
    pub notifications: Vec<Entry>,
}

impl Feed {
    pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut Entry> {
        self.status.iter_mut().chain(self.notifications.iter_mut())
    }

    pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a Entry> {
        self.status.iter().chain(self.notifications.iter())
    }

    pub fn new() -> Feed {
        Feed {
            status: Vec::new(),
            notifications: Vec::new()
        }
    }

    pub fn from_err(err: &str, desc: &str) -> Feed {
        Feed {
            status: vec![
                Entry::new(err, &hash(&(timestamp(), err, desc)))
                    .description(desc)
                    .color("#FF0000")
                    .timestamp(timestamp())
            ],
            notifications: Vec::new(),
        }
    }
}

pub type Map<T> = BTreeMap<String, T>;
pub type Feeds = Map<Feed>;

pub fn fetch_feeds() {
    let mut feeds = BTreeMap::new();

    let config = load_config().unwrap();

    for (name, data) in &config.feeds {
        let feed = fetch_feed(name, data);
        feeds.insert(name.clone(), feed);
    }

    *get_feeds() = feeds;
}

pub fn start_fetch_thread(interval: Duration) -> thread::JoinHandle<()> {
    thread::spawn(move || {
        thread::sleep(interval);
        fetch_feeds();
    })
}
<commit_msg>Changed JSON names to less rusty.<commit_after>use super::*;

use std::collections::BTreeMap;

#[derive(Serialize)]
pub struct Entry {
    pub title: String,
    pub guid: String,
    #[serde(rename="feedName")]
    pub feed_name: Option<String>,
    pub description: Option<String>,
    pub link: Option<String>,
    pub color: Option<String>,
    #[serde(rename="imageURL")]
    pub image_url: Option<String>,
    pub timestamp: Option<u64>,
    pub extra: Option<Json>,
}

impl Entry {
    pub fn new(title: &str, guid: &str) -> Entry {
        Entry{
            title: title.to_string(),
            guid: guid.to_string(),
            feed_name: None,
            description: None,
            link: None,
            color: None,
            image_url: None,
            timestamp: None,
            extra: None,
        }
    }

    pub fn description(mut self, description: &str) -> Entry {
        self.description = Some(description.to_string());
        self
    }

    pub fn link(mut self, link: &str) -> Entry {
        self.link = Some(link.to_string());
        self
    }

    pub fn color(mut self, color: &str) -> Entry {
        self.color = Some(color.to_string());
        self
    }

    pub fn image_url(mut self, image_url: &str) -> Entry {
        self.image_url = Some(image_url.to_string());
        self
    }

    pub fn timestamp(mut self, timestamp: u64) -> Entry {
        self.timestamp = Some(timestamp);
        self
    }

    pub fn extra(mut self, extra: Json) -> Entry {
        self.extra = Some(extra);
        self
    }

    pub fn set_description(mut self, description: Option<String>) -> Entry {
        self.description = description;
        self
    }

    pub fn set_link(mut self, link: Option<String>) -> Entry {
        self.link = link;
        self
    }

    pub fn set_color(mut self, color: Option<String>) -> Entry {
        self.color = color;
        self
    }

    pub fn set_image_url(mut self, image_url: Option<String>) -> Entry {
        self.image_url = image_url;
        self
    }

    pub fn set_timestamp(mut self, timestamp: Option<u64>) -> Entry {
        self.timestamp = timestamp;
        self
    }

    pub fn set_extra(mut self, extra: Option<Json>) -> Entry {
        self.extra = extra;
        self
    }
}

#[derive(Serialize)]
pub struct Feed {
    pub status: Vec<Entry>,
    pub notifications: Vec<Entry>,
}

impl Feed {
    pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut Entry> {
        self.status.iter_mut().chain(self.notifications.iter_mut())
    }

    pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a Entry> {
        self.status.iter().chain(self.notifications.iter())
    }

    pub fn new() -> Feed {
        Feed {
            status: Vec::new(),
            notifications: Vec::new()
        }
    }

    pub fn from_err(err: &str, desc: &str) -> Feed {
        Feed {
            status: vec![
                Entry::new(err, &hash(&(timestamp(), err, desc)))
                    .description(desc)
                    .color("#FF0000")
                    .timestamp(timestamp())
            ],
            notifications: Vec::new(),
        }
    }
}

pub type Map<T> = BTreeMap<String, T>;
pub type Feeds = Map<Feed>;

pub fn fetch_feeds() {
    let mut feeds = BTreeMap::new();

    let config = load_config().unwrap();

    for (name, data) in &config.feeds {
        let feed = fetch_feed(name, data);
        feeds.insert(name.clone(), feed);
    }

    *get_feeds() = feeds;
}

pub fn start_fetch_thread(interval: Duration) -> thread::JoinHandle<()> {
    thread::spawn(move || {
        thread::sleep(interval);
        fetch_feeds();
    })
}
<|endoftext|>


<commit_before>use engine::{Tile, Map};
use util::units::{Size};

use std::io;

pub trait IntoMap {
    fn into_map(self) -> MapBuildResult;
}

impl IntoMap for Vec<Vec<Tile>> {
    fn into_map(self) -> MapBuildResult {
        // TODO: check dimensions are the same
        let size = Size::new(self.len() as i32, self[0].len() as i32);

        Ok(Map {
            tiles: self,
            size: size,
        })
    }
}

fn build_line(l: &&str) -> Vec<Tile> {
    l.chars().map(|c| Tile::from_char(c)).collect()
}

impl IntoMap for String {
    fn into_map(self) -> MapBuildResult {
        let lines: Vec<&str> = self.split('\n').collect();

        if !lines.iter().all(|x| x.len() == lines[0].len()) { return Err("Different length lines") };

        let tiles: Vec<Vec<Tile>> = lines.iter().map(build_line).collect();

        Ok(Map::new(tiles))
    }
}

impl IntoMap for Path {
    fn into_map(self) -> MapBuildResult {
        let mut level_file = io::File::open(&self);
        let level_string = level_file.read_to_string().ok().expect("Failed to read level file");

        Ok(Map::new(level_string))
    }
}

pub type MapBuildResult = Result<Map, &'static str>;
<commit_msg>std::io -> std::old_io<commit_after>use engine::{Tile, Map};
use util::units::{Size};

use std::{old_io, fmt};

pub trait IntoMap {
    fn into_map(self) -> MapBuildResult;
}

impl IntoMap for Vec<Vec<Tile>> {
    fn into_map(self) -> MapBuildResult {
        // TODO: check dimensions are the same
        let size = Size::new(self.len() as i32, self[0].len() as i32);

        Ok(Map {
            tiles: self,
            size: size,
        })
    }
}

fn build_line(l: &&str) -> Vec<Tile> {
    l.chars().map(|c| Tile::from_char(c)).collect()
}

impl IntoMap for String {
    fn into_map(self) -> MapBuildResult {
        let lines: Vec<&str> = self.split('\n').collect();

        if !lines.iter().all(|x| x.len() == lines[0].len()) { return Err("Different length lines") };

        let tiles: Vec<Vec<Tile>> = lines.iter().map(build_line).collect();

        Ok(Map::new(tiles))
    }
}

impl IntoMap for Path {
    fn into_map(self) -> MapBuildResult {
        let mut level_file = old_io::File::open(&self);
        let level_string = level_file.read_to_string().ok().expect("Failed to read level file");

        Ok(Map::new(level_string))
    }
}

pub type MapBuildResult = Result<Map, &'static str>;
<|endoftext|>


<commit_before>//! Free functions that create iterator adaptors or call iterator methods.
//!
//! The benefit of free functions is that they accept any [`IntoIterator`] as
//! argument, so the resulting code may be easier to read.

#[cfg(feature = "use_alloc")]
use std::fmt::Display;
use std::iter::{self, Zip};
#[cfg(feature = "use_alloc")]
type VecIntoIter<T> = alloc::vec::IntoIter<T>;

#[cfg(feature = "use_alloc")]
use alloc::{
    string::String,
};

use crate::Itertools;
use crate::intersperse::{Intersperse, IntersperseWith};

pub use crate::adaptors::{
    interleave,
    merge,
    put_back,
};
#[cfg(feature = "use_alloc")]
pub use crate::put_back_n_impl::put_back_n;
#[cfg(feature = "use_alloc")]
pub use crate::multipeek_impl::multipeek;
#[cfg(feature = "use_alloc")]
pub use crate::peek_nth::peek_nth;
#[cfg(feature = "use_alloc")]
pub use crate::kmerge_impl::kmerge;
pub use crate::zip_eq_impl::zip_eq;
pub use crate::merge_join::merge_join_by;
#[cfg(feature = "use_alloc")]
pub use crate::rciter_impl::rciter;

/// Iterate `iterable` with a particular value inserted between each element.
///
/// [`IntoIterator`] enabled version of [`Iterator::intersperse`].
///
/// ```
/// use itertools::intersperse;
///
/// itertools::assert_equal(intersperse((0..3), 8), vec![0, 8, 1, 8, 2]);
/// ```
pub fn intersperse<I>(iterable: I, element: I::Item) -> Intersperse<I::IntoIter>
    where I: IntoIterator,
          <I as IntoIterator>::Item: Clone
{
    Itertools::intersperse(iterable.into_iter(), element)
}

/// Iterate `iterable` with a particular value created by a function inserted
/// between each element.
///
/// [`IntoIterator`] enabled version of [`Iterator::intersperse_with`].
///
/// ```
/// use itertools::intersperse_with;
///
/// let mut i = 10;
/// itertools::assert_equal(intersperse_with((0..3), || { i -= 1; i }), vec![0, 9, 1, 8, 2]);
/// assert_eq!(i, 8);
/// ```
pub fn intersperse_with<I, F>(iterable: I, element: F) -> IntersperseWith<I::IntoIter, F>
    where I: IntoIterator,
          F: FnMut() -> I::Item
{
    Itertools::intersperse_with(iterable.into_iter(), element)
}

/// Iterate `iterable` with a running index.
///
/// [`IntoIterator`] enabled version of [`Iterator::enumerate`].
///
/// ```
/// use itertools::enumerate;
///
/// for (i, elt) in enumerate(&[1, 2, 3]) {
///     /* loop body */
/// }
/// ```
pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter>
    where I: IntoIterator
{
    iterable.into_iter().enumerate()
}

/// Iterate `iterable` in reverse.
///
/// [`IntoIterator`] enabled version of [`Iterator::rev`].
///
/// ```
/// use itertools::rev;
///
/// for elt in rev(&[1, 2, 3]) {
///     /* loop body */
/// }
/// ```
pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter>
    where I: IntoIterator,
          I::IntoIter: DoubleEndedIterator
{
    iterable.into_iter().rev()
}

/// Iterate `i` and `j` in lock step.
///
/// [`IntoIterator`] enabled version of [`Iterator::zip`].
///
/// ```
/// use itertools::zip;
///
/// let data = [1, 2, 3, 4, 5];
/// for (a, b) in zip(&data, &data[1..]) {
///     /* loop body */
/// }
/// ```
pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter>
    where I: IntoIterator,
          J: IntoIterator
{
    i.into_iter().zip(j)
}

/// Create an iterator that first iterates `i` and then `j`.
///
/// [`IntoIterator`] enabled version of [`Iterator::chain`].
///
/// ```
/// use itertools::chain;
///
/// for elt in chain(&[1, 2, 3], &[4]) {
///     /* loop body */
/// }
/// ```
pub fn chain<I, J>(i: I, j: J) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
    where I: IntoIterator,
          J: IntoIterator<Item = I::Item>
{
    i.into_iter().chain(j)
}

/// Create an iterator that clones each element from &T to T
///
/// [`IntoIterator`] enabled version of [`Iterator::cloned`].
///
/// ```
/// use itertools::cloned;
///
/// assert_eq!(cloned(b"abc").next(), Some(b'a'));
/// ```
pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned<I::IntoIter>
    where I: IntoIterator<Item=&'a T>,
          T: Clone,
{
    iterable.into_iter().cloned()
}

/// Perform a fold operation over the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::fold`].
///
/// ```
/// use itertools::fold;
///
/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.);
/// ```
pub fn fold<I, B, F>(iterable: I, init: B, f: F) -> B
    where I: IntoIterator,
          F: FnMut(B, I::Item) -> B
{
    iterable.into_iter().fold(init, f)
}

/// Test whether the predicate holds for all elements in the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::all`].
///
/// ```
/// use itertools::all;
///
/// assert!(all(&[1, 2, 3], |elt| *elt > 0));
/// ```
pub fn all<I, F>(iterable: I, f: F) -> bool
    where I: IntoIterator,
          F: FnMut(I::Item) -> bool
{
    iterable.into_iter().all(f)
}

/// Test whether the predicate holds for any elements in the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::any`].
///
/// ```
/// use itertools::any;
///
/// assert!(any(&[0, -1, 2], |elt| *elt > 0));
/// ```
pub fn any<I, F>(iterable: I, f: F) -> bool
    where I: IntoIterator,
          F: FnMut(I::Item) -> bool
{
    iterable.into_iter().any(f)
}

/// Return the maximum value of the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::max`].
///
/// ```
/// use itertools::max;
///
/// assert_eq!(max(0..10), Some(9));
/// ```
pub fn max<I>(iterable: I) -> Option<I::Item>
    where I: IntoIterator,
          I::Item: Ord
{
    iterable.into_iter().max()
}

/// Return the minimum value of the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::min`].
///
/// ```
/// use itertools::min;
///
/// assert_eq!(min(0..10), Some(0));
/// ```
pub fn min<I>(iterable: I) -> Option<I::Item>
    where I: IntoIterator,
          I::Item: Ord
{
    iterable.into_iter().min()
}

/// Combine all iterator elements into one String, separated by `sep`.
///
/// [`IntoIterator`] enabled version of [`Itertools::join`].
///
/// ```
/// use itertools::join;
///
/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3");
/// ```
#[cfg(feature = "use_alloc")]
pub fn join<I>(iterable: I, sep: &str) -> String
    where I: IntoIterator,
          I::Item: Display
{
    iterable.into_iter().join(sep)
}

/// Sort all iterator elements into a new iterator in ascending order.
///
/// [`IntoIterator`] enabled version of [`Itertools::sorted`].
///
/// ```
/// use itertools::sorted;
/// use itertools::assert_equal;
///
/// assert_equal(sorted("rust".chars()), "rstu".chars());
/// ```
#[cfg(feature = "use_alloc")]
pub fn sorted<I>(iterable: I) -> VecIntoIter<I::Item>
    where I: IntoIterator,
          I::Item: Ord
{
    iterable.into_iter().sorted()
}

<commit_msg>Added body to free::zip<commit_after>//! Free functions that create iterator adaptors or call iterator methods.
//!
//! The benefit of free functions is that they accept any [`IntoIterator`] as
//! argument, so the resulting code may be easier to read.

#[cfg(feature = "use_alloc")]
use std::fmt::Display;
use std::iter::{self, Zip};
#[cfg(feature = "use_alloc")]
type VecIntoIter<T> = alloc::vec::IntoIter<T>;

#[cfg(feature = "use_alloc")]
use alloc::string::String;

use crate::intersperse::{Intersperse, IntersperseWith};
use crate::Itertools;

pub use crate::adaptors::{interleave, merge, put_back};
#[cfg(feature = "use_alloc")]
pub use crate::kmerge_impl::kmerge;
pub use crate::merge_join::merge_join_by;
#[cfg(feature = "use_alloc")]
pub use crate::multipeek_impl::multipeek;
#[cfg(feature = "use_alloc")]
pub use crate::peek_nth::peek_nth;
#[cfg(feature = "use_alloc")]
pub use crate::put_back_n_impl::put_back_n;
#[cfg(feature = "use_alloc")]
pub use crate::rciter_impl::rciter;
pub use crate::zip_eq_impl::zip_eq;

/// Iterate `iterable` with a particular value inserted between each element.
///
/// [`IntoIterator`] enabled version of [`Iterator::intersperse`].
///
/// ```
/// use itertools::intersperse;
///
/// itertools::assert_equal(intersperse((0..3), 8), vec![0, 8, 1, 8, 2]);
/// ```
pub fn intersperse<I>(iterable: I, element: I::Item) -> Intersperse<I::IntoIter>
where
    I: IntoIterator,
    <I as IntoIterator>::Item: Clone,
{
    Itertools::intersperse(iterable.into_iter(), element)
}

/// Iterate `iterable` with a particular value created by a function inserted
/// between each element.
///
/// [`IntoIterator`] enabled version of [`Iterator::intersperse_with`].
///
/// ```
/// use itertools::intersperse_with;
///
/// let mut i = 10;
/// itertools::assert_equal(intersperse_with((0..3), || { i -= 1; i }), vec![0, 9, 1, 8, 2]);
/// assert_eq!(i, 8);
/// ```
pub fn intersperse_with<I, F>(iterable: I, element: F) -> IntersperseWith<I::IntoIter, F>
where
    I: IntoIterator,
    F: FnMut() -> I::Item,
{
    Itertools::intersperse_with(iterable.into_iter(), element)
}

/// Iterate `iterable` with a running index.
///
/// [`IntoIterator`] enabled version of [`Iterator::enumerate`].
///
/// ```
/// use itertools::enumerate;
///
/// for (i, elt) in enumerate(&[1, 2, 3]) {
///     /* loop body */
/// }
/// ```
pub fn enumerate<I>(iterable: I) -> iter::Enumerate<I::IntoIter>
where
    I: IntoIterator,
{
    iterable.into_iter().enumerate()
}

/// Iterate `iterable` in reverse.
///
/// [`IntoIterator`] enabled version of [`Iterator::rev`].
///
/// ```
/// use itertools::rev;
///
/// for elt in rev(&[1, 2, 3]) {
///     /* loop body */
/// }
/// ```
pub fn rev<I>(iterable: I) -> iter::Rev<I::IntoIter>
where
    I: IntoIterator,
    I::IntoIter: DoubleEndedIterator,
{
    iterable.into_iter().rev()
}

/// Iterate `i` and `j` in lock step.
///
/// [`IntoIterator`] enabled version of [`Iterator::zip`].
///
/// ```
/// use itertools::zip;
///
/// let data_1 = [1, 2, 3, 4, 5];
/// let data_2 = ['a', 'b', 'c'];
/// let mut result: Vec<(i32, char)> = Vec::new();
///
/// for (a, b) in zip(&data_1, &data_2) {
///     result.push((*a, *b));
/// }
/// assert_eq!(result, vec![(1, 'a'),(2, 'b'),(3, 'c')]);
/// ```
///
pub fn zip<I, J>(i: I, j: J) -> Zip<I::IntoIter, J::IntoIter>
where
    I: IntoIterator,
    J: IntoIterator,
{
    i.into_iter().zip(j)
}

/// Create an iterator that first iterates `i` and then `j`.
///
/// [`IntoIterator`] enabled version of [`Iterator::chain`].
///
/// ```
/// use itertools::chain;
///
/// for elt in chain(&[1, 2, 3], &[4]) {
///     /* loop body */
/// }
/// ```
pub fn chain<I, J>(
    i: I,
    j: J,
) -> iter::Chain<<I as IntoIterator>::IntoIter, <J as IntoIterator>::IntoIter>
where
    I: IntoIterator,
    J: IntoIterator<Item = I::Item>,
{
    i.into_iter().chain(j)
}

/// Create an iterator that clones each element from &T to T
///
/// [`IntoIterator`] enabled version of [`Iterator::cloned`].
///
/// ```
/// use itertools::cloned;
///
/// assert_eq!(cloned(b"abc").next(), Some(b'a'));
/// ```
pub fn cloned<'a, I, T: 'a>(iterable: I) -> iter::Cloned<I::IntoIter>
where
    I: IntoIterator<Item = &'a T>,
    T: Clone,
{
    iterable.into_iter().cloned()
}

/// Perform a fold operation over the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::fold`].
///
/// ```
/// use itertools::fold;
///
/// assert_eq!(fold(&[1., 2., 3.], 0., |a, &b| f32::max(a, b)), 3.);
/// ```
pub fn fold<I, B, F>(iterable: I, init: B, f: F) -> B
where
    I: IntoIterator,
    F: FnMut(B, I::Item) -> B,
{
    iterable.into_iter().fold(init, f)
}

/// Test whether the predicate holds for all elements in the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::all`].
///
/// ```
/// use itertools::all;
///
/// assert!(all(&[1, 2, 3], |elt| *elt > 0));
/// ```
pub fn all<I, F>(iterable: I, f: F) -> bool
where
    I: IntoIterator,
    F: FnMut(I::Item) -> bool,
{
    iterable.into_iter().all(f)
}

/// Test whether the predicate holds for any elements in the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::any`].
///
/// ```
/// use itertools::any;
///
/// assert!(any(&[0, -1, 2], |elt| *elt > 0));
/// ```
pub fn any<I, F>(iterable: I, f: F) -> bool
where
    I: IntoIterator,
    F: FnMut(I::Item) -> bool,
{
    iterable.into_iter().any(f)
}

/// Return the maximum value of the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::max`].
///
/// ```
/// use itertools::max;
///
/// assert_eq!(max(0..10), Some(9));
/// ```
pub fn max<I>(iterable: I) -> Option<I::Item>
where
    I: IntoIterator,
    I::Item: Ord,
{
    iterable.into_iter().max()
}

/// Return the minimum value of the iterable.
///
/// [`IntoIterator`] enabled version of [`Iterator::min`].
///
/// ```
/// use itertools::min;
///
/// assert_eq!(min(0..10), Some(0));
/// ```
pub fn min<I>(iterable: I) -> Option<I::Item>
where
    I: IntoIterator,
    I::Item: Ord,
{
    iterable.into_iter().min()
}

/// Combine all iterator elements into one String, separated by `sep`.
///
/// [`IntoIterator`] enabled version of [`Itertools::join`].
///
/// ```
/// use itertools::join;
///
/// assert_eq!(join(&[1, 2, 3], ", "), "1, 2, 3");
/// ```
#[cfg(feature = "use_alloc")]
pub fn join<I>(iterable: I, sep: &str) -> String
where
    I: IntoIterator,
    I::Item: Display,
{
    iterable.into_iter().join(sep)
}

/// Sort all iterator elements into a new iterator in ascending order.
///
/// [`IntoIterator`] enabled version of [`Itertools::sorted`].
///
/// ```
/// use itertools::sorted;
/// use itertools::assert_equal;
///
/// assert_equal(sorted("rust".chars()), "rstu".chars());
/// ```
#[cfg(feature = "use_alloc")]
pub fn sorted<I>(iterable: I) -> VecIntoIter<I::Item>
where
    I: IntoIterator,
    I::Item: Ord,
{
    iterable.into_iter().sorted()
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::io;
use byteorder::{self, ReadBytesExt, WriteBytesExt, LittleEndian};
use {GameDataRead, GameDataWrite, Strings};
use gamedata_io::{Chunk, get_chunk_header, ReadError, Tell};

impl<'a> Chunk<'a> for Strings {
    const TYPE_ID: &'static [u8; 4] = b"STRG";
    type ReadOutput = (Self, Vec<u32>);
    fn read<R: GameDataRead>(reader: &mut R) -> Result<Self::ReadOutput, ReadError> {
        try!(get_chunk_header(reader, Self::TYPE_ID));
        let count = try!(reader.read_u32::<LittleEndian>());
        let mut offsets = Vec::with_capacity(count as usize);
        for _ in 0..count {
            let offset = try!(reader.read_u32::<LittleEndian>());
            offsets.push(offset);
        }
        let mut strings = Vec::with_capacity(count as usize);
        for _ in 0..count {
            let string = try!(read_string(reader));
            strings.push(string);
        }
        // TODO: Why do we need to consume additional 4 bytes?
        // Looks like 4 zero bytes.
        // Okay, let's assume that this is zero padding for 16 byte alignment.
        let finished_offset = try!(reader.tell());
        let mut offset = finished_offset;
        // Seek to nearest 16 byte aligned offset
        while offset % 16 != 0 {
            offset += 1;
        }
        try!(reader.seek(io::SeekFrom::Start(offset)));
        Ok((Strings { strings: strings }, offsets))
    }
    fn write_content<W: GameDataWrite>(&self, writer: &mut W) -> io::Result<()> {
        try!(writer.write_u32::<LittleEndian>(self.strings.len() as u32));
        let start_offset = try!(writer.tell());
        let mut string_offset = start_offset as u32 + (self.strings.len() as u32 * 4);
        for string in &self.strings {
            try!(writer.write_u32::<LittleEndian>(string_offset));
            string_offset += (string.len() + 1) as u32 + 4;
        }
        for string in &self.strings {
            try!(writer.write_u32::<LittleEndian>(string.len() as u32));
            try!(writer.write_all(string.as_bytes()));
            try!(writer.write_u8(0));
        }
        // Write zero padding for 16 byte alignment
        let finished_offset = try!(writer.tell());
        let mut offset = finished_offset;
        while offset % 16 != 0 {
            offset += 1;
            try!(writer.write_u8(0));
        }
        Ok(())
    }
}

fn read_string<R: GameDataRead>(reader: &mut R) -> Result<String, StringReadError> {
    let len = try!(reader.read_u32::<LittleEndian>());
    let mut buf = Vec::with_capacity(len as usize);
    unsafe {
        buf.set_len(len as usize);
        try!(reader.read_exact(&mut buf));
    }
    let terminator = try!(reader.read_u8());
    if terminator == 0 {
        // We assume strings are valid UTF-8, if not, panic.
        Ok(String::from_utf8(buf).unwrap())
    } else {
        Err(StringReadError::MissingNullTerminator)
    }
}

quick_error! {
    #[derive(Debug)]
    /// Error when reading a string from the string table.
    pub enum StringReadError {
        /// An I/O error.
        Io(err: io::Error) {
            from()
        }
        /// A byte order error.
        ByteOrder(err: byteorder::Error) {
            from()
        }
        /// Missing null terminator.
        MissingNullTerminator {}
    }
}
<commit_msg>Make gamedata_io::read_string implementation safe<commit_after>use std::io::prelude::*;
use std::io;
use byteorder::{self, ReadBytesExt, WriteBytesExt, LittleEndian};
use {GameDataRead, GameDataWrite, Strings};
use gamedata_io::{Chunk, get_chunk_header, ReadError, Tell};

impl<'a> Chunk<'a> for Strings {
    const TYPE_ID: &'static [u8; 4] = b"STRG";
    type ReadOutput = (Self, Vec<u32>);
    fn read<R: GameDataRead>(reader: &mut R) -> Result<Self::ReadOutput, ReadError> {
        try!(get_chunk_header(reader, Self::TYPE_ID));
        let count = try!(reader.read_u32::<LittleEndian>());
        let mut offsets = Vec::with_capacity(count as usize);
        for _ in 0..count {
            let offset = try!(reader.read_u32::<LittleEndian>());
            offsets.push(offset);
        }
        let mut strings = Vec::with_capacity(count as usize);
        for _ in 0..count {
            let string = try!(read_string(reader));
            strings.push(string);
        }
        // TODO: Why do we need to consume additional 4 bytes?
        // Looks like 4 zero bytes.
        // Okay, let's assume that this is zero padding for 16 byte alignment.
        let finished_offset = try!(reader.tell());
        let mut offset = finished_offset;
        // Seek to nearest 16 byte aligned offset
        while offset % 16 != 0 {
            offset += 1;
        }
        try!(reader.seek(io::SeekFrom::Start(offset)));
        Ok((Strings { strings: strings }, offsets))
    }
    fn write_content<W: GameDataWrite>(&self, writer: &mut W) -> io::Result<()> {
        try!(writer.write_u32::<LittleEndian>(self.strings.len() as u32));
        let start_offset = try!(writer.tell());
        let mut string_offset = start_offset as u32 + (self.strings.len() as u32 * 4);
        for string in &self.strings {
            try!(writer.write_u32::<LittleEndian>(string_offset));
            string_offset += (string.len() + 1) as u32 + 4;
        }
        for string in &self.strings {
            try!(writer.write_u32::<LittleEndian>(string.len() as u32));
            try!(writer.write_all(string.as_bytes()));
            try!(writer.write_u8(0));
        }
        // Write zero padding for 16 byte alignment
        let finished_offset = try!(writer.tell());
        let mut offset = finished_offset;
        while offset % 16 != 0 {
            offset += 1;
            try!(writer.write_u8(0));
        }
        Ok(())
    }
}

fn read_string<R: GameDataRead>(reader: &mut R) -> Result<String, StringReadError> {
    let len = try!(reader.read_u32::<LittleEndian>());
    let buf = try!(super::read_into_byte_vec(reader, len as usize));
    let terminator = try!(reader.read_u8());
    if terminator == 0 {
        // We assume strings are valid UTF-8, if not, panic.
        Ok(String::from_utf8(buf).unwrap())
    } else {
        Err(StringReadError::MissingNullTerminator)
    }
}

quick_error! {
    #[derive(Debug)]
    /// Error when reading a string from the string table.
    pub enum StringReadError {
        /// An I/O error.
        Io(err: io::Error) {
            from()
        }
        /// A byte order error.
        ByteOrder(err: byteorder::Error) {
            from()
        }
        /// Missing null terminator.
        MissingNullTerminator {}
    }
}
<|endoftext|>


<commit_before>use super::Scalar;
use nullable::Nullable;

macro_rules! iml_scalar_as {
    ($t:ident, $as_op:ident, $is_op:ident) => {

        // ToDo: fix docstring
        impl Scalar {
            /// Convert the value to specified type
            ///
            /// The result may be undefined as the same rule as `as`
            pub fn $as_op(&self) -> Nullable<$t> {
                match self {
                    &Scalar::Null => Nullable::Null,
                    &Scalar::i64(val) => Nullable::Value(val as $t),
                    &Scalar::i32(val) => Nullable::Value(val as $t),
                    &Scalar::i16(val) => Nullable::Value(val as $t),
                    &Scalar::i8(val) => Nullable::Value(val as $t),
                    &Scalar::isize(val) => Nullable::Value(val as $t),
                    &Scalar::u64(val) => Nullable::Value(val as $t),
                    &Scalar::u32(val) => Nullable::Value(val as $t),
                    &Scalar::u16(val) => Nullable::Value(val as $t),
                    &Scalar::u8(val) => Nullable::Value(val as $t),
                    &Scalar::usize(val) => Nullable::Value(val as $t),
                    &Scalar::f64(val) => Nullable::Value(val as $t),
                    &Scalar::f32(val) => Nullable::Value(val as $t),
                    _ => panic!("cannot convert to specified type")
                }
            }

            /// Return whether the scalar is specific type
            pub fn $is_op(&self) -> bool {
                match self {
                    &Scalar::$t(_) => true,
                    _ => false
                }
            }
        }
    }
}
iml_scalar_as!(i64, as_i64, is_i64);
iml_scalar_as!(i32, as_i32, is_i32);
iml_scalar_as!(i16, as_i16, is_i16);
iml_scalar_as!(i8, as_i8, is_i8);
iml_scalar_as!(isize, as_isize, is_isize);
iml_scalar_as!(u64, as_u64, is_u64);
iml_scalar_as!(u32, as_u32, is_u32);
iml_scalar_as!(u16, as_u16, is_u16);
iml_scalar_as!(u8, as_u8, is_u8);
iml_scalar_as!(usize, as_usize, is_usize);
iml_scalar_as!(f64, as_f64, is_f64);
iml_scalar_as!(f32, as_f32, is_f32);

impl Scalar {
    pub fn as_bool(&self) -> Nullable<bool> {
        match self {
            &Scalar::Null => Nullable::Null,
            &Scalar::bool(val) => Nullable::Value(val),
            _ => panic!("cannot convert to specified type"),
        }
    }

    pub fn is_bool(&self) -> bool {
        match self {
            &Scalar::bool(_) => true,
            _ => false,
        }
    }
}

impl Scalar {
    pub fn as_str(&self) -> Nullable<String> {
        match self {
            &Scalar::Null => Nullable::Null,
            &Scalar::String(ref val) => Nullable::Value(val.clone()),
            _ => panic!("cannot convert to specified type"),
        }
    }

    pub fn is_str(&self) -> bool {
        match self {
            &Scalar::String(_) => true,
            _ => false,
        }
    }
}

impl Scalar {
    pub fn dtype(&self) -> String {
        match self {
            &Scalar::Null => "null".to_string(),
            &Scalar::i64(_) => "i64".to_string(),
            &Scalar::i32(_) => "i32".to_string(),
            &Scalar::i16(_) => "i16".to_string(),
            &Scalar::i8(_) => "i8".to_string(),
            &Scalar::isize(_) => "isize".to_string(),
            &Scalar::u64(_) => "u64".to_string(),
            &Scalar::u32(_) => "u32".to_string(),
            &Scalar::u16(_) => "u16".to_string(),
            &Scalar::u8(_) => "u8".to_string(),
            &Scalar::usize(_) => "usize".to_string(),
            &Scalar::f64(_) => "f64".to_string(),
            &Scalar::f32(_) => "f32".to_string(),
            &Scalar::bool(_) => "bool".to_string(),
            &Scalar::String(_) => "str".to_string(),
        }
    }
}

#[cfg(test)]
mod tests {

    use super::super::Scalar;
    use nullable::Nullable;

    #[test]
    fn test_i64_dtype_property() {
        let i = Scalar::i64(1);
        assert_eq!(i.dtype(), "i64".to_string());
        assert_eq!(i.is_i64(), true);
        assert_eq!(i.is_f64(), false);
        assert_eq!(i.is_bool(), false);
        assert_eq!(i.is_str(), false);

        assert_eq!(i.as_i64(), Nullable::new(1i64));
        assert_eq!(i.as_usize(), Nullable::new(1usize));
        assert_eq!(i.as_f64(), Nullable::new(1.0f64));
    }

    #[test]
    #[should_panic]
    fn test_i64_to_bool() {
        // 1 as bool is unsupported cast
        let i = Scalar::i64(1);
        i.as_bool();
    }

    #[test]
    #[should_panic]
    fn test_i64_to_str() {
        // non numeric cast
        let i = Scalar::i64(1);
        i.as_str();
    }

    #[test]
    fn test_f64_dtype_property() {
        let f = Scalar::f64(1.1);
        assert_eq!(f.dtype(), "f64".to_string());
        assert_eq!(f.is_i64(), false);
        assert_eq!(f.is_f64(), true);
        assert_eq!(f.is_bool(), false);
        assert_eq!(f.is_str(), false);

        assert_eq!(f.as_f64(), Nullable::new(1.1f64));
        assert_eq!(f.as_i64(), Nullable::new(1.1 as i64));
        assert_eq!(f.as_usize(), Nullable::new(1.1 as usize));
    }

    #[test]
    #[should_panic]
    fn test_f64_to_bool() {
        // 1 as bool is unsupported cast
        let f = Scalar::f64(1.1);
        f.as_bool();
    }

    #[test]
    #[should_panic]
    fn test_f64_to_str() {
        // non numeric cast
        let f = Scalar::f64(1.1);
        f.as_str();
    }

    #[test]
    fn test_bool_dtype_property() {
        let b = Scalar::bool(true);
        assert_eq!(b.dtype(), "bool".to_string());
        assert_eq!(b.is_i64(), false);
        assert_eq!(b.is_f64(), false);
        assert_eq!(b.is_bool(), true);
        assert_eq!(b.is_str(), false);

        assert_eq!(b.as_bool(), Nullable::new(true));
        // assert_eq!(b.as_i64(), Nullable::new(true as i64));
    }

    #[test]
    #[should_panic]
    fn test_bool_to_f64() {
        // casting `bool` as `f64` is invalid
        let b = Scalar::bool(true);
        b.as_f64();
    }

    #[test]
    #[should_panic]
    fn test_bool_to_str() {
        // non numeric cast
        let b = Scalar::bool(true);
        b.as_str();
    }

    #[test]
    fn test_str_dtype_property() {
        let s = Scalar::String("aa".to_string());
        assert_eq!(s.dtype(), "str".to_string());
        assert_eq!(s.is_i64(), false);
        assert_eq!(s.is_f64(), false);
        assert_eq!(s.is_bool(), false);
        assert_eq!(s.is_str(), true);

        assert_eq!(s.as_str(), Nullable::new("aa".to_string()));
    }

    #[test]
    #[should_panic]
    fn test_str_to_i64() {
        let s = Scalar::String("1".to_string());
        s.as_i64();
    }

    #[test]
    #[should_panic]
    fn test_str_to_f64() {
        let s = Scalar::String("1.1".to_string());
        s.as_f64();
    }

    #[test]
    #[should_panic]
    fn test_str_to_bool() {
        let s = Scalar::String("true".to_string());
        s.as_bool();
    }
}
<commit_msg>ENH: Add Scalar display<commit_after>use std::fmt;

use super::Scalar;
use nullable::Nullable;

macro_rules! iml_scalar_as {
    ($t:ident, $as_op:ident, $is_op:ident) => {

        // ToDo: fix docstring
        impl Scalar {
            /// Convert the value to specified type
            ///
            /// The result may be undefined as the same rule as `as`
            pub fn $as_op(&self) -> Nullable<$t> {
                match self {
                    &Scalar::Null => Nullable::Null,
                    &Scalar::i64(val) => Nullable::Value(val as $t),
                    &Scalar::i32(val) => Nullable::Value(val as $t),
                    &Scalar::i16(val) => Nullable::Value(val as $t),
                    &Scalar::i8(val) => Nullable::Value(val as $t),
                    &Scalar::isize(val) => Nullable::Value(val as $t),
                    &Scalar::u64(val) => Nullable::Value(val as $t),
                    &Scalar::u32(val) => Nullable::Value(val as $t),
                    &Scalar::u16(val) => Nullable::Value(val as $t),
                    &Scalar::u8(val) => Nullable::Value(val as $t),
                    &Scalar::usize(val) => Nullable::Value(val as $t),
                    &Scalar::f64(val) => Nullable::Value(val as $t),
                    &Scalar::f32(val) => Nullable::Value(val as $t),
                    _ => panic!("cannot convert to specified type")
                }
            }

            /// Return whether the scalar is specific type
            pub fn $is_op(&self) -> bool {
                match self {
                    &Scalar::$t(_) => true,
                    _ => false
                }
            }
        }
    }
}
iml_scalar_as!(i64, as_i64, is_i64);
iml_scalar_as!(i32, as_i32, is_i32);
iml_scalar_as!(i16, as_i16, is_i16);
iml_scalar_as!(i8, as_i8, is_i8);
iml_scalar_as!(isize, as_isize, is_isize);
iml_scalar_as!(u64, as_u64, is_u64);
iml_scalar_as!(u32, as_u32, is_u32);
iml_scalar_as!(u16, as_u16, is_u16);
iml_scalar_as!(u8, as_u8, is_u8);
iml_scalar_as!(usize, as_usize, is_usize);
iml_scalar_as!(f64, as_f64, is_f64);
iml_scalar_as!(f32, as_f32, is_f32);

impl Scalar {
    pub fn as_bool(&self) -> Nullable<bool> {
        match self {
            &Scalar::Null => Nullable::Null,
            &Scalar::bool(val) => Nullable::Value(val),
            _ => panic!("cannot convert to specified type"),
        }
    }

    pub fn is_bool(&self) -> bool {
        match self {
            &Scalar::bool(_) => true,
            _ => false,
        }
    }
}

impl Scalar {
    pub fn as_str(&self) -> Nullable<String> {
        match self {
            &Scalar::Null => Nullable::Null,
            &Scalar::String(ref val) => Nullable::Value(val.clone()),
            _ => panic!("cannot convert to specified type"),
        }
    }

    pub fn is_str(&self) -> bool {
        match self {
            &Scalar::String(_) => true,
            _ => false,
        }
    }
}

impl Scalar {
    pub fn dtype(&self) -> String {
        match self {
            &Scalar::Null => "null".to_string(),
            &Scalar::i64(_) => "i64".to_string(),
            &Scalar::i32(_) => "i32".to_string(),
            &Scalar::i16(_) => "i16".to_string(),
            &Scalar::i8(_) => "i8".to_string(),
            &Scalar::isize(_) => "isize".to_string(),
            &Scalar::u64(_) => "u64".to_string(),
            &Scalar::u32(_) => "u32".to_string(),
            &Scalar::u16(_) => "u16".to_string(),
            &Scalar::u8(_) => "u8".to_string(),
            &Scalar::usize(_) => "usize".to_string(),
            &Scalar::f64(_) => "f64".to_string(),
            &Scalar::f32(_) => "f32".to_string(),
            &Scalar::bool(_) => "bool".to_string(),
            &Scalar::String(_) => "str".to_string(),
        }
    }
}

// Implement `Display` for `Scalar`.
impl fmt::Display for Scalar {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Use `self.number` to refer to each positional data point.
        match self {
            &Scalar::Null => write!(f, "Null"),
            &Scalar::i64(ref val) => write!(f, "{}", val),
            &Scalar::i32(ref val) => write!(f, "{}", val),
            &Scalar::i16(ref val) => write!(f, "{}", val),
            &Scalar::i8(ref val) => write!(f, "{}", val),
            &Scalar::isize(ref val) => write!(f, "{}", val),
            &Scalar::u64(ref val) => write!(f, "{}", val),
            &Scalar::u32(ref val) => write!(f, "{}", val),
            &Scalar::u16(ref val) => write!(f, "{}", val),
            &Scalar::u8(ref val) => write!(f, "{}", val),
            &Scalar::usize(ref val) => write!(f, "{}", val),
            &Scalar::f64(ref val) => write!(f, "{}", val),
            &Scalar::f32(ref val) => write!(f, "{}", val),
            &Scalar::bool(ref val) => write!(f, "{}", val),
            &Scalar::String(ref val) => write!(f, "{}", val),
        }
    }
}

#[cfg(test)]
mod tests {

    use std::io::Write;

    use super::super::Scalar;
    use nullable::Nullable;

    #[test]
    fn test_i64_dtype_property() {
        let i = Scalar::i64(1);
        assert_eq!(i.dtype(), "i64".to_string());
        assert_eq!(i.is_i64(), true);
        assert_eq!(i.is_f64(), false);
        assert_eq!(i.is_bool(), false);
        assert_eq!(i.is_str(), false);

        assert_eq!(i.as_i64(), Nullable::new(1i64));
        assert_eq!(i.as_usize(), Nullable::new(1usize));
        assert_eq!(i.as_f64(), Nullable::new(1.0f64));
    }

    #[test]
    #[should_panic]
    fn test_i64_to_bool() {
        // 1 as bool is unsupported cast
        let i = Scalar::i64(1);
        i.as_bool();
    }

    #[test]
    #[should_panic]
    fn test_i64_to_str() {
        // non numeric cast
        let i = Scalar::i64(1);
        i.as_str();
    }

    #[test]
    fn test_f64_dtype_property() {
        let f = Scalar::f64(1.1);
        assert_eq!(f.dtype(), "f64".to_string());
        assert_eq!(f.is_i64(), false);
        assert_eq!(f.is_f64(), true);
        assert_eq!(f.is_bool(), false);
        assert_eq!(f.is_str(), false);

        assert_eq!(f.as_f64(), Nullable::new(1.1f64));
        assert_eq!(f.as_i64(), Nullable::new(1.1 as i64));
        assert_eq!(f.as_usize(), Nullable::new(1.1 as usize));
    }

    #[test]
    #[should_panic]
    fn test_f64_to_bool() {
        // 1 as bool is unsupported cast
        let f = Scalar::f64(1.1);
        f.as_bool();
    }

    #[test]
    #[should_panic]
    fn test_f64_to_str() {
        // non numeric cast
        let f = Scalar::f64(1.1);
        f.as_str();
    }

    #[test]
    fn test_bool_dtype_property() {
        let b = Scalar::bool(true);
        assert_eq!(b.dtype(), "bool".to_string());
        assert_eq!(b.is_i64(), false);
        assert_eq!(b.is_f64(), false);
        assert_eq!(b.is_bool(), true);
        assert_eq!(b.is_str(), false);

        assert_eq!(b.as_bool(), Nullable::new(true));
        // assert_eq!(b.as_i64(), Nullable::new(true as i64));
    }

    #[test]
    #[should_panic]
    fn test_bool_to_f64() {
        // casting `bool` as `f64` is invalid
        let b = Scalar::bool(true);
        b.as_f64();
    }

    #[test]
    #[should_panic]
    fn test_bool_to_str() {
        // non numeric cast
        let b = Scalar::bool(true);
        b.as_str();
    }

    #[test]
    fn test_str_dtype_property() {
        let s = Scalar::String("aa".to_string());
        assert_eq!(s.dtype(), "str".to_string());
        assert_eq!(s.is_i64(), false);
        assert_eq!(s.is_f64(), false);
        assert_eq!(s.is_bool(), false);
        assert_eq!(s.is_str(), true);

        assert_eq!(s.as_str(), Nullable::new("aa".to_string()));
    }

    #[test]
    #[should_panic]
    fn test_str_to_i64() {
        let s = Scalar::String("1".to_string());
        s.as_i64();
    }

    #[test]
    #[should_panic]
    fn test_str_to_f64() {
        let s = Scalar::String("1.1".to_string());
        s.as_f64();
    }

    #[test]
    #[should_panic]
    fn test_str_to_bool() {
        let s = Scalar::String("true".to_string());
        s.as_bool();
    }

    #[test]
    fn test_scalar_format() {
        let s = Scalar::Null;
        // better way?
        let mut buf = Vec::new();
        let _ = write!(&mut buf, "{}", s);
        assert_eq!(&buf, b"Null");

        let s = Scalar::i64(100);
        let mut buf = Vec::new();
        let _ = write!(&mut buf, "{}", s);
        assert_eq!(&buf, b"100");

        let s = Scalar::f64(1.1);
        let mut buf = Vec::new();
        let _ = write!(&mut buf, "{}", s);
        assert_eq!(&buf, b"1.1");

        let s = Scalar::bool(true);
        let mut buf = Vec::new();
        let _ = write!(&mut buf, "{}", s);
        assert_eq!(&buf, b"true");

        let s = Scalar::String("xx".to_string());
        let mut buf = Vec::new();
        let _ = write!(&mut buf, "{}", s);
        assert_eq!(&buf, b"xx");
    }
}
<|endoftext|>


<commit_before>#[feature(macro_rules)];
#[crate_id = "codegen#0.1"];

use std::os;
use std::io::BufferedWriter;
use std::io::File;
use std::io;
use std::io::stdio::println;
use std::io::fs::mkdir_recursive;
use std::path::GenericPath;
pub mod branchify;
pub mod keycode;
pub mod scancode;

fn main() {
    let args = os::args();
    match args.len() {
        0 => {
            println("usage: codegen [keycode|scancode].rs destdir");
            os::set_exit_status(1);
        },
        3 => {
            let output_dir = GenericPath::new(args[2].clone());
            // TODO: maybe not 0777?
            mkdir_recursive(&output_dir, 0b111_111_111);

            match args[1] {
                ~"keycode.rs" => keycode::generate(&output_dir),
                ~"scancode.rs" => scancode::generate(&output_dir),
                s => {
                    println!("unknown thing-to-generate '{}'", s);
                    os::set_exit_status(1);
                }
            }
        },
        _ => {
            println!("usage: {} [keycode|scancode].rs destdir", args[0]);
            os::set_exit_status(1);
        }
    }
}

pub fn get_writer(output_dir: &Path, filename: &str) -> ~BufferedWriter<File> {
    match File::open_mode(&output_dir.join(filename), io::Truncate, io::Write) {
        Ok(writer) => ~BufferedWriter::new(writer),
        Err(e) => fail!("Unable to write file: {:s}", e.desc),
    }
}
<commit_msg>Change from match to if for strings.<commit_after>#[feature(macro_rules)];
#[crate_id = "codegen#0.1"];

use std::os;
use std::io::BufferedWriter;
use std::io::File;
use std::io;
use std::io::stdio::println;
use std::io::fs::mkdir_recursive;
use std::path::GenericPath;
pub mod branchify;
pub mod keycode;
pub mod scancode;

fn main() {
    let args = os::args();
    match args.len() {
        0 => {
            println("usage: codegen [keycode|scancode].rs destdir");
            os::set_exit_status(1);
        },
        3 => {
            let output_dir = GenericPath::new(args[2].clone());
            // TODO: maybe not 0777?
            mkdir_recursive(&output_dir, 0b111_111_111);

            if args[1] == ~"keycode.rs" {
                keycode::generate(&output_dir);
            } else if args[1] == ~"scancode.rs" {
                scancode::generate(&output_dir);
            } else {
                println!("unknown thing-to-generate '{}'", args[1]);
                os::set_exit_status(1);
            }
        },
        _ => {
            println!("usage: {} [keycode|scancode].rs destdir", args[0]);
            os::set_exit_status(1);
        }
    }
}

pub fn get_writer(output_dir: &Path, filename: &str) -> ~BufferedWriter<File> {
    match File::open_mode(&output_dir.join(filename), io::Truncate, io::Write) {
        Ok(writer) => ~BufferedWriter::new(writer),
        Err(e) => fail!("Unable to write file: {:s}", e.desc),
    }
}
<|endoftext|>


<commit_before>use toml::Value;

use libimagerror::into::IntoError;
use libimagstore::storeid::StoreId;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

use git2::Repository;

/// Check the configuration whether we should commit interactively
pub fn commit_interactive(config: &Value, action: &StoreAction) -> bool {
    match config.lookup("commit.interactive") {
        Some(&Value::Boolean(b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_{}.commit.interactive' must be a Boolean.",
                  action);
            warn!("Defaulting to commit.interactive = false");
            false
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_{}.commit.interactive'", action);
            warn!("Defaulting to false");
            false
        }
    }
}

/// Check the configuration whether we should commit with the editor
fn commit_with_editor(config: &Value, action: &StoreAction) -> bool {
    match config.lookup("commit.interactive_editor") {
        Some(&Value::Boolean(b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_{}.commit.interactive_editor' must be a Boolean.",
                  action);
            warn!("Defaulting to commit.interactive_editor = false");
            false
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_{}.commit.interactive_editor'", action);
            warn!("Defaulting to false");
            false
        }
    }
}

/// Get the commit default message
fn commit_default_msg<'a>(config: &'a Value, action: &'a StoreAction) -> &'a str {
    match config.lookup("commit.message") {
        Some(&Value::String(ref b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_{}.commit.message' must be a String.",
                  action);
            warn!("Defaulting to commit.message = '{}'", action.as_commit_message());
            action.as_commit_message()
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_{}.commit.message'", action);
            warn!("Defaulting to commit.message = '{}'", action.as_commit_message());
            action.as_commit_message()
        }
    }
}

/// Get the commit template
///
/// TODO: Implement good template string
fn commit_template(action: &StoreAction, id: &StoreId) -> String {
    format!(r#"
# Please commit your changes and remove these lines.
#
# You're about to commit changes via the {action} Hook
#
#   Altered file: {id}
#
    "#,
    action = action,
    id = id.local().display())
}

/// Generate a commit message
///
/// Uses the functions `commit_interactive()` and `commit_with_editor()`
/// or reads one from the commandline or uses the `commit_default_msg()` string to create a commit
/// message.
pub fn commit_message(repo: &Repository, config: &Value, action: StoreAction, id: &StoreId) -> Result<String> {
    use libimaginteraction::ask::ask_string;
    use libimagutil::edit::edit_in_tmpfile_with_command;
    use std::process::Command;

    if commit_interactive(config, &action) {
        if commit_with_editor(config, &action) {
            repo.config()
                .map_err_into(GHEK::GitConfigFetchError)
                .and_then(|c| c.get_string("core.editor").map_err_into(GHEK::GitConfigEditorFetchError))
                .map_err_into(GHEK::ConfigError)
                .map(Command::new)
                .and_then(|cmd| {
                    let mut s = commit_template(&action, id);
                    edit_in_tmpfile_with_command(cmd, &mut s).map(|_| s)
                        .map_err_into(GHEK::EditorError)
                })
        } else {
            Ok(ask_string("Commit Message", None, false, false, None, "> "))
        }
    } else {
        Ok(String::from(commit_default_msg(config, &action)))
    }
}

/// Check whether the hook should abort if the repository cannot be initialized
pub fn abort_on_repo_init_err(cfg: &Value) -> bool {
    get_bool_cfg(Some(cfg), "abort_on_repo_init_failure", true, true)
}

/// Get the branch which must be checked out before running the hook (if any).
///
/// If there is no configuration for this, this is `Ok(None)`, otherwise we try to find the
/// configuration `String`.
pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

/// Check whether we should check out a branch before committing.
pub fn do_checkout_ensure_branch(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "try_checkout_ensure_branch", true, true)
}

/// Helper to get a boolean value from the configuration.
fn get_bool_cfg(cfg: Option<&Value>, name: &str, on_fail: bool, on_unavail: bool) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup(name) {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, '{}' must be a Boolean (true|false).", name);
                warn!("Assuming '{}' now.", on_fail);
                on_fail
            },
            None => {
                debug!("No key '{}' - Assuming '{}'", name, on_unavail);
                on_unavail
            },
        }
    })
    .unwrap_or_else(|| {
        debug!("No configuration to fetch {} from, assuming {}", name, on_unavail);
        on_unavail
    })
}

/// Check whether the hook is enabled or not. If the config is not there, the hook is _enabled_ by
/// default.
pub fn is_enabled(cfg: &Value) -> bool {
    get_bool_cfg(Some(cfg), "enabled", true, true)
}

<commit_msg>util: get_bool_cfg(): Output with warn!() instead of debug!()<commit_after>use toml::Value;

use libimagerror::into::IntoError;
use libimagstore::storeid::StoreId;

use vcs::git::error::GitHookErrorKind as GHEK;
use vcs::git::error::MapErrInto;
use vcs::git::result::Result;

use vcs::git::action::StoreAction;

use git2::Repository;

/// Check the configuration whether we should commit interactively
pub fn commit_interactive(config: &Value, action: &StoreAction) -> bool {
    match config.lookup("commit.interactive") {
        Some(&Value::Boolean(b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_{}.commit.interactive' must be a Boolean.",
                  action);
            warn!("Defaulting to commit.interactive = false");
            false
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_{}.commit.interactive'", action);
            warn!("Defaulting to false");
            false
        }
    }
}

/// Check the configuration whether we should commit with the editor
fn commit_with_editor(config: &Value, action: &StoreAction) -> bool {
    match config.lookup("commit.interactive_editor") {
        Some(&Value::Boolean(b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_{}.commit.interactive_editor' must be a Boolean.",
                  action);
            warn!("Defaulting to commit.interactive_editor = false");
            false
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_{}.commit.interactive_editor'", action);
            warn!("Defaulting to false");
            false
        }
    }
}

/// Get the commit default message
fn commit_default_msg<'a>(config: &'a Value, action: &'a StoreAction) -> &'a str {
    match config.lookup("commit.message") {
        Some(&Value::String(ref b)) => b,
        Some(_) => {
            warn!("Configuration error, 'store.hooks.stdhook_git_{}.commit.message' must be a String.",
                  action);
            warn!("Defaulting to commit.message = '{}'", action.as_commit_message());
            action.as_commit_message()
        }
        None => {
            warn!("Unavailable configuration for");
            warn!("\t'store.hooks.stdhook_git_{}.commit.message'", action);
            warn!("Defaulting to commit.message = '{}'", action.as_commit_message());
            action.as_commit_message()
        }
    }
}

/// Get the commit template
///
/// TODO: Implement good template string
fn commit_template(action: &StoreAction, id: &StoreId) -> String {
    format!(r#"
# Please commit your changes and remove these lines.
#
# You're about to commit changes via the {action} Hook
#
#   Altered file: {id}
#
    "#,
    action = action,
    id = id.local().display())
}

/// Generate a commit message
///
/// Uses the functions `commit_interactive()` and `commit_with_editor()`
/// or reads one from the commandline or uses the `commit_default_msg()` string to create a commit
/// message.
pub fn commit_message(repo: &Repository, config: &Value, action: StoreAction, id: &StoreId) -> Result<String> {
    use libimaginteraction::ask::ask_string;
    use libimagutil::edit::edit_in_tmpfile_with_command;
    use std::process::Command;

    if commit_interactive(config, &action) {
        if commit_with_editor(config, &action) {
            repo.config()
                .map_err_into(GHEK::GitConfigFetchError)
                .and_then(|c| c.get_string("core.editor").map_err_into(GHEK::GitConfigEditorFetchError))
                .map_err_into(GHEK::ConfigError)
                .map(Command::new)
                .and_then(|cmd| {
                    let mut s = commit_template(&action, id);
                    edit_in_tmpfile_with_command(cmd, &mut s).map(|_| s)
                        .map_err_into(GHEK::EditorError)
                })
        } else {
            Ok(ask_string("Commit Message", None, false, false, None, "> "))
        }
    } else {
        Ok(String::from(commit_default_msg(config, &action)))
    }
}

/// Check whether the hook should abort if the repository cannot be initialized
pub fn abort_on_repo_init_err(cfg: &Value) -> bool {
    get_bool_cfg(Some(cfg), "abort_on_repo_init_failure", true, true)
}

/// Get the branch which must be checked out before running the hook (if any).
///
/// If there is no configuration for this, this is `Ok(None)`, otherwise we try to find the
/// configuration `String`.
pub fn ensure_branch(cfg: Option<&Value>) -> Result<Option<String>> {
    match cfg {
        Some(cfg) => {
            match cfg.lookup("ensure_branch") {
                Some(&Value::String(ref s)) => Ok(Some(s.clone())),
                Some(_) => {
                    warn!("Configuration error, 'ensure_branch' must be a String.");
                    Err(GHEK::ConfigTypeError.into_error())
                        .map_err_into(GHEK::ConfigTypeError)
                },
                None => {
                    debug!("No key `ensure_branch'");
                    Ok(None)
                },
            }
        },
        None => Ok(None),
    }
}

/// Check whether we should check out a branch before committing.
pub fn do_checkout_ensure_branch(cfg: Option<&Value>) -> bool {
    get_bool_cfg(cfg, "try_checkout_ensure_branch", true, true)
}

/// Helper to get a boolean value from the configuration.
fn get_bool_cfg(cfg: Option<&Value>, name: &str, on_fail: bool, on_unavail: bool) -> bool {
    cfg.map(|cfg| {
        match cfg.lookup(name) {
            Some(&Value::Boolean(b)) => b,
            Some(_) => {
                warn!("Configuration error, '{}' must be a Boolean (true|false).", name);
                warn!("Assuming '{}' now.", on_fail);
                on_fail
            },
            None => {
                warn!("No key '{}' - Assuming '{}'", name, on_unavail);
                on_unavail
            },
        }
    })
    .unwrap_or_else(|| {
        warn!("No configuration to fetch {} from, assuming {}", name, on_unavail);
        on_unavail
    })
}

/// Check whether the hook is enabled or not. If the config is not there, the hook is _enabled_ by
/// default.
pub fn is_enabled(cfg: &Value) -> bool {
    get_bool_cfg(Some(cfg), "enabled", true, true)
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use serde_json::{Value, from_str};
use serde_json::error::Result as R;
use serde_json::Serializer;
use serde::ser::Serialize;
use serde::ser::Serializer as Ser;

use storage::parser::{FileHeaderParser, ParserError};
use storage::file::header::spec::FileHeaderSpec;
use storage::file::header::data::FileHeaderData;

pub struct JsonHeaderParser {
    spec: Option<FileHeaderSpec>,
}

impl JsonHeaderParser {

    pub fn new(spec: Option<FileHeaderSpec>) -> JsonHeaderParser {
        JsonHeaderParser {
            spec: spec
        }
    }

}

impl Display for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "JsonHeaderParser"));
        Ok(())
    }

}

impl Debug for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "JsonHeaderParser, Spec: {:?}", self.spec));
        Ok(())
    }

}

impl FileHeaderParser for JsonHeaderParser {

    fn read(&self, string: Option<String>)
        -> Result<FileHeaderData, ParserError>
    {
        if string.is_some() {
            let s = string.unwrap();
            debug!("Deserializing: {}", s);
            let fromstr : R<Value> = from_str(&s[..]);
            if let Ok(ref content) = fromstr {
                return Ok(visit_json(&content))
            }
            let oe = fromstr.err().unwrap();
            let s = format!("JSON parser error: {}", oe.description());
            let e = ParserError::short(&s[..], s.clone(), 0);
            Err(e)
        } else {
            Ok(FileHeaderData::Null)
        }
    }

    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError> {
        let mut s = Vec::<u8>::new();
        {
            let mut ser = Serializer::pretty(&mut s);
            data.serialize(&mut ser);
        }

        String::from_utf8(s).or(
            Err(ParserError::short("Cannot parse utf8 bytes",
                                   String::from("<not printable>"),
                                   0)))
    }

}

// TODO: This function must be able to return a parser error
fn visit_json(v: &Value) -> FileHeaderData {
    match v {
        &Value::Null             => FileHeaderData::Null,
        &Value::Bool(b)          => FileHeaderData::Bool(b),
        &Value::I64(i)           => FileHeaderData::Integer(i),
        &Value::U64(u)           => FileHeaderData::UInteger(u),
        &Value::F64(f)           => FileHeaderData::Float(f),
        &Value::String(ref s)        => FileHeaderData::Text(s.clone()),
        &Value::Array(ref vec)       => {
            FileHeaderData::Array {
                values: Box::new(vec.clone().into_iter().map(|i| visit_json(&i)).collect())
            }
        },
        &Value::Object(ref btree)    => {
            let btree = btree.clone();
            FileHeaderData::Map{
                keys: btree.into_iter().map(|(k, v)|
                    FileHeaderData::Key {
                        name: k,
                        value: Box::new(visit_json(&v)),
                    }
                ).collect()
            }
        }
    }
}

impl Serialize for FileHeaderData {

    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Ser
    {
        match self {
            &FileHeaderData::Null               => {
                let o : Option<bool> = None;
                o.serialize(ser)
            },
            &FileHeaderData::Bool(ref b)            => b.serialize(ser),
            &FileHeaderData::Integer(ref i)         => i.serialize(ser),
            &FileHeaderData::UInteger(ref u)        => u.serialize(ser),
            &FileHeaderData::Float(ref f)           => f.serialize(ser),
            &FileHeaderData::Text(ref s)            => (&s[..]).serialize(ser),
            &FileHeaderData::Array{values: ref vs}  => vs.serialize(ser),
            &FileHeaderData::Map{keys: ref ks}      => {
                let mut hm = HashMap::new();

                for key in ks {
                    if let &FileHeaderData::Key{name: ref n, value: ref v} = key {
                        hm.insert(n, v);
                    } else {
                        panic!("Not a key: {:?}", key);
                    }
                }

                hm.serialize(ser)
            },
            &FileHeaderData::Key{name: _, value: _} => unreachable!(),

        }
    }

}

#[cfg(test)]
mod test {

    use std::ops::Deref;

    use super::JsonHeaderParser;
    use storage::parser::{FileHeaderParser, ParserError};
    use storage::file::header::data::FileHeaderData as FHD;
    use storage::file::header::spec::FileHeaderSpec as FHS;

    #[test]
    fn test_deserialization() {
        let text = String::from("{\"a\": 1, \"b\": -2}");
        let spec = FHS::Map {
            keys: vec![
                FHS::Key {
                    name: String::from("a"),
                    value_type: Box::new(FHS::UInteger)
                },
                FHS::Key {
                    name: String::from("b"),
                    value_type: Box::new(FHS::Integer)
                }
            ]
        };

        let parser = JsonHeaderParser::new(Some(spec));
        let parsed = parser.read(Some(text));
        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys: keys}) => {
                for k in keys {
                    match k {
                        FHD::Key{name: name, value: value} => {
                            assert!(name == "a" || name == "b", "Key unknown");
                            match value.deref() {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                &FHD::Integer(i) => assert_eq!(i, -2),
                                _ => assert!(false, "Integers are not here"),
                            }
                        },
                        _ => assert!(false, "Key is not a Key"),
                    }
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    #[test]
    fn test_deserialization_without_spec() {
        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);
        let parsed  = parser.read(Some(text));

        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys: keys}) => {
                for k in keys {
                    match_key(&k);
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    fn match_key(k: &FHD) {
        use std::ops::Deref;

        match k {
            &FHD::Key{name: ref name, value: ref value} => {
                assert!(name == "a" || name == "b", "Key unknown");
                match value.deref() {
                    &FHD::Array{values: ref vs} => {
                        for value in vs.iter() {
                            match value {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                _ => assert!(false, "UInt is not an UInt"),
                            }
                        }
                    }

                    &FHD::Map{keys: ref ks} => {
                        for key in ks.iter() {
                            match key {
                                &FHD::Key{name: ref name, value: ref value} => {
                                    match value.deref() {
                                        &FHD::Integer(i) => {
                                            assert_eq!(i, -2);
                                            assert_eq!(name, "c");
                                        },
                                        _ => assert!(false, "Int is not an Int"),
                                    };
                                },
                                _ => assert!(false, "Key is not a Key"),
                            }
                        }
                    }
                    _ => assert!(false, "Integers are not here"),
                }
            },
            _ => assert!(false, "Key in main Map is not a Key"),
        }
    }

    #[test]
    fn test_desser() {
        use serde_json::error::Result as R;
        use serde_json::{Value, from_str};

        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);

        let des = parser.read(Some(text.clone()));
        assert!(des.is_ok(), "Deserializing failed");

        let ser = parser.write(&des.unwrap());
        assert!(ser.is_ok(), "Parser error when serializing deserialized text");

        let json_text : R<Value> = from_str(&text[..]);
        let json_ser  : R<Value> = from_str(&ser.unwrap()[..]);

        assert!(json_text.is_ok(), "Could not use serde to serialize text for comparison");
        assert!(json_ser.is_ok(),  "Could not use serde to serialize serialized-deserialized text for comparison");
        assert_eq!(json_text.unwrap(), json_ser.unwrap());
    }

}
<commit_msg>Use return value from serialize() and print debug output on failure<commit_after>use std::collections::HashMap;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use serde_json::{Value, from_str};
use serde_json::error::Result as R;
use serde_json::Serializer;
use serde::ser::Serialize;
use serde::ser::Serializer as Ser;

use storage::parser::{FileHeaderParser, ParserError};
use storage::file::header::spec::FileHeaderSpec;
use storage::file::header::data::FileHeaderData;

pub struct JsonHeaderParser {
    spec: Option<FileHeaderSpec>,
}

impl JsonHeaderParser {

    pub fn new(spec: Option<FileHeaderSpec>) -> JsonHeaderParser {
        JsonHeaderParser {
            spec: spec
        }
    }

}

impl Display for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "JsonHeaderParser"));
        Ok(())
    }

}

impl Debug for JsonHeaderParser {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        try!(write!(fmt, "JsonHeaderParser, Spec: {:?}", self.spec));
        Ok(())
    }

}

impl FileHeaderParser for JsonHeaderParser {

    fn read(&self, string: Option<String>)
        -> Result<FileHeaderData, ParserError>
    {
        if string.is_some() {
            let s = string.unwrap();
            debug!("Deserializing: {}", s);
            let fromstr : R<Value> = from_str(&s[..]);
            if let Ok(ref content) = fromstr {
                return Ok(visit_json(&content))
            }
            let oe = fromstr.err().unwrap();
            let s = format!("JSON parser error: {}", oe.description());
            let e = ParserError::short(&s[..], s.clone(), 0);
            Err(e)
        } else {
            Ok(FileHeaderData::Null)
        }
    }

    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError> {
        let mut s = Vec::<u8>::new();
        {
            let mut ser = Serializer::pretty(&mut s);
            data.serialize(&mut ser).map_err(|e| {
                debug!("Serializer error: {:?}", e);
            }).ok();
        }

        String::from_utf8(s).or(
            Err(ParserError::short("Cannot parse utf8 bytes",
                                   String::from("<not printable>"),
                                   0)))
    }

}

// TODO: This function must be able to return a parser error
fn visit_json(v: &Value) -> FileHeaderData {
    match v {
        &Value::Null             => FileHeaderData::Null,
        &Value::Bool(b)          => FileHeaderData::Bool(b),
        &Value::I64(i)           => FileHeaderData::Integer(i),
        &Value::U64(u)           => FileHeaderData::UInteger(u),
        &Value::F64(f)           => FileHeaderData::Float(f),
        &Value::String(ref s)        => FileHeaderData::Text(s.clone()),
        &Value::Array(ref vec)       => {
            FileHeaderData::Array {
                values: Box::new(vec.clone().into_iter().map(|i| visit_json(&i)).collect())
            }
        },
        &Value::Object(ref btree)    => {
            let btree = btree.clone();
            FileHeaderData::Map{
                keys: btree.into_iter().map(|(k, v)|
                    FileHeaderData::Key {
                        name: k,
                        value: Box::new(visit_json(&v)),
                    }
                ).collect()
            }
        }
    }
}

impl Serialize for FileHeaderData {

    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Ser
    {
        match self {
            &FileHeaderData::Null               => {
                let o : Option<bool> = None;
                o.serialize(ser)
            },
            &FileHeaderData::Bool(ref b)            => b.serialize(ser),
            &FileHeaderData::Integer(ref i)         => i.serialize(ser),
            &FileHeaderData::UInteger(ref u)        => u.serialize(ser),
            &FileHeaderData::Float(ref f)           => f.serialize(ser),
            &FileHeaderData::Text(ref s)            => (&s[..]).serialize(ser),
            &FileHeaderData::Array{values: ref vs}  => vs.serialize(ser),
            &FileHeaderData::Map{keys: ref ks}      => {
                let mut hm = HashMap::new();

                for key in ks {
                    if let &FileHeaderData::Key{name: ref n, value: ref v} = key {
                        hm.insert(n, v);
                    } else {
                        panic!("Not a key: {:?}", key);
                    }
                }

                hm.serialize(ser)
            },
            &FileHeaderData::Key{name: _, value: _} => unreachable!(),

        }
    }

}

#[cfg(test)]
mod test {

    use std::ops::Deref;

    use super::JsonHeaderParser;
    use storage::parser::{FileHeaderParser, ParserError};
    use storage::file::header::data::FileHeaderData as FHD;
    use storage::file::header::spec::FileHeaderSpec as FHS;

    #[test]
    fn test_deserialization() {
        let text = String::from("{\"a\": 1, \"b\": -2}");
        let spec = FHS::Map {
            keys: vec![
                FHS::Key {
                    name: String::from("a"),
                    value_type: Box::new(FHS::UInteger)
                },
                FHS::Key {
                    name: String::from("b"),
                    value_type: Box::new(FHS::Integer)
                }
            ]
        };

        let parser = JsonHeaderParser::new(Some(spec));
        let parsed = parser.read(Some(text));
        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys: keys}) => {
                for k in keys {
                    match k {
                        FHD::Key{name: name, value: value} => {
                            assert!(name == "a" || name == "b", "Key unknown");
                            match value.deref() {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                &FHD::Integer(i) => assert_eq!(i, -2),
                                _ => assert!(false, "Integers are not here"),
                            }
                        },
                        _ => assert!(false, "Key is not a Key"),
                    }
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    #[test]
    fn test_deserialization_without_spec() {
        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);
        let parsed  = parser.read(Some(text));

        assert!(parsed.is_ok(), "Parsed is not ok: {:?}", parsed);

        match parsed.ok() {
            Some(FHD::Map{keys: keys}) => {
                for k in keys {
                    match_key(&k);
                }
            },

            _ => assert!(false, "Parsed is not a map"),
        }
    }

    fn match_key(k: &FHD) {
        use std::ops::Deref;

        match k {
            &FHD::Key{name: ref name, value: ref value} => {
                assert!(name == "a" || name == "b", "Key unknown");
                match value.deref() {
                    &FHD::Array{values: ref vs} => {
                        for value in vs.iter() {
                            match value {
                                &FHD::UInteger(u) => assert_eq!(u, 1),
                                _ => assert!(false, "UInt is not an UInt"),
                            }
                        }
                    }

                    &FHD::Map{keys: ref ks} => {
                        for key in ks.iter() {
                            match key {
                                &FHD::Key{name: ref name, value: ref value} => {
                                    match value.deref() {
                                        &FHD::Integer(i) => {
                                            assert_eq!(i, -2);
                                            assert_eq!(name, "c");
                                        },
                                        _ => assert!(false, "Int is not an Int"),
                                    };
                                },
                                _ => assert!(false, "Key is not a Key"),
                            }
                        }
                    }
                    _ => assert!(false, "Integers are not here"),
                }
            },
            _ => assert!(false, "Key in main Map is not a Key"),
        }
    }

    #[test]
    fn test_desser() {
        use serde_json::error::Result as R;
        use serde_json::{Value, from_str};

        let text    = String::from("{\"a\": [1], \"b\": {\"c\": -2}}");
        let parser  = JsonHeaderParser::new(None);

        let des = parser.read(Some(text.clone()));
        assert!(des.is_ok(), "Deserializing failed");

        let ser = parser.write(&des.unwrap());
        assert!(ser.is_ok(), "Parser error when serializing deserialized text");

        let json_text : R<Value> = from_str(&text[..]);
        let json_ser  : R<Value> = from_str(&ser.unwrap()[..]);

        assert!(json_text.is_ok(), "Could not use serde to serialize text for comparison");
        assert!(json_ser.is_ok(),  "Could not use serde to serialize serialized-deserialized text for comparison");
        assert_eq!(json_text.unwrap(), json_ser.unwrap());
    }

}
<|endoftext|>


<commit_before>use bitstring::Bit;

// Open questions:
// - How to declare some fields final
// - How to declare some fields mutable (can be changed for non-mut self)
// - Have the tree implement iter and simplify some methods with "fold".

/// Context tree which computes a probability estimate for a sequence of
/// bits based on a mixture model of Markov chains. Lower-degree Markov
/// chains have higher priors in the mixture model, thus formalizing the
/// notion of Occam's Razor.
///
/// In order to get a probability for a sequence, all bits in the sequence
/// must be processed in-order.
pub struct ContextTree {
  root: Node,
}

impl ContextTree {
  /// The depth of the tree is the distance between leaves and the root.
  /// For a given depth d, the tree will compute a mixture model of all
  /// Markov chains of degree at most d.
  pub fn create(depth: usize) -> ContextTree {
    ContextTree {
      root: Node::create_root(depth, 0),
    }
  }

  /// Returns the total number of nodes in the tree.
  pub fn size(&self) -> usize {
    self.root.size()
  }

  /// Returns log2 of the estimated probability of the current history.
  pub fn log_block_prob(&mut self) -> f64 {
    return self.root.log_weighted_prob();
  }
}

/// One node in the context tree. Maintains a count of the number
/// of zeroes and ones seen and provides access to partial results
/// of the overall probability estimates computed in the context
/// tree.
struct Node {
  /// Children.
  zero_child: Option<Box<Node>>,
  one_child: Option<Box<Node>>,

  /// Frequencies.
  zeroes: u64,
  ones: u64,

  /// The log2 of the probability of a sequence with self.zeroes zeroes
  /// and self.ones one. Computed using the Krichevsky Trofimov
  /// estimator algorithm.
  log_kt_prob: f64,

  /// The log2 of the weighted block probability of the current sequence.
  /// Funtion of self.zeroes and self.ones and the values recursively
  /// provided by the children of this node (if any), lazily recomputed.
  log_weighted_prob: f64,
}

impl Node {
  /// Creates a node and all its children recursively until the provided
  /// depth is reached.
  pub fn create_root(target_depth: usize, current_depth: usize) -> Node {
    if target_depth == current_depth {
      return Node::new(None, None);  // Leaf.
    } else {
      return Node::new(
          Some(Box::new(Node::create_root(target_depth, current_depth + 1))),
          Some(Box::new(Node::create_root(target_depth, current_depth + 1))));
    }
  }

  fn new(zero_child: Option<Box<Node>>, one_child: Option<Box<Node>>) -> Node {
    // Context trees are complete trees (either both children or no children).
    assert!(zero_child.is_none() == one_child.is_none());

    return Node {
      zero_child: zero_child,
      one_child: one_child,
      zeroes: 0,
      ones: 0,
      log_kt_prob: 0.0,
      log_weighted_prob: 0.0,
    };
  }

  pub fn log_weighted_prob(&self) -> f64 {
    self.log_weighted_prob
  }

  /// Updates the state of the node based on the value of the new bit.
  /// Assumes that child nodes (if any) have already been updated.
  pub fn update(&mut self, bit: Bit) {
    match bit {
      Bit::Zero => self.zeroes += 1,
      Bit::One => self.ones += 1,
    }

    // Old value + 0.5 is the same as new value - 0.5.
    let first_summand = match bit {
      Bit::Zero => self.zeroes as f64 - 0.5,
      Bit::One => self.ones as f64 - 0.5,
    }.log2();
    let norm_summand = ((self.zeroes + self.ones) as f64).log2();

    self.log_kt_prob = first_summand - norm_summand + self.log_kt_prob;
    self.update_weighted_prob();
  }

  /// Corresponds to undoing one update for the specified bit value.
  /// Assumes that child nodes (if any) have already been reverted.
  pub fn revert(&mut self, bit: Bit) {
    match bit {
      Bit::Zero => self.zeroes -= 1,
      Bit::One => self.ones -= 1,
    }
    // TODO(dinowernli): Update kt probs.
    self.update_weighted_prob();
  }

  /// Updates the value of log_weighted_prob. Assumes that log_kt_prob
  /// as well as all values in all children (if any) are up-to-date.
  fn update_weighted_prob(&mut self) {
    if self.is_leaf() {
      self.log_weighted_prob = self.log_kt_prob;
    }

    let log_weighted_probs =
        self.zero_child.as_ref().unwrap().log_weighted_prob() +
        self.one_child.as_ref().unwrap().log_weighted_prob();
    let exponent = log_weighted_probs - self.log_kt_prob;
    let power = exponent.exp2();

    // The recursive term should be log2(1 + 2^exponent). If the exponent is
    // large enough, 2^exponent is inf. In this case, we approximate
    // log2(1 + 2^exponent) by log2(2^exponent) = exponent.
    let inf = 1.0f64 / 0.0f64;
    let recursive_term =
        if power == inf { exponent } else { (power + 1.0).log2() };

    self.log_weighted_prob = self.log_kt_prob + recursive_term - 1.0;
  }

  /// Returns the number of nodes in the subtree rooted at this node.
  fn size(&self) -> usize {
    1 + match self.zero_child {
      None => 0,
      Some(ref node) => node.size(),
    } + match self.one_child {
      None => 0,
      Some(ref node) => node.size(),
    }
  }

  fn is_leaf(&self) -> bool {
    // By construction we have either both children or none.
    return self.zero_child.is_none();
  }
}
<commit_msg>Add a history to the context tree.<commit_after>use bitstring::Bit;
use bitstring::Bitstring;

// Open questions:
// - How to declare some fields final
// - How to declare some fields mutable (can be changed for non-mut self)
// - Have the tree implement iter and simplify some methods with "fold".

/// Context tree which computes a probability estimate for a sequence of
/// bits based on a mixture model of Markov chains. Lower-degree Markov
/// chains have higher priors in the mixture model, thus formalizing the
/// notion of Occam's Razor.
///
/// In order to get a probability for a sequence, all bits in the sequence
/// must be processed in-order.
pub struct ContextTree {
  root: Node,
  history: Bitstring,
}

impl ContextTree {
  /// The depth of the tree is the distance between leaves and the root.
  /// For a given depth d, the tree will compute a mixture model of all
  /// Markov chains of degree at most d.
  pub fn create(depth: usize) -> ContextTree {
    ContextTree {
      root: Node::create_root(depth, 0),
      history: Bitstring::empty(),
    }
  }

  /// Returns the total number of nodes in the tree.
  pub fn size(&self) -> usize {
    self.root.size()
  }

  /// Returns log2 of the estimated probability of the current history.
  fn log_block_prob(&mut self) -> f64 {
    return self.root.log_weighted_prob();
  }
}

/// One node in the context tree. Maintains a count of the number
/// of zeroes and ones seen and provides access to partial results
/// of the overall probability estimates computed in the context
/// tree.
struct Node {
  /// Children.
  zero_child: Option<Box<Node>>,
  one_child: Option<Box<Node>>,

  /// Frequencies.
  zeroes: u64,
  ones: u64,

  /// The log2 of the probability of a sequence with self.zeroes zeroes
  /// and self.ones one. Computed using the Krichevsky Trofimov
  /// estimator algorithm.
  log_kt_prob: f64,

  /// The log2 of the weighted block probability of the current sequence.
  /// Funtion of self.zeroes and self.ones and the values recursively
  /// provided by the children of this node (if any), lazily recomputed.
  log_weighted_prob: f64,
}

impl Node {
  /// Creates a node and all its children recursively until the provided
  /// depth is reached.
  pub fn create_root(target_depth: usize, current_depth: usize) -> Node {
    if target_depth == current_depth {
      return Node::new(None, None);  // Leaf.
    } else {
      return Node::new(
          Some(Box::new(Node::create_root(target_depth, current_depth + 1))),
          Some(Box::new(Node::create_root(target_depth, current_depth + 1))));
    }
  }

  fn new(zero_child: Option<Box<Node>>, one_child: Option<Box<Node>>) -> Node {
    // Context trees are complete trees (either both children or no children).
    assert!(zero_child.is_none() == one_child.is_none());

    return Node {
      zero_child: zero_child,
      one_child: one_child,
      zeroes: 0,
      ones: 0,
      log_kt_prob: 0.0,
      log_weighted_prob: 0.0,
    };
  }

  pub fn log_weighted_prob(&self) -> f64 {
    self.log_weighted_prob
  }

  /// Updates the state of the node based on the value of the new bit.
  /// Assumes that child nodes (if any) have already been updated.
  pub fn update(&mut self, bit: Bit) {
    match bit {
      Bit::Zero => self.zeroes += 1,
      Bit::One => self.ones += 1,
    }

    // Old value + 0.5 is the same as new value - 0.5.
    let first_summand = match bit {
      Bit::Zero => self.zeroes as f64 - 0.5,
      Bit::One => self.ones as f64 - 0.5,
    }.log2();
    let norm_summand = ((self.zeroes + self.ones) as f64).log2();

    self.log_kt_prob = first_summand - norm_summand + self.log_kt_prob;
    self.update_weighted_prob();
  }

  /// Corresponds to undoing one update for the specified bit value.
  /// Assumes that child nodes (if any) have already been reverted.
  pub fn revert(&mut self, bit: Bit) {
    match bit {
      Bit::Zero => self.zeroes -= 1,
      Bit::One => self.ones -= 1,
    }
    // TODO(dinowernli): Update kt probs.
    self.update_weighted_prob();
  }

  /// Updates the value of log_weighted_prob. Assumes that log_kt_prob
  /// as well as all values in all children (if any) are up-to-date.
  fn update_weighted_prob(&mut self) {
    if self.is_leaf() {
      self.log_weighted_prob = self.log_kt_prob;
    }

    let log_weighted_probs =
        self.zero_child.as_ref().unwrap().log_weighted_prob() +
        self.one_child.as_ref().unwrap().log_weighted_prob();
    let exponent = log_weighted_probs - self.log_kt_prob;
    let power = exponent.exp2();

    // The recursive term should be log2(1 + 2^exponent). If the exponent is
    // large enough, 2^exponent is inf. In this case, we approximate
    // log2(1 + 2^exponent) by log2(2^exponent) = exponent.
    let inf = 1.0f64 / 0.0f64;
    let recursive_term =
        if power == inf { exponent } else { (power + 1.0).log2() };

    self.log_weighted_prob = self.log_kt_prob + recursive_term - 1.0;
  }

  /// Returns the number of nodes in the subtree rooted at this node.
  fn size(&self) -> usize {
    1 + match self.zero_child {
      None => 0,
      Some(ref node) => node.size(),
    } + match self.one_child {
      None => 0,
      Some(ref node) => node.size(),
    }
  }

  fn is_leaf(&self) -> bool {
    // By construction we have either both children or none.
    return self.zero_child.is_none();
  }
}
<|endoftext|>


<commit_before>//! Primitives used by num_format and sub_modules.
//! never dealt with above (e.g. Sub Tokenizer never uses these)

use itertools::{put_back_n, PutBackN};
use std::str::Chars;
use uucore::{display::Quotable, show_error};

use super::format_field::FormatField;

// contains the rough ingredients to final
// output for a number, organized together
// to allow for easy generalization of output manipulation
// (e.g. max number of digits after decimal)
pub struct FormatPrimitive {
    pub prefix: Option<String>,
    pub pre_decimal: Option<String>,
    pub post_decimal: Option<String>,
    pub suffix: Option<String>,
}

impl Default for FormatPrimitive {
    fn default() -> FormatPrimitive {
        FormatPrimitive {
            prefix: None,
            pre_decimal: None,
            post_decimal: None,
            suffix: None,
        }
    }
}

#[derive(Clone, PartialEq)]
pub enum Base {
    Ten = 10,
    Hex = 16,
    Octal = 8,
}

// information from the beginning of a numeric argument
// the precedes the beginning of a numeric value
pub struct InitialPrefix {
    pub radix_in: Base,
    pub sign: i8,
    pub offset: usize,
}

pub trait Formatter {
    //  return a FormatPrimitive for
    // particular field char(s), given the argument
    // string and prefix information (sign, radix)
    fn get_primitive(
        &self,
        field: &FormatField,
        in_prefix: &InitialPrefix,
        str_in: &str,
    ) -> Option<FormatPrimitive>;
    // return a string from a FormatPrimitive,
    // given information about the field
    fn primitive_to_str(&self, prim: &FormatPrimitive, field: FormatField) -> String;
}
pub fn get_it_at(offset: usize, str_in: &str) -> PutBackN<Chars> {
    put_back_n(str_in[offset..].chars())
}

// TODO: put this somewhere better
pub fn warn_incomplete_conv(pf_arg: &str) {
    // important: keep println here not print
    show_error!("{}: value not completely converted", pf_arg.maybe_quote());
}
<commit_msg>printf: derive Default impl for FormatPrimitive<commit_after>//! Primitives used by num_format and sub_modules.
//! never dealt with above (e.g. Sub Tokenizer never uses these)

use itertools::{put_back_n, PutBackN};
use std::str::Chars;
use uucore::{display::Quotable, show_error};

use super::format_field::FormatField;

// contains the rough ingredients to final
// output for a number, organized together
// to allow for easy generalization of output manipulation
// (e.g. max number of digits after decimal)
#[derive(Default)]
pub struct FormatPrimitive {
    pub prefix: Option<String>,
    pub pre_decimal: Option<String>,
    pub post_decimal: Option<String>,
    pub suffix: Option<String>,
}

#[derive(Clone, PartialEq)]
pub enum Base {
    Ten = 10,
    Hex = 16,
    Octal = 8,
}

// information from the beginning of a numeric argument
// the precedes the beginning of a numeric value
pub struct InitialPrefix {
    pub radix_in: Base,
    pub sign: i8,
    pub offset: usize,
}

pub trait Formatter {
    //  return a FormatPrimitive for
    // particular field char(s), given the argument
    // string and prefix information (sign, radix)
    fn get_primitive(
        &self,
        field: &FormatField,
        in_prefix: &InitialPrefix,
        str_in: &str,
    ) -> Option<FormatPrimitive>;
    // return a string from a FormatPrimitive,
    // given information about the field
    fn primitive_to_str(&self, prim: &FormatPrimitive, field: FormatField) -> String;
}
pub fn get_it_at(offset: usize, str_in: &str) -> PutBackN<Chars> {
    put_back_n(str_in[offset..].chars())
}

// TODO: put this somewhere better
pub fn warn_incomplete_conv(pf_arg: &str) {
    // important: keep println here not print
    show_error!("{}: value not completely converted", pf_arg.maybe_quote());
}
<|endoftext|>


<commit_before>//! Abstractions for page tables and other paging related structures.
//!
//! Page tables translate virtual memory “pages” to physical memory “frames”.

pub use self::frame::PhysFrame;
pub use self::frame_alloc::{FrameAllocator, FrameDeallocator};
#[cfg(target_arch = "x86_64")]
pub use self::mapper::RecursivePageTable;
pub use self::mapper::{MappedPageTable, Mapper, MapperAllSizes};
pub use self::page::{Page, PageSize, Size1GiB, Size2MiB, Size4KiB};
pub use self::page_table::{PageTable, PageTableFlags};

pub mod frame;
mod frame_alloc;
pub mod mapper;
pub mod page;
pub mod page_table;
<commit_msg>Mark paging::{MappedPageTable, RecursivePageTable} re-exports as doc(no_inline)<commit_after>//! Abstractions for page tables and other paging related structures.
//!
//! Page tables translate virtual memory “pages” to physical memory “frames”.

pub use self::frame::PhysFrame;
pub use self::frame_alloc::{FrameAllocator, FrameDeallocator};
#[cfg(target_arch = "x86_64")]
#[doc(no_inline)]
pub use self::mapper::{MappedPageTable, RecursivePageTable};
pub use self::mapper::{Mapper, MapperAllSizes};
pub use self::page::{Page, PageSize, Size1GiB, Size2MiB, Size4KiB};
pub use self::page_table::{PageTable, PageTableFlags};

pub mod frame;
mod frame_alloc;
pub mod mapper;
pub mod page;
pub mod page_table;
<|endoftext|>