<commit_before>extern crate futures;
extern crate notify;
extern crate serde;
extern crate serde_json;
extern crate textnonce;
extern crate chrono;

use std::sync::mpsc;
use std::error::Error as StdError;
use std::ops::Drop;
use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt};

use serde::{Serialize, Deserialize};

pub struct Queue<T> {
    path: String,
    _placeholder: std::marker::PhantomData<T>,
}

impl<T: Serialize + Deserialize> Queue<T> {
    pub fn new(path: &str) -> Result<Queue<T>, std::io::Error> {
        std::fs::DirBuilder::new().recursive(true).mode(0o700).create(path)?;
        Ok(Queue::<T> {
            path: path.to_string(),
            _placeholder: std::marker::PhantomData,
        })
    }

    pub fn push(&self, item: T) -> Result<(), std::io::Error> {
        let mut item_path = std::path::PathBuf::from(&self.path);
        let item_name = format!("{}-{}",
                                chrono::UTC::now().timestamp(),
                                textnonce::TextNonce::sized_urlsafe(32).unwrap().into_string());
        item_path.push(item_name);
        let complete_path = item_path.to_str().unwrap();
        item_path.with_extension("inc");
        let incomplete_path = item_path.to_str().unwrap().to_string();

        {
            let mut item_file = std::fs::OpenOptions::new().write(true)
                .mode(0o600)
                .create_new(true)
                .open(&incomplete_path)?;
            match serde_json::to_writer(&mut item_file, &item) {
                Ok(_) => {}
                Err(e) => return Err(to_ioerror(&e)),
            }
        }
        std::fs::rename(incomplete_path, complete_path)?;
        Ok(())
    }

    pub fn pop(&self) -> Result<Option<T>, std::io::Error> {
        let dirh = std::fs::read_dir(&self.path)?;
        for maybe_dirent in dirh {
            let item_path = match maybe_dirent {
                Ok(dirent) => dirent.path(),
                Err(e) => return Err(e),
            };
            {
                let item_file = std::fs::OpenOptions::new().read(true)
                    .open(&item_path)?;
                let _cleanup = Cleanup::File(item_path.to_str().unwrap().to_string());
                let maybe_item: Result<T, serde_json::error::Error> =
                    serde_json::from_reader(item_file);
                match maybe_item {
                    Ok(item) => return Ok(Some(item)),
                    Err(e) => return Err(to_ioerror(&e)),
                }
            }
        }
        Ok(None)
    }

    pub fn pull(&self) -> Result<Option<T>, std::io::Error> {
        let dirh = std::fs::read_dir(&self.path)?;
        let mut items: Vec<_> = dirh.filter(|item| match item {
                &Ok(ref dirent) => {
                    let p = dirent.path();
                    match p.extension() {
                        Some(_) => false,
                        None => p.is_file(),
                    }
                }
                &Err(_) => false,
            })
            .map(|item| item.unwrap())
            .collect();
        items.sort_by_key(|dir| dir.path());
        if items.is_empty() {
            return Ok(None);
        }
        let item_path = &items[0].path();
        {
            let item_file = std::fs::OpenOptions::new().read(true)
                .open(item_path)?;
            let _cleanup = Cleanup::File(item_path.to_str().unwrap().to_string());
            let maybe_item: Result<T, serde_json::error::Error> =
                serde_json::from_reader(item_file);
            match maybe_item {
                Ok(item) => return Ok(Some(item)),
                Err(e) => return Err(to_ioerror(&e)),
            }
        }
    }
}

pub struct QueueStream<T> {
    queue: Queue<T>,
    _watcher: notify::RecommendedWatcher,
    rx: mpsc::Receiver<notify::DebouncedEvent>,
}

impl<T: Serialize + Deserialize> QueueStream<T> {
    pub fn new(path: &str) -> Result<QueueStream<T>, std::io::Error> {
        let queue = Queue::<T>::new(path)?;
        let (tx, rx) = mpsc::channel();
        let watcher = match notify::Watcher::new(tx, std::time::Duration::from_secs(1)) {
            Ok(watcher) => watcher,
            Err(notify::Error::Io(e)) => return Err(e),
            Err(e) => return Err(to_ioerror(&e)),
        };
        Ok(QueueStream::<T> {
            queue: queue,
            _watcher: watcher,
            rx: rx,
        })
    }
}

impl<T: Serialize + Deserialize> futures::stream::Stream for QueueStream<T> {
    type Item = T;
    type Error = std::io::Error;

    fn poll(&mut self) -> futures::Poll<Option<Self::Item>, Self::Error> {
        match self.rx.try_recv() {
            Ok(_) => {
                match self.queue.pop() {
                    Ok(Some(t)) => Ok(futures::Async::Ready(Some(t))),
                    Ok(None) => Ok(futures::Async::NotReady),
                    Err(e) => Err(to_ioerror(&e)),
                }
            }
            Err(mpsc::TryRecvError::Empty) => Ok(futures::Async::NotReady),
            Err(mpsc::TryRecvError::Disconnected) => Ok(futures::Async::Ready(None)),
        }
    }
}

fn to_ioerror(e: &StdError) -> std::io::Error {
    std::io::Error::new(std::io::ErrorKind::Other, e.description())
}

enum Cleanup {
    File(String),
}

impl Drop for Cleanup {
    fn drop(&mut self) {
        match self {
            &mut Cleanup::File(ref path) => {
                match std::fs::remove_file(path) {
                    Ok(_) => {}
                    Err(e) => {
                        println!("warning: failed to remove file {}: {}", path, e);
                    }
                }
            }
        }
    }
}
<commit_msg>Add tests, doc comments, some cleanup.<commit_after>#[macro_use]
extern crate serde_derive;

extern crate futures;
extern crate notify;
extern crate serde;
extern crate serde_json;
extern crate textnonce;
extern crate chrono;

use std::sync::mpsc;
use std::error::Error as StdError;
use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt};

use serde::{Serialize, Deserialize};

/// A durable queue backed by the filesystem.
///
/// This queue stores items of type T as files in a spool directory. Files are serialized with
/// serde_json so T must derive serde's Serialize and Deserialize traits.
///
/// The queue's directory should only contain items of the same type. Any files in the spool
/// that fail to deserialize will be discarded.
pub struct Queue<T> {
    path: String,
    _placeholder: std::marker::PhantomData<T>,
}

impl<T: Serialize + Deserialize> Queue<T> {
    /// Create a new `Queue<T>` using the given directory path for storage.
    pub fn new(path: &str) -> Result<Queue<T>, std::io::Error> {
        std::fs::DirBuilder::new().recursive(true).mode(0o700).create(path)?;
        Ok(Queue::<T> {
            path: path.to_string(),
            _placeholder: std::marker::PhantomData,
        })
    }

    /// Push an item into the Queue.
    pub fn push(&self, item: T) -> Result<(), std::io::Error> {
        let mut item_path = std::path::PathBuf::from(&self.path);
        let item_name = format!("{}-{}", chrono::UTC::now().timestamp(), rand_string());
        item_path.push(item_name);
        let complete_path = item_path.to_str().unwrap();
        item_path.with_extension("inc");
        let incomplete_path = item_path.to_str().unwrap().to_string();

        {
            let mut item_file = std::fs::OpenOptions::new().write(true)
                .mode(0o600)
                .create_new(true)
                .open(&incomplete_path)?;
            match serde_json::to_writer(&mut item_file, &item) {
                Ok(_) => {}
                Err(e) => return Err(to_ioerror(&e)),
            }
        }
        std::fs::rename(incomplete_path, complete_path)?;
        Ok(())
    }

    /// Pop an item off the queue without regard to ordering.
    ///
    /// This method returns the first matching directory entry. Queue ordering cannot be
    /// guaranteed, as the serialized file is chosen based on the filesystem's ordering.
    ///
    /// Use this method when you value speed over order-correctness.
    pub fn pop(&self) -> Result<Option<T>, std::io::Error> {
        let dirh = std::fs::read_dir(&self.path)?;
        for maybe_dirent in dirh {
            let item_path = match maybe_dirent {
                Ok(dirent) => dirent.path(),
                Err(e) => return Err(e),
            };
            {
                let item_file = std::fs::OpenOptions::new().read(true)
                    .open(&item_path)?;
                let _cleanup = cleanup::Cleanup::File(item_path.to_str().unwrap().to_string());
                let maybe_item: Result<T, serde_json::error::Error> =
                    serde_json::from_reader(item_file);
                match maybe_item {
                    Ok(item) => return Ok(Some(item)),
                    Err(e) => return Err(to_ioerror(&e)),
                }
            }
        }
        Ok(None)
    }

    /// Pull the next queued item off the queue.
    ///
    /// This method returns the next item, based on the system time when the item was pushed
    /// onto the queue. Note that system time may not always be in monotonically increasing order,
    /// so this is not strictly guaranteed.
    ///
    /// This method may be much slower, especially if the queue size grows large.
    ///
    /// If multiple threads or processes are pulling from the same queue directory, globally
    /// duplicates may occur, since reading the item's file and removing it is not atomic.
    pub fn pull(&self) -> Result<Option<T>, std::io::Error> {
        let dirh = std::fs::read_dir(&self.path)?;
        let mut items: Vec<_> = dirh.filter(|item| match item {
                &Ok(ref dirent) => {
                    let p = dirent.path();
                    match p.extension() {
                        Some(_) => false,
                        None => p.is_file(),
                    }
                }
                &Err(_) => false,
            })
            .map(|item| item.unwrap())
            .collect();
        items.sort_by_key(|dir| dir.path());
        if items.is_empty() {
            return Ok(None);
        }
        let item_path = &items[0].path();
        {
            let item_file = std::fs::OpenOptions::new().read(true)
                .open(item_path)?;
            let _cleanup = cleanup::Cleanup::File(item_path.to_str().unwrap().to_string());
            let maybe_item: Result<T, serde_json::error::Error> =
                serde_json::from_reader(item_file);
            match maybe_item {
                Ok(item) => return Ok(Some(item)),
                Err(e) => return Err(to_ioerror(&e)),
            }
        }
    }
}

/// Process a Queue<T> as a stream of future values.
pub struct QueueStream<T> {
    queue: Queue<T>,
    _watcher: notify::RecommendedWatcher,
    rx: mpsc::Receiver<notify::DebouncedEvent>,
}

impl<T: Serialize + Deserialize> QueueStream<T> {
    /// Create a new QueueStream<T> with the given spool path.
    pub fn new(path: &str) -> Result<QueueStream<T>, std::io::Error> {
        let queue = Queue::<T>::new(path)?;
        let (tx, rx) = mpsc::channel();
        let watcher = match notify::Watcher::new(tx, std::time::Duration::from_secs(1)) {
            Ok(watcher) => watcher,
            Err(notify::Error::Io(e)) => return Err(e),
            Err(e) => return Err(to_ioerror(&e)),
        };
        Ok(QueueStream::<T> {
            queue: queue,
            _watcher: watcher,
            rx: rx,
        })
    }
}

impl<T: Serialize + Deserialize> futures::stream::Stream for QueueStream<T> {
    type Item = T;
    type Error = std::io::Error;

    /// Attempt to pull the next item off the stream.
    ///
    /// This method polls the underlying filesystem watcher for changes since the last poll.
    fn poll(&mut self) -> futures::Poll<Option<Self::Item>, Self::Error> {
        match self.rx.try_recv() {
            Ok(_) => {
                match self.queue.pop() {
                    Ok(Some(t)) => Ok(futures::Async::Ready(Some(t))),
                    Ok(None) => Ok(futures::Async::NotReady),
                    Err(e) => Err(to_ioerror(&e)),
                }
            }
            Err(mpsc::TryRecvError::Empty) => Ok(futures::Async::NotReady),
            Err(mpsc::TryRecvError::Disconnected) => Ok(futures::Async::Ready(None)),
        }
    }
}

fn to_ioerror(e: &StdError) -> std::io::Error {
    std::io::Error::new(std::io::ErrorKind::Other, e.description())
}

mod cleanup {
    use std;
    use std::ops::Drop;

    pub enum Cleanup {
        File(String),
        #[allow(dead_code)]
        Dir(String),
    }

    impl Drop for Cleanup {
        fn drop(&mut self) {
            match self {
                &mut Cleanup::File(ref path) => {
                    match std::fs::remove_file(path) {
                        Ok(_) => {}
                        Err(e) => {
                            println!("warning: failed to remove file {}: {}", path, e);
                        }
                    }
                }
                &mut Cleanup::Dir(ref path) => {
                    match std::fs::remove_dir_all(path) {
                        Ok(_) => {}
                        Err(e) => {
                            println!("warning: failed to remove file {}: {}", path, e);
                        }
                    }
                }
            }
        }
    }
}

fn rand_string() -> String {
    textnonce::TextNonce::sized_urlsafe(32).unwrap().into_string()
}

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

    #[derive(Serialize, Deserialize)]
    #[derive(PartialEq,Debug)]
    struct Foo {
        i: i32,
        b: bool,
        s: String,
    }

    fn new_queue() -> (Queue<Foo>, cleanup::Cleanup) {
        let mut spool_path_buf = std::env::temp_dir();
        spool_path_buf.push(rand_string());
        let spool_dir = spool_path_buf.to_str().unwrap();
        let _cleanup = cleanup::Cleanup::Dir(spool_dir.to_string());
        let q = Queue::<Foo>::new(spool_dir).unwrap();
        (q, _cleanup)
    }

    #[test]
    fn test_push_pop() {
        let (q, _cleanup) = new_queue();
        assert!(q.push(Foo {
                i: 999,
                b: true,
                s: "foo".to_string(),
            })
            .is_ok());
        let result = q.pop().unwrap().unwrap();
        assert_eq!(result,
                   Foo {
                       i: 999,
                       b: true,
                       s: "foo".to_string(),
                   });
    }

    #[test]
    fn test_push_pull() {
        let (q, _cleanup) = new_queue();
        assert!(q.push(Foo {
                i: 888,
                b: false,
                s: "bar".to_string(),
            })
            .is_ok());
        let result = q.pop().unwrap().unwrap();
        assert_eq!(result,
                   Foo {
                       i: 888,
                       b: false,
                       s: "bar".to_string(),
                   });
    }
}
<|endoftext|>


<commit_before>extern crate cards;

use std::cmp::{Ord};

use cards::card::{Card};

#[derive(Debug, PartialEq)]
#[derive(Eq, Hash)]
#[derive(PartialOrd, Ord)]
pub enum HandRankClass {
    HighCard,
    OnePair,
    TwoPair,
    ThreeOfAKind,
    Straight,
    Flush,
    FullHouse,
    FourOfAKind,
    StraightFlush,
}

// find maximum value to determine best hand
// larger values are "better", inverting the Cactus Kev convention
pub type HandRank = u16;

pub const HAND_RANK_COUNT : u16 = 7462;

// assumes there are HAND_RANK_COUNT distinct hand ranks, where the
// largest are the most valuable. An inversion of cactus kev's ranks
pub fn hand_rank_to_class(val: &HandRank) -> HandRankClass {
    match *val {
        x if x < HAND_RANK_COUNT-6185 => HandRankClass::HighCard,
        x if x < HAND_RANK_COUNT-3325 => HandRankClass::OnePair,
        x if x < HAND_RANK_COUNT-2467 => HandRankClass::TwoPair,
        x if x < HAND_RANK_COUNT-1609 => HandRankClass::ThreeOfAKind,
        x if x < HAND_RANK_COUNT-1599 => HandRankClass::Straight,
        x if x < HAND_RANK_COUNT-322  => HandRankClass::Flush,
        x if x < HAND_RANK_COUNT-166  => HandRankClass::FullHouse,
        x if x < HAND_RANK_COUNT-10   => HandRankClass::FourOfAKind,
        x if x < HAND_RANK_COUNT-0    => HandRankClass::StraightFlush,
        _                              => panic!("Unexpected hand rank value!")
    }
}

pub enum CardSlot {
    Empty,
    Dealt(Card),
}

impl CardSlot {
    pub fn expect_borrow(&self) -> &Card {
        match self {
            &CardSlot::Empty => panic!("You are trying to borrow a non-dealt card"),
            &CardSlot::Dealt(ref x) => x
        }
    }
}

pub struct HandCards(pub CardSlot, pub CardSlot);
pub struct CommunityCards(pub CardSlot, pub CardSlot, pub CardSlot, pub CardSlot, pub CardSlot);
<commit_msg>Idem.<commit_after>extern crate cards;

use std::cmp::{Ord};

use cards::card::{Card};

#[derive(Debug, PartialEq)]
#[derive(Eq, Hash)]
#[derive(PartialOrd, Ord)]
pub enum HandRankClass {
    HighCard,
    OnePair,
    TwoPair,
    ThreeOfAKind,
    Straight,
    Flush,
    FullHouse,
    FourOfAKind,
    StraightFlush,
}

// find maximum value to determine best hand
// larger values are "better", inverting the Cactus Kev convention
pub type HandRank = u16;

pub const HAND_RANK_COUNT : u16 = 7462;

// assumes there are HAND_RANK_COUNT distinct hand ranks, where the
// largest are the most valuable. An inversion of cactus kev's ranks
pub fn hand_rank_to_class(val: &HandRank) -> HandRankClass {
    match *val {
        x if x <= HAND_RANK_COUNT-6185 => HandRankClass::HighCard,
        x if x <= HAND_RANK_COUNT-3325 => HandRankClass::OnePair,
        x if x <= HAND_RANK_COUNT-2467 => HandRankClass::TwoPair,
        x if x <= HAND_RANK_COUNT-1609 => HandRankClass::ThreeOfAKind,
        x if x <= HAND_RANK_COUNT-1599 => HandRankClass::Straight,
        x if x <= HAND_RANK_COUNT-322  => HandRankClass::Flush,
        x if x <= HAND_RANK_COUNT-166  => HandRankClass::FullHouse,
        x if x <= HAND_RANK_COUNT-10   => HandRankClass::FourOfAKind,
        x if x <= HAND_RANK_COUNT-0    => HandRankClass::StraightFlush,
        _                              => panic!("Unexpected hand rank value!")
    }
}

pub enum CardSlot {
    Empty,
    Dealt(Card),
}

impl CardSlot {
    pub fn expect_borrow(&self) -> &Card {
        match self {
            &CardSlot::Empty => panic!("You are trying to borrow a non-dealt card"),
            &CardSlot::Dealt(ref x) => x
        }
    }
}

pub struct HandCards(pub CardSlot, pub CardSlot);
pub struct CommunityCards(pub CardSlot, pub CardSlot, pub CardSlot, pub CardSlot, pub CardSlot);
<|endoftext|>


<commit_before>#![feature(vec_push_all)]

extern crate unicode_segmentation;
use unicode_segmentation::UnicodeSegmentation;

use std::rc::Rc;

// const SPLIT_LEN: usize = 10;
// const JOIN_LEN: usize = 5;
// const REBALANCE_RATIO: f32 = 1.2;

pub enum Rope {
    Leaf { base: Rc<String>,
           start: usize,
           end: usize,
           graphemes: usize },
    Concat { left: Rc<Rope>,
             right: Rc<Rope>,
             graphemes: usize },
}
impl Rope {
    /// Create a new rope leaf
    pub fn from_str(base: &str) -> Rope {
        let num_graphemes = count_grapheme_clusters(base);
        Rope::Leaf { base: Rc::new(String::from(base)),
                     start: 0,
                     end: base.len(),
                     graphemes: num_graphemes }
    }
    /// Gets the number of Unicode grapheme clusters in the children of this node
    pub fn num_graphemes(&self) -> usize {
        match *self {
            Rope::Leaf { graphemes, .. } => graphemes,
            Rope::Concat { graphemes, .. } => graphemes,
        }
    }
    /// Split a Rope after the nth grapheme
    pub fn split(&self, grapheme_index: usize) -> Option<(Rope, Rope)> {
        match *self {
            Rope::Leaf { ref base, start, end, .. } => {
                grapheme_byte_index(&base[start..end], grapheme_index)
                    .map(|byte_index| {
                        let left = Rope::Leaf { base: base.clone(),
                                                start: start,
                                                end: start+byte_index,
                                                graphemes: count_grapheme_clusters(&base[start..start+byte_index]) };
                        let right = Rope::Leaf { base: base.clone(),
                                                 start: start+byte_index,
                                                 end: end,
                                                 graphemes: count_grapheme_clusters(&base[start+byte_index..end]) };
                        (left, right)
                    })
            },
            Rope::Concat{ ref left, ref right, .. } => {
                // self is (left, right)
                if left.num_graphemes() >= grapheme_index {
                    // split left into (l1, l2), return (l1, concat(l2, right))
                    left.split(grapheme_index).map(|(l1, l2)| {
                        (l1, Rope::Concat { left: Rc::new(l2.clone()),
                                            right: right.clone(),
                                            graphemes: l2.num_graphemes() + right.num_graphemes() })
                    })
                } else {
                    // split right into (r1, r2), return (concat(left, r1), r2)
                    right.split(grapheme_index - left.num_graphemes()).map(|(r1, r2)| {
                        (Rope::Concat { left: left.clone(),
                                        right: Rc::new(r1.clone()),
                                        graphemes: left.num_graphemes() + r1.num_graphemes() },
                         r2)
                    })
                }
            }
        }
    }
    /// Collect the pieces of this Rope into a continuous String
    pub fn to_string(&self) -> String {
        let mut buf = String::with_capacity(self.num_graphemes());

        fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
            let mut v = vec![];
            match *root {
                Rope::Leaf { ref base, start, end, .. } => {
                    v.push( &base[start..end] );
                },
                Rope::Concat { ref left, ref right, .. } => {
                    v.push_all(&str_parts(&left));
                    v.push_all(&str_parts(&right));
                },
            }
            v
        }
        for part in str_parts(self).iter() {
            buf.push_str(part);
        }

        buf
    }
    /// Join two pieces into a Rope
    pub fn join(left: Rope, right: Rope) -> Rope {
        let graphemes = left.num_graphemes() + right.num_graphemes();
        Rope::Concat { left: Rc::new(left),
                       right: Rc::new(right),
                       graphemes: graphemes }
    }
    /// Insert a string into a Rope by splitting and joining nodes
    /// Returns a new Rope, leaving the original unchanged
    pub fn insert(&self, grapheme_index: usize, value: &str) -> Option<Rope> {
        self.split(grapheme_index).map(|(left, right)| {
            let left = Rope::join(left, Rope::from_str(value));
            Rope::join(left, right)
        })
    }
    /// Append a string to the Rope, returning a new instance and leaving the original unchanged
    pub fn append(&self, value: &str) -> Rope {
        Rope::join(self.clone(), Rope::from_str(value))
    }
    /// Remove a substring range from the Rope
    pub fn delete(&self, start_grapheme: usize, num_graphemes: usize) -> Option<Rope> {
        self.split(start_grapheme).map(|(head, middle)| {
            middle.split(num_graphemes).map(|(_, tail)| {
                Rope::join(head.clone(), tail.clone())
            })
        }).unwrap()
    }
}
impl Clone for Rope {
    fn clone(&self) -> Rope {
        match *self {
            Rope::Leaf { ref base, start, end, graphemes } => Rope::Leaf { base: base.clone(),
                                                                           start: start,
                                                                           end: end,
                                                                           graphemes: graphemes },
            Rope::Concat { ref left, ref right, graphemes } => Rope::Concat { left: left.clone(),
                                                                              right: right.clone(),
                                                                              graphemes: graphemes },
        }
    }
}
/// Count the number of unicode extended grapheme clusters in a string
/// This is O(n)
fn count_grapheme_clusters(s: &str) -> usize {
    UnicodeSegmentation::graphemes(s, true).collect::<Vec<&str>>().len()
}

/// Find the byte index of the nth grapheme cluster in a string
/// Returns None if the grapheme index is out of bounds
fn grapheme_byte_index(base: &str, nth_grapheme: usize) -> Option<usize> {
    UnicodeSegmentation::grapheme_indices(base, true)
        .nth(nth_grapheme).map(|(i, _)| i)
}

#[cfg(test)]
fn to_string_debug(root: &Rope) -> String {
    let mut buf = String::with_capacity(root.num_graphemes());

    fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
        let mut v = vec![];
        match *root {
            Rope::Leaf { ref base, start, end, .. } => {
                v.push( "<" );
                v.push( &base[start..end] );
                v.push( ">" );
            },
            Rope::Concat { ref left, ref right, .. } => {
                v.push( "(" );
                v.push_all(&str_parts(&left));
                v.push( "," );
                v.push_all(&str_parts(&right));
                v.push( ")" );
            },
        }
        v
    }
    for part in str_parts(root).iter() {
        buf.push_str(part);
    }

    buf
}

#[test]
fn test_count_grapheme_clusters() {
    // 11 bytes, 3 grapheme clusters
    let s = "a̐éö̲";
    assert_eq!(s.len(), 11);
    assert_eq!(count_grapheme_clusters(s), 3);
}

#[test]
fn test_create_leaf() {
    let leaf = Rope::from_str("a̐éö̲");
    assert_eq!(leaf.num_graphemes(), 3);
}

#[test]
fn test_split_leaf() {
    let leaf = Rope::from_str("a̐éö̲a̐éö̲");
    let (left, right) = leaf.split(3).unwrap();
    assert_eq!(left.num_graphemes(), right.num_graphemes());
    assert_eq!(left.to_string(), "a̐éö̲");
}

#[test]
fn test_create_rope() {
    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.");
    assert_eq!(rope.num_graphemes(), 44);
    assert_eq!(rope.to_string(), "The quick brown fox jumps over the lazy dog.");
}

#[test]
fn test_rope_operations() {
    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.");

    let (left, right) = rope.split(22).unwrap();
    assert_eq!(left.to_string(), "The quick brown fox ju");
    assert_eq!(right.to_string(), "mps over the lazy dog.");

    let rope2 = Rope::join(left, Rope::from_str("mps over the tiny wooden fence!"));
    assert_eq!(rope2.to_string(), "The quick brown fox jumps over the tiny wooden fence!");

    let rope3 = rope2.insert(10, "(and really very clever) ").unwrap();
    assert_eq!(rope3.to_string(), "The quick (and really very clever) brown fox jumps over the tiny wooden fence!");

    let rope4 = rope2.append(" One fish two fish, red fish blue fish.");
    assert_eq!(rope4.to_string(), "The quick brown fox jumps over the tiny wooden fence! One fish two fish, red fish blue fish.");

    let rope5 = rope4.delete(4, 6).expect("a").delete(14, 6).expect("b").insert(13, " hops").expect("c");

    println!("{}\n{}\n", rope.to_string(), to_string_debug(&rope));
    println!("{}\n{}\n", rope2.to_string(), to_string_debug(&rope2));
    println!("{}\n{}\n", rope3.to_string(), to_string_debug(&rope3));
    println!("{}\n{}\n", rope4.to_string(), to_string_debug(&rope4));
    println!("{}\n{}\n", rope5.to_string(), to_string_debug(&rope5));
}
<commit_msg>Add Index and Iterator impls, tests<commit_after>#![feature(vec_push_all)]

extern crate unicode_segmentation;
use unicode_segmentation::UnicodeSegmentation;

use std::rc::Rc;

// const SPLIT_LEN: usize = 10;
// const JOIN_LEN: usize = 5;
// const REBALANCE_RATIO: f32 = 1.2;

pub enum Rope {
    Leaf { base: Rc<String>,
           start: usize,
           end: usize,
           graphemes: usize },
    Concat { left: Rc<Rope>,
             right: Rc<Rope>,
             graphemes: usize },
}
impl Rope {
    /// Create a new rope leaf
    pub fn from_str(base: &str) -> Rope {
        let num_graphemes = count_grapheme_clusters(base);
        Rope::Leaf { base: Rc::new(String::from(base)),
                     start: 0,
                     end: base.len(),
                     graphemes: num_graphemes }
    }
    /// Gets the number of Unicode grapheme clusters in the children of this node
    pub fn num_graphemes(&self) -> usize {
        match *self {
            Rope::Leaf { graphemes, .. } => graphemes,
            Rope::Concat { graphemes, .. } => graphemes,
        }
    }
    /// Split a Rope after the nth grapheme
    pub fn split(&self, grapheme_index: usize) -> Option<(Rope, Rope)> {
        match *self {
            Rope::Leaf { ref base, start, end, .. } => {
                grapheme_byte_index(&base[start..end], grapheme_index)
                    .map(|byte_index| {
                        let left = Rope::Leaf { base: base.clone(),
                                                start: start,
                                                end: start+byte_index,
                                                graphemes: count_grapheme_clusters(&base[start..start+byte_index]) };
                        let right = Rope::Leaf { base: base.clone(),
                                                 start: start+byte_index,
                                                 end: end,
                                                 graphemes: count_grapheme_clusters(&base[start+byte_index..end]) };
                        (left, right)
                    })
            },
            Rope::Concat{ ref left, ref right, .. } => {
                // self is (left, right)
                if left.num_graphemes() >= grapheme_index {
                    // split left into (l1, l2), return (l1, concat(l2, right))
                    left.split(grapheme_index).map(|(l1, l2)| {
                        (l1, Rope::Concat { left: Rc::new(l2.clone()),
                                            right: right.clone(),
                                            graphemes: l2.num_graphemes() + right.num_graphemes() })
                    })
                } else {
                    // split right into (r1, r2), return (concat(left, r1), r2)
                    right.split(grapheme_index - left.num_graphemes()).map(|(r1, r2)| {
                        (Rope::Concat { left: left.clone(),
                                        right: Rc::new(r1.clone()),
                                        graphemes: left.num_graphemes() + r1.num_graphemes() },
                         r2)
                    })
                }
            }
        }
    }
    /// Collect the pieces of this Rope into a continuous String
    pub fn to_string(&self) -> String {
        let mut buf = String::with_capacity(self.num_graphemes());

        fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
            let mut v = vec![];
            match *root {
                Rope::Leaf { ref base, start, end, .. } => {
                    v.push( &base[start..end] );
                },
                Rope::Concat { ref left, ref right, .. } => {
                    v.push_all(&str_parts(&left));
                    v.push_all(&str_parts(&right));
                },
            }
            v
        }
        for part in str_parts(self).iter() {
            buf.push_str(part);
        }

        buf
    }
    /// Join two pieces into a Rope
    pub fn join(left: Rope, right: Rope) -> Rope {
        let graphemes = left.num_graphemes() + right.num_graphemes();
        Rope::Concat { left: Rc::new(left),
                       right: Rc::new(right),
                       graphemes: graphemes }
    }
    /// Insert a string into a Rope by splitting and joining nodes
    /// Returns a new Rope, leaving the original unchanged
    pub fn insert(&self, grapheme_index: usize, value: &str) -> Option<Rope> {
        self.split(grapheme_index).map(|(left, right)| {
            let left = Rope::join(left, Rope::from_str(value));
            Rope::join(left, right)
        })
    }
    /// Append a string to the Rope, returning a new instance and leaving the original unchanged
    pub fn append(&self, value: &str) -> Rope {
        Rope::join(self.clone(), Rope::from_str(value))
    }
    /// Remove a substring range from the Rope
    pub fn delete(&self, start_grapheme: usize, num_graphemes: usize) -> Option<Rope> {
        self.split(start_grapheme).map(|(head, middle)| {
            middle.split(num_graphemes).map(|(_, tail)| {
                Rope::join(head.clone(), tail.clone())
            })
        }).unwrap()
    }
    /// Return the balance ratio (left.num_graphemes() / right.num_graphemes()) for a given concat node
    /// If this node is a leaf, returns 1.0
    pub fn get_balance(&self) -> f32 {
        match *self {
            Rope::Leaf { .. } => 1.0,
            Rope::Concat { ref left, ref right, .. } => left.num_graphemes() as f32 / right.num_graphemes() as f32,
        }
    }
    /// Returns the nth grapheme as an Option<&str>, returns None if the index is out of bounds
    pub fn get_nth_grapheme<'a>(&'a self, index: usize) -> Option<&'a str> {
        if index >= self.num_graphemes() {
            None
        } else {
            match *self {
                Rope::Leaf { ref base, start, end, .. } => {
                    nth_grapheme_cluster(&base[start..end], index)
                }
                Rope::Concat { ref left, ref right, .. } => {
                    if index < left.num_graphemes() { left.get_nth_grapheme(index) }
                    else { right.get_nth_grapheme(index - left.num_graphemes()) }
                }
            }
        }
    }
    /// Returns a new Rope where all neighboring nodes shorter than min_graphemes are merged and any
    /// nodes greater than max_graphemes are split
    /// Panics if max_graphemes is equal to 0, or if min_graphmes is greater than max_graphemes
    pub fn fixup_lengths(&self, min_graphemes: usize, max_graphemes: usize) -> Rope {
        assert!(max_graphemes > 0);
        assert!(min_graphemes <= max_graphemes);

        if self.is_leaf() && self.num_graphemes() > max_graphemes {
            // split long leafs
            if let Some((left, right)) = self.split(self.num_graphemes() / 2) {
                return Rope::join(left.fixup_lengths(min_graphemes, max_graphemes),
                                  right.fixup_lengths(min_graphemes, max_graphemes));
            }
        } else if !self.is_leaf() {
            if let Rope::Concat { ref left, ref right, graphemes } = *self {
                if graphemes <= min_graphemes {
                    // merge short concats
                    let mut merged = String::with_capacity(graphemes);
                    merged.push_str(&left.to_string());
                    merged.push_str(&right.to_string());
                    let len = merged.len();
                    return Rope::Leaf { base: Rc::new(merged), start: 0, end: len, graphemes: graphemes };
                } else {
                    // recurse
                    return Rope::Concat { left: Rc::new(left.fixup_lengths(min_graphemes, max_graphemes)),
                                          right: Rc::new(right.fixup_lengths(min_graphemes, max_graphemes)),
                                          graphemes: graphemes };
                }
            }
        }

        // nothing to be done
        return self.clone();
    }
    /// Returns true if this node is a Leaf
    fn is_leaf(&self) -> bool {
        match *self {
            Rope::Leaf { .. } => true,
            _ => false,
        }
    }
    /// Returns an iterator over the graphemes of this Rope
    pub fn graphemes<'a>(&'a self) -> GraphemeIter<'a> {
        GraphemeIter { root: self, index: 0 }
    }
}
impl Clone for Rope {
    fn clone(&self) -> Rope {
        match *self {
            Rope::Leaf { ref base, start, end, graphemes } => Rope::Leaf { base: base.clone(),
                                                                           start: start,
                                                                           end: end,
                                                                           graphemes: graphemes },
            Rope::Concat { ref left, ref right, graphemes } => Rope::Concat { left: left.clone(),
                                                                              right: right.clone(),
                                                                              graphemes: graphemes },
        }
    }
}
impl std::ops::Index<usize> for Rope {
    type Output = str;

    fn index<'a>(&'a self, _index: usize) -> &'a str {
        self.get_nth_grapheme(_index).expect("rope index out of bounds")
    }
}
pub struct GraphemeIter<'a> {
    root: &'a Rope,
    index: usize,
}
impl <'a> std::iter::Iterator for GraphemeIter<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        let res = self.root.get_nth_grapheme(self.index);
        self.index += 1;
        res
    }
}

/// Count the number of unicode extended grapheme clusters in a string
/// This is O(n)
fn count_grapheme_clusters(s: &str) -> usize {
    UnicodeSegmentation::graphemes(s, true).collect::<Vec<&str>>().len()
}

/// Find the byte index of the nth grapheme cluster in a string
/// Returns None if the grapheme index is out of bounds
fn grapheme_byte_index(base: &str, nth_grapheme: usize) -> Option<usize> {
    UnicodeSegmentation::grapheme_indices(base, true)
        .nth(nth_grapheme).map(|(i, _)| i)
}

/// Find the nth grapheme in a string
/// Returns None if the index is out of bounds
fn nth_grapheme_cluster(base: &str, nth_grapheme: usize) -> Option<&str> {
    UnicodeSegmentation::graphemes(base, true)
        .nth(nth_grapheme)
}

#[cfg(test)]
fn to_string_debug(root: &Rope) -> String {
    let mut buf = String::with_capacity(root.num_graphemes());

    fn str_parts<'a>(root: &'a Rope) -> Vec<&'a str> {
        let mut v = vec![];
        match *root {
            Rope::Leaf { ref base, start, end, .. } => {
                v.push( "<" );
                v.push( &base[start..end] );
                v.push( ">" );
            },
            Rope::Concat { ref left, ref right, .. } => {
                v.push( "(" );
                v.push_all(&str_parts(&left));
                v.push( ", " );
                v.push_all(&str_parts(&right));
                v.push( ")" );
            },
        }
        v
    }

    for part in str_parts(root).iter() {
        buf.push_str(part);
    }

    buf
}

#[test]
fn test_count_grapheme_clusters() {
    // 11 bytes, 3 grapheme clusters
    let s = "a̐éö̲";
    assert_eq!(s.len(), 11);
    assert_eq!(count_grapheme_clusters(s), 3);
}

#[test]
fn test_create_leaf() {
    let leaf = Rope::from_str("a̐éö̲");
    assert_eq!(leaf.num_graphemes(), 3);
}

#[test]
fn test_split_leaf() {
    let leaf = Rope::from_str("a̐éö̲a̐éö̲");
    let (left, right) = leaf.split(3).unwrap();
    assert_eq!(left.num_graphemes(), right.num_graphemes());
    assert_eq!(left.to_string(), "a̐éö̲");
}

#[test]
fn test_create_rope() {
    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.");
    assert_eq!(rope.num_graphemes(), 44);
    assert_eq!(rope.to_string(), "The quick brown fox jumps over the lazy dog.");
}

#[test]
fn test_fixup_lengths() {
    fn find_max_leaf(root: &Rope) -> usize {
        let len = root.num_graphemes();
        if let Rope::Concat { ref left, ref right, .. } = *root {
            std::cmp::max( find_max_leaf(&*left), find_max_leaf(&*right) )
        } else {
            len
        }
    }

    let rope = Rope::from_str("The quick brown fox jumps over the lazy dog.")
        .fixup_lengths(2, 4);
    assert_eq!(rope.num_graphemes(), 44);
    assert!(find_max_leaf(&rope) <= 4);
}

#[test]
fn test_index() {
    let leaf = Rope::from_str("a̐éö̲a̐éö̲,a̐éö̲a̐éö̲ foo bar baz aéö").fixup_lengths(2, 4);
    assert_eq!(leaf.get_nth_grapheme(2).unwrap(), "ö̲");
    assert_eq!(&leaf[2], "ö̲");
}

#[test]
fn test_iter() {
    let leaf = Rope::from_str("a̐éö̲a̐éö̲,a̐éö̲a̐éö̲ foo bar baz aéö").fixup_lengths(2, 4);
    let x: String = leaf.graphemes().collect();
    assert_eq!(leaf.to_string(), x);
}

#[test]
fn test_join() {
    let left = Rope::from_str("foo");
    let right = Rope::from_str("bar");
    assert_eq!("foobar", Rope::join(left, right).to_string());
}

#[test]
fn test_delete() {
    let rope = Rope::from_str("fooa̐éö̲bar").delete(3, 3).unwrap();
    assert_eq!("foobar", rope.to_string());
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate quick_error;
extern crate sdl2;
extern crate stopwatch;
extern crate blip_buf;

pub mod cart;
pub mod memory;
pub mod mappers;
pub mod ppu;
pub mod apu;
pub mod io;
pub mod cpu;
pub mod screen;
pub mod audio;

mod util;

#[cfg(feature="cputrace")]
pub mod disasm;

use cart::Cart;
use cpu::CPU;
use memory::CpuMemory;
use apu::APU;
use ppu::PPU;
use io::IO;
use sdl2::EventPump;
use sdl2::event::Event;

use std::rc::Rc;
use std::cell::RefCell;

use stopwatch::Stopwatch;

fn pump_events(pump: &Rc<RefCell<EventPump>>) -> bool {
    for event in pump.borrow_mut().poll_iter() {
        match event {
            Event::Quit {..} => return true,
            _ => (),
        }
    }
    false
}

fn run_frame(cpu: &mut CPU, io: &Rc<RefCell<IO>>, ppu: &Rc<RefCell<PPU>>) {
    io.borrow_mut().poll();
    loop {
        let cycle = cpu.cycle();
        let nmi = ppu.borrow_mut().run_to(cycle);
        let frame_end = nmi == ::ppu::StepResult::NMI;
        if frame_end {
            cpu.nmi();
        }
        cpu.step();
        if frame_end {
            break;
        }
    }
}

pub fn start_emulator(cart: Cart) {
    let sdl = sdl2::init().unwrap();
    let screen = screen::sdl::SDLScreen::new(&sdl);
    let audio_out = audio::sdl::SDLAudioOut::new(&sdl);
    let event_pump = Rc::new(RefCell::new(sdl.event_pump().unwrap()));

    let cart: Rc<RefCell<Cart>> = Rc::new(RefCell::new(cart));
    let ppu = PPU::new(cart.clone(), Box::new(screen));
    let ppu = Rc::new(RefCell::new(ppu));
    let apu = APU::new(Box::new(audio_out));
    let io: Rc<RefCell<IO>> = Rc::new(RefCell::new(io::sdl::SdlIO::new(event_pump.clone())));
    let mem = CpuMemory::new(ppu.clone(), apu, io.clone(), cart);
    let mut cpu = CPU::new(mem);
    cpu.init();

    let mut stopwatch = Stopwatch::start_new();
    let smoothing = 0.9;
    let mut avg_frame_time = 0.0f64;
    loop {
        if pump_events(&event_pump) || cpu.halted() {
            break;
        }
        run_frame(&mut cpu, &io, &ppu);
        let current = stopwatch.elapsed().num_nanoseconds().unwrap() as f64;
        avg_frame_time = (avg_frame_time * smoothing) + (current * (1.0 - smoothing));
        println!("Frames per second:{:.*}", 2, 1000000000.0 / avg_frame_time);
        stopwatch.restart();
    }
}
<commit_msg>Fixed controls.<commit_after>#[macro_use]
extern crate bitflags;

#[macro_use]
extern crate quick_error;
extern crate sdl2;
extern crate stopwatch;
extern crate blip_buf;

pub mod cart;
pub mod memory;
pub mod mappers;
pub mod ppu;
pub mod apu;
pub mod io;
pub mod cpu;
pub mod screen;
pub mod audio;

mod util;

#[cfg(feature="cputrace")]
pub mod disasm;

use cart::Cart;
use cpu::CPU;
use memory::CpuMemory;
use apu::APU;
use ppu::PPU;
use io::IO;
use sdl2::EventPump;
use sdl2::event::Event;

use std::rc::Rc;
use std::cell::RefCell;

use stopwatch::Stopwatch;

fn pump_events(pump: &Rc<RefCell<EventPump>>) -> bool {
    for event in pump.borrow_mut().poll_iter() {
        match event {
            Event::Quit {..} => return true,
            _ => (),
        }
    }
    false
}

fn run_frame(cpu: &mut CPU, io: &Rc<RefCell<IO>>, ppu: &Rc<RefCell<PPU>>) {
    loop {
        io.borrow_mut().poll();
        let cycle = cpu.cycle();
        let nmi = ppu.borrow_mut().run_to(cycle);
        let frame_end = nmi == ::ppu::StepResult::NMI;
        if frame_end {
            cpu.nmi();
        }
        cpu.step();
        if frame_end {
            break;
        }
    }
}

pub fn start_emulator(cart: Cart) {
    let sdl = sdl2::init().unwrap();
    let screen = screen::sdl::SDLScreen::new(&sdl);
    let audio_out = audio::sdl::SDLAudioOut::new(&sdl);
    let event_pump = Rc::new(RefCell::new(sdl.event_pump().unwrap()));

    let cart: Rc<RefCell<Cart>> = Rc::new(RefCell::new(cart));
    let ppu = PPU::new(cart.clone(), Box::new(screen));
    let ppu = Rc::new(RefCell::new(ppu));
    let apu = APU::new(Box::new(audio_out));
    let io: Rc<RefCell<IO>> = Rc::new(RefCell::new(io::sdl::SdlIO::new(event_pump.clone())));
    let mem = CpuMemory::new(ppu.clone(), apu, io.clone(), cart);
    let mut cpu = CPU::new(mem);
    cpu.init();

    let mut stopwatch = Stopwatch::start_new();
    let smoothing = 0.9;
    let mut avg_frame_time = 0.0f64;
    loop {
        if pump_events(&event_pump) || cpu.halted() {
            break;
        }
        run_frame(&mut cpu, &io, &ppu);
        let current = stopwatch.elapsed().num_nanoseconds().unwrap() as f64;
        avg_frame_time = (avg_frame_time * smoothing) + (current * (1.0 - smoothing));
        println!("Frames per second:{:.*}", 2, 1000000000.0 / avg_frame_time);
        stopwatch.restart();
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

#[macro_use]
extern crate log;
extern crate fern;
extern crate time;
extern crate libc;
extern crate rand;
extern crate simple_stream;
extern crate num_cpus;
extern crate epoll;
extern crate rustc_serialize;

use std::sync::Mutex;
use std::net::ToSocketAddrs;

use types::*;

mod epollloop;
mod resources;
mod socket;
mod stats;
mod types;
mod workerthread;

/// Starts the server binding to the passed address.
/// This is a blocking call for the life of the server.
pub fn begin<T, K>(address: T, handler: Box<K>) where
    T: ToSocketAddrs + Send + 'static,
    K: EventHandler + Send + Sync + 'static {

    // Logger
    initialize_logger();

    // Data collection
    let mut data = Mutex::new(stats::GeneralData::new());
    stats::init(&mut data);

    // Begin server
    epollloop::begin(address, handler);
}

/// Initializes the global logger
fn initialize_logger() {
    let _ = fern::init_global_logger(fern::DispatchConfig {
        format: Box::new(|msg: &str, level: &log::LogLevel, _location: &log::LogLocation| {
            format!("[{}][{}] {}", time::now().strftime("%Y-%m-%d][%H:%M:%S").unwrap(), level, msg)
        }),
        output: vec![fern::OutputConfig::stdout(), fern::OutputConfig::file("/var/log/hydrogen.log")],
        level: log::LogLevelFilter::Trace,
    }, log::LogLevelFilter::Trace);
    info!("Logger initialized. \nLog file: /var/log/hydrogen.log");
}
<commit_msg>Types module is now public<commit_after>// Copyright 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
//
// This Source Code Form is subject to the terms of the
// Mozilla Public License, v. 2.0. If a copy of the MPL was not
// distributed with this file, You can obtain one at
// http://mozilla.org/MPL/2.0/.

#[macro_use]
extern crate log;
extern crate fern;
extern crate time;
extern crate libc;
extern crate rand;
extern crate simple_stream;
extern crate num_cpus;
extern crate epoll;
extern crate rustc_serialize;

use std::sync::Mutex;
use std::net::ToSocketAddrs;

use types::*;

pub mod types;
pub mod socket;

mod stats;
mod epollloop;
mod resources;
mod workerthread;

/// Starts the server binding to the passed address.
/// This is a blocking call for the life of the server.
pub fn begin<T, K>(address: T, handler: Box<K>) where
    T: ToSocketAddrs + Send + 'static,
    K: EventHandler + Send + Sync + 'static {

    // Logger
    initialize_logger();

    // Data collection
    let mut data = Mutex::new(stats::GeneralData::new());
    stats::init(&mut data);

    // Begin server
    epollloop::begin(address, handler);
}

/// Initializes the global logger
fn initialize_logger() {
    let _ = fern::init_global_logger(fern::DispatchConfig {
        format: Box::new(|msg: &str, level: &log::LogLevel, _location: &log::LogLocation| {
            format!("[{}][{}] {}", time::now().strftime("%Y-%m-%d][%H:%M:%S").unwrap(), level, msg)
        }),
        output: vec![fern::OutputConfig::stdout(), fern::OutputConfig::file("/var/log/hydrogen.log")],
        level: log::LogLevelFilter::Trace,
    }, log::LogLevelFilter::Trace);
    info!("Logger initialized. \nLog file: /var/log/hydrogen.log");
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate ndarray;

use std::f64;

use ndarray::{
    OwnedArray,
    Ix,
};

pub type V = OwnedArray<f64, Ix>;

pub struct OnlineStats {
    sum_of_weights : f64,
    mean : V,
    m2 : V,
    n : u64
}

impl OnlineStats {
    pub fn new(width: usize) -> OnlineStats {
        OnlineStats {
            sum_of_weights: 0.,
            mean: V::zeros(width),
            m2:   V::zeros(width),
            n: 0 }
    }

    pub fn next_value(&mut self, data : &V, weight : f64) {
        let temp = weight + self.sum_of_weights;
        // nice
        let delta = data - &self.mean;
        let r = &delta * (weight / temp); // Interoperation with scalars works nicely.

        self.mean.iadd(&r); // While I don't like this style, is efficient and will be += when rust supports it so fine.

        self.m2.iadd(&(self.sum_of_weights * (r * &delta)));
        self.sum_of_weights = temp;
        self.n += 1;
    }

    pub fn mean_and_variance(&self) -> (V, V) {
        //let var = if self.n > 1 {self.M2 / self.sumOfWeights * self.n / (self.n - 1) } else {Float::inf};
        let var = if self.n > 1 {
            &self.m2 * ((self.n as f64) / (self.sum_of_weights * ((self.n - 1) as f64)))
        } else {
            V::from_elem(self.m2.dim(), f64::INFINITY)
        };
        (self.mean.clone(), var)
    }
}

use ndarray::arr1;

#[test]
fn weighted_stats17(){
    let const_vec = arr1(&[1., 3., 4.]);
    let const_vec2 = arr1(&[1., 1.5, 1.]);
    let const_vec3 = arr1(&[0., 2., 4.]);
    let mut s = OnlineStats::new(3);
    s.next_value(&const_vec, 1.);
    let (m1, _) = s.mean_and_variance();
    assert_eq!(m1, const_vec);
    s.next_value(&const_vec2, 2.);
    let (m2, _) = s.mean_and_variance();
    assert_eq!(m2, arr1(&[1., 2., 2.]));
    s.next_value(&const_vec3, 3.);
    let (m3, _) = s.mean_and_variance();
    assert_eq!(m3, arr1(&[0.5, 2., 3.]));
}
<commit_msg>Remove self-addressed comments.<commit_after>#[macro_use]
extern crate ndarray;

use std::f64;

use ndarray::{
    OwnedArray,
    Ix,
};

pub type V = OwnedArray<f64, Ix>;

pub struct OnlineStats {
    sum_of_weights : f64,
    mean : V,
    m2 : V,
    n : u64
}

impl OnlineStats {
    pub fn new(width: usize) -> OnlineStats {
        OnlineStats {
            sum_of_weights: 0.,
            mean: V::zeros(width),
            m2:   V::zeros(width),
            n: 0 }
    }

    pub fn next_value(&mut self, data : &V, weight : f64) {
        let temp = weight + self.sum_of_weights;
        // nice
        let delta = data - &self.mean;
        let r = &delta * (weight / temp);

        self.mean.iadd(&r);

        self.m2.iadd(&(self.sum_of_weights * (r * &delta)));
        self.sum_of_weights = temp;
        self.n += 1;
    }

    pub fn mean_and_variance(&self) -> (V, V) {
        //let var = if self.n > 1 {self.M2 / self.sumOfWeights * self.n / (self.n - 1) } else {Float::inf};
        let var = if self.n > 1 {
            &self.m2 * ((self.n as f64) / (self.sum_of_weights * ((self.n - 1) as f64)))
        } else {
            V::from_elem(self.m2.dim(), f64::INFINITY)
        };
        (self.mean.clone(), var)
    }
}

use ndarray::arr1;

#[test]
fn weighted_stats17(){
    let const_vec = arr1(&[1., 3., 4.]);
    let const_vec2 = arr1(&[1., 1.5, 1.]);
    let const_vec3 = arr1(&[0., 2., 4.]);
    let mut s = OnlineStats::new(3);
    s.next_value(&const_vec, 1.);
    let (m1, _) = s.mean_and_variance();
    assert_eq!(m1, const_vec);
    s.next_value(&const_vec2, 2.);
    let (m2, _) = s.mean_and_variance();
    assert_eq!(m2, arr1(&[1., 2., 2.]));
    s.next_value(&const_vec3, 3.);
    let (m3, _) = s.mean_and_variance();
    assert_eq!(m3, arr1(&[0.5, 2., 3.]));
}
<|endoftext|>


<commit_before>extern crate libc;

use std::ffi::{OsStr, OsString};
use std::fmt::Debug;
use std::fs::File;
use std::io;
use std::os::unix::io::{FromRawFd, IntoRawFd};
use std::path::{Path, PathBuf};
use std::process::{Command, ExitStatus};

pub trait Expression: Clone + Debug {
    fn run(&self) -> Result;
}

#[derive(Debug, Clone)]
pub struct ArgvCommand {
    argv: Vec<OsString>,
    stdout: Option<PathBuf>,
}

impl ArgvCommand {
    pub fn new<T: AsRef<OsStr>>(prog: T) -> ArgvCommand {
        ArgvCommand{
            argv: vec![prog.as_ref().to_owned()],
            stdout: None,
        }
    }

    pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut Self {
        self.argv.push(arg.as_ref().to_owned());
        self
    }

    pub fn stdout<T: AsRef<Path>>(&mut self, path: T) -> &mut Self {
        self.stdout = Some(path.as_ref().to_owned());
        self
    }
}

impl Expression for ArgvCommand {
    fn run(&self) -> Result {
        // Create a Command and add the args.
        let mut command = Command::new(&self.argv[0]);
        command.args(&self.argv[1..]);
        if let Some(ref path) = self.stdout {
            let file = try!(File::create(path));
            command.stdout(unsafe {
                FromRawFd::from_raw_fd(file.into_raw_fd())
            });
        }
        let exit_status = try!(command.status());
        Ok(CommandOutput{
            stdout: None,
            stderr: None,
            status: exit_status,
        })
    }
}

#[derive(Debug, Clone)]
pub struct Pipe {
    // TODO: Make this hold any Expression.
    left: ArgvCommand,
    right: ArgvCommand,
}

impl Pipe {
    pub fn new(left: &ArgvCommand, right: &ArgvCommand) -> Pipe {
        Pipe{left: left.clone(), right: right.clone()}
    }
}

impl Expression for Pipe {
    fn run(&self) -> Result {
        let mut pipes: [libc::c_int; 2] = [-1; 2];
        let error = unsafe { libc::pipe(pipes.as_mut_ptr()) };
        assert_eq!(error, 0);
        println!("pipes: {:?}", pipes);
        Err(Error::Io(std::io::Error::new(std::io::ErrorKind::Other, "foo")))
    }
}

pub type Result = std::result::Result<CommandOutput, Error>;

#[derive(Debug, Clone)]
pub struct CommandOutput {
    pub stdout: Option<Vec<u8>>,
    pub stderr: Option<Vec<u8>>,
    pub status: ExitStatus,
}

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Status(CommandOutput),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

#[cfg(test)]
mod test {
    use super::{ArgvCommand, Pipe, Expression};
    use std::fs::File;
    use std::io::prelude::*;

    #[test]
    fn test_run() {
        let result = ArgvCommand::new("true").arg("foo").arg("bar").run();
        assert!(result.unwrap().status.success());
    }

    #[test]
    fn test_stdout() {
        let path = "/tmp/cargo_test_file";
        let result = ArgvCommand::new("echo").arg("hi").stdout(path).run();
        assert!(result.unwrap().status.success());
        let mut contents = String::new();
        File::open(path).unwrap().read_to_string(&mut contents).unwrap();
        assert_eq!(contents, "hi\n");
    }

    #[test]
    fn test_pipe() {
        let mut left = ArgvCommand::new("echo");
        left.arg("hi");
        let mut right = ArgvCommand::new("sed");
        right.arg("s/i/o/");
        let pipe = Pipe::new(&left, &right);
    }
}
<commit_msg>a basic pipe working<commit_after>extern crate libc;

use std::ffi::{OsStr, OsString};
use std::fmt::Debug;
use std::fs::File;
use std::io;
use std::mem;
use std::os::unix::io::{FromRawFd, IntoRawFd, RawFd};
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio, Output};

pub trait Expression: Clone + Debug {
    fn exec(&self, context: IoContext) -> Result;

    fn run(&self) -> Result {
        let context = IoContext {
            stdin: CloneableStdio::Inherit,
            stdout: CloneableStdio::Inherit,
            stderr: CloneableStdio::Inherit,
        };
        self.exec(context)
    }
}

#[derive(Debug, Clone)]
pub struct ArgvCommand {
    argv: Vec<OsString>,
    stdout: Option<PathBuf>,
}

impl ArgvCommand {
    pub fn new<T: AsRef<OsStr>>(prog: T) -> ArgvCommand {
        ArgvCommand{
            argv: vec![prog.as_ref().to_owned()],
            stdout: None,
        }
    }

    pub fn arg<T: AsRef<OsStr>>(&mut self, arg: T) -> &mut Self {
        self.argv.push(arg.as_ref().to_owned());
        self
    }

    pub fn stdout<T: AsRef<Path>>(&mut self, path: T) -> &mut Self {
        self.stdout = Some(path.as_ref().to_owned());
        self
    }
}

impl Expression for ArgvCommand {
    fn exec(&self, context: IoContext) -> Result {
        let IoContext{stdin, stdout, stderr} = context;
        // Create a Command and add the args.
        let mut command = Command::new(&self.argv[0]);
        command.args(&self.argv[1..]);
        command.stdin(stdin.to_stdio());
        command.stdout(stdout.to_stdio());
        command.stderr(stderr.to_stdio());
        if let Some(ref path) = self.stdout {
            let file = try!(File::create(path));
            command.stdout(unsafe {
                FromRawFd::from_raw_fd(file.into_raw_fd())
            });
        }
        let exit_status = try!(command.status());
        Ok(Output{
            stdout: Vec::new(),
            stderr: Vec::new(),
            status: exit_status,
        })
    }
}

#[derive(Debug, Clone)]
pub struct Pipe {
    // TODO: Make this hold any Expression.
    left: ArgvCommand,
    right: ArgvCommand,
}

impl Pipe {
    pub fn new(left: &ArgvCommand, right: &ArgvCommand) -> Pipe {
        Pipe{left: left.clone(), right: right.clone()}
    }
}

impl Expression for Pipe {
    fn exec(&self, context: IoContext) -> Result {
        let IoContext{stdin, stdout, stderr} = context;
        let (read_pipe, write_pipe) = open_pipe();
        let left_context = IoContext{
            stdin: stdin,
            stdout: CloneableStdio::Fd(write_pipe),
            stderr: stderr.clone(),
        };
        let right_context = IoContext{
            stdin: CloneableStdio::Fd(read_pipe),
            stdout: stdout,
            stderr: stderr,
        };
        let left_clone = self.left.clone();
        let left_thread = std::thread::spawn(move || {
            left_clone.exec(left_context)
        });
        let right_result = self.right.exec(right_context);
        let left_result = left_thread.join().unwrap();  // TODO: handle errors here?
        match right_result {
            Err(_) => right_result,
            _ => left_result,
        }
    }
}

pub type Result = std::result::Result<Output, Error>;

#[derive(Debug)]
pub enum Error {
    Io(io::Error),
    Status(Output),
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Io(err)
    }
}

#[derive(Clone, Debug)]
pub struct IoContext {
    stdin: CloneableStdio,
    stdout: CloneableStdio,
    stderr: CloneableStdio,
}

#[derive(Clone, Debug)]
enum CloneableStdio {
    Inherit,
    Fd(CloneableFd),
}

impl CloneableStdio {
    fn to_stdio(self) -> Stdio {
        match self {
            CloneableStdio::Inherit => Stdio::inherit(),
            CloneableStdio::Fd(fd) => unsafe {
                FromRawFd::from_raw_fd(fd.into_raw_fd())
            },
        }
    }
}

#[derive(Debug)]
struct CloneableFd {
    // The struct *owns* this file descriptor, and will close it in drop().
    fd: RawFd,
}

impl Clone for CloneableFd {
    fn clone(&self) -> Self {
        let new_fd = unsafe { libc::dup(self.fd) };
        assert!(new_fd >= 0);
        unsafe { FromRawFd::from_raw_fd(new_fd) }
    }
}

impl FromRawFd for CloneableFd {
    unsafe fn from_raw_fd(fd: RawFd) -> Self {
        CloneableFd{fd: fd}
    }
}

impl IntoRawFd for CloneableFd {
    fn into_raw_fd(self) -> RawFd {
        let fd = self.fd;
        mem::forget(self);  // prevent drop() from closing the fd
        fd
    }
}

impl Drop for CloneableFd {
    fn drop(&mut self) {
        let error = unsafe { libc::close(self.fd) };
        assert_eq!(error, 0);
    }
}

// (read, write)
// TODO: error handling
fn open_pipe() -> (CloneableFd, CloneableFd) {
    unsafe {
        let mut pipes = [0, 0];
        let error = libc::pipe(pipes.as_mut_ptr());
        assert_eq!(error, 0);
        // prevent child processes from inheriting these by default
        for fd in &pipes {
            let ret = libc::ioctl(*fd, libc::FIOCLEX);
            assert_eq!(ret, 0);
        }
        (FromRawFd::from_raw_fd(pipes[0]), FromRawFd::from_raw_fd(pipes[1]))
    }
}

#[cfg(test)]
mod test {
    use super::{ArgvCommand, Pipe, Expression};
    use std::fs::File;
    use std::io::prelude::*;
    use std::path::PathBuf;
    use std::process::Command;
    use std::str::from_utf8;

    fn mktemp() -> PathBuf {
        // TODO: use duct for this :)
        let output = Command::new("mktemp").output().unwrap();
        let path: PathBuf = from_utf8(&output.stdout).unwrap().trim().into();
        println!("here's the path we're using: {:?}", path);
        path
    }

    #[test]
    fn test_run() {
        let result = ArgvCommand::new("true").arg("foo").arg("bar").run();
        assert!(result.unwrap().status.success());
    }

    #[test]
    fn test_stdout() {
        let path = mktemp();
        let result = ArgvCommand::new("echo").arg("hi").stdout(&path).run();
        assert!(result.unwrap().status.success());
        let mut contents = String::new();
        File::open(&path).unwrap().read_to_string(&mut contents).unwrap();
        assert_eq!(contents, "hi\n");
    }

    #[test]
    fn test_pipe() {
        let mut left = ArgvCommand::new("echo");
        left.arg("hi");
        let mut right = ArgvCommand::new("sed");
        right.arg("s/i/o/");
        let path = mktemp();
        right.stdout(&path);
        let pipe = Pipe::new(&left, &right);
        let result = pipe.run();
        assert!(result.unwrap().status.success());
        let mut contents = String::new();
        File::open(&path).unwrap().read_to_string(&mut contents).unwrap();
        assert_eq!(contents, "ho\n");
    }
}
<|endoftext|>


<commit_before>#![warn(missing_docs)]
//! The Spotify crate.
//!
//! This crate contains methods to retrieve information from
//! and manipulate the local Spotify client instance.

// Extern crates
extern crate winapi;
extern crate kernel32;
extern crate reqwest;
extern crate time;
extern crate json;

// Modules
#[cfg(windows)]
mod windows_process;
mod connector;
mod status;

// Imports
#[cfg(windows)]
use windows_process::WindowsProcess;
use connector::{SpotifyConnector, InternalSpotifyError};
use status::SpotifyStatus;
use json::JsonValue;

/// The `Result` type used in this crate.
type Result<T> = std::result::Result<T, SpotifyError>;

/// The `SpotifyError` enum.
#[derive(Debug)]
pub enum SpotifyError {
    /// An internal error.
    InternalError(InternalSpotifyError),
    /// Indicates that the Spotify Client is not running.
    ClientNotRunning,
    /// Indicates that the SpotifyWebHelper process it not running.
    WebHelperNotRunning,
}

/// The Spotify API.
#[allow(dead_code)]
pub struct Spotify {
    /// The Spotify connector.
    connector: SpotifyConnector,
}

/// Implements `Spotify`.
impl Spotify {
    /// Constructs a new `Spotify`.
    ///
    /// Does additional checks to verify that Spotify
    /// and SpotifyWebHelper are running.
    #[cfg(windows)]
    pub fn new() -> Result<Spotify> {
        if !Spotify::spotify_alive() {
            return Err(SpotifyError::ClientNotRunning);
        }
        if !Spotify::spotify_webhelper_alive() {
            return Err(SpotifyError::WebHelperNotRunning);
        }
        Spotify::new_unchecked()
    }
    /// Constructs a new `Spotify`.
    #[cfg(not(windows))]
    pub fn new() -> Result<Spotify> {
        Spotify::new_unchecked()
    }
    /// Constructs a new `Spotify`.
    ///
    /// Skips the checks done in `Spotify::new`.
    fn new_unchecked() -> Result<Spotify> {
        match SpotifyConnector::connect_new() {
            Ok(result) => Ok(Spotify { connector: result }),
            Err(error) => Err(SpotifyError::InternalError(error)),
        }
    }
    /// Fetches the current status from Spotify.
    pub fn get_status(&self) -> Result<SpotifyStatus> {
        let json = match self.get_status_object() {
            Ok(result) => result,
            Err(error) => return Err(error),
        };
        Ok(SpotifyStatus::from(json))
    }
    /// Fetches the current status from Spotify.
    fn get_status_object(&self) -> Result<JsonValue> {
        match self.connector.fetch_status_json() {
            Ok(result) => Ok(result),
            Err(error) => Err(SpotifyError::InternalError(error)),
        }
    }
    /// Tests whether the Spotify process is running.
    #[cfg(windows)]
    fn spotify_alive() -> bool {
        let process = "Spotify.exe";
        WindowsProcess::find_by_name(process).is_some()
    }
    /// Tests whether the SpotifyWebHelper process is running.
    #[cfg(windows)]
    fn spotify_webhelper_alive() -> bool {
        let process = "SpotifyWebHelper.exe";
        WindowsProcess::find_by_name(process).is_some()
    }
}<commit_msg>Make status module public<commit_after>#![warn(missing_docs)]
//! The Spotify crate.
//!
//! This crate contains methods to retrieve information from
//! and manipulate the local Spotify client instance.

// Extern crates
extern crate winapi;
extern crate kernel32;
extern crate reqwest;
extern crate time;
extern crate json;

// Modules
#[cfg(windows)]
mod windows_process;
mod connector;
pub mod status;

// Imports
#[cfg(windows)]
use windows_process::WindowsProcess;
use connector::{SpotifyConnector, InternalSpotifyError};
use status::SpotifyStatus;
use json::JsonValue;

/// The `Result` type used in this crate.
type Result<T> = std::result::Result<T, SpotifyError>;

/// The `SpotifyError` enum.
#[derive(Debug)]
pub enum SpotifyError {
    /// An internal error.
    InternalError(InternalSpotifyError),
    /// Indicates that the Spotify Client is not running.
    ClientNotRunning,
    /// Indicates that the SpotifyWebHelper process it not running.
    WebHelperNotRunning,
}

/// The Spotify API.
#[allow(dead_code)]
pub struct Spotify {
    /// The Spotify connector.
    connector: SpotifyConnector,
}

/// Implements `Spotify`.
impl Spotify {
    /// Constructs a new `Spotify`.
    ///
    /// Does additional checks to verify that Spotify
    /// and SpotifyWebHelper are running.
    #[cfg(windows)]
    pub fn new() -> Result<Spotify> {
        if !Spotify::spotify_alive() {
            return Err(SpotifyError::ClientNotRunning);
        }
        if !Spotify::spotify_webhelper_alive() {
            return Err(SpotifyError::WebHelperNotRunning);
        }
        Spotify::new_unchecked()
    }
    /// Constructs a new `Spotify`.
    #[cfg(not(windows))]
    pub fn new() -> Result<Spotify> {
        Spotify::new_unchecked()
    }
    /// Constructs a new `Spotify`.
    ///
    /// Skips the checks done in `Spotify::new`.
    fn new_unchecked() -> Result<Spotify> {
        match SpotifyConnector::connect_new() {
            Ok(result) => Ok(Spotify { connector: result }),
            Err(error) => Err(SpotifyError::InternalError(error)),
        }
    }
    /// Fetches the current status from Spotify.
    pub fn get_status(&self) -> Result<SpotifyStatus> {
        let json = match self.get_status_object() {
            Ok(result) => result,
            Err(error) => return Err(error),
        };
        Ok(SpotifyStatus::from(json))
    }
    /// Fetches the current status from Spotify.
    fn get_status_object(&self) -> Result<JsonValue> {
        match self.connector.fetch_status_json() {
            Ok(result) => Ok(result),
            Err(error) => Err(SpotifyError::InternalError(error)),
        }
    }
    /// Tests whether the Spotify process is running.
    #[cfg(windows)]
    fn spotify_alive() -> bool {
        let process = "Spotify.exe";
        WindowsProcess::find_by_name(process).is_some()
    }
    /// Tests whether the SpotifyWebHelper process is running.
    #[cfg(windows)]
    fn spotify_webhelper_alive() -> bool {
        let process = "SpotifyWebHelper.exe";
        WindowsProcess::find_by_name(process).is_some()
    }
}<|endoftext|>


<commit_before>#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum Param {
    Short(char),
    Long(String),
}

pub trait IntoParam {
    fn into_param(self) -> Param;
}

impl IntoParam for &'static str {
    fn into_param(self) -> Param {
        Param::Long(self.to_owned())
    }
}

impl IntoParam for char {
    fn into_param(self) -> Param {
        Param::Short(self)
    }
}

use std::collections::HashMap;

/// Our homebrewed Arg Parser
///
/// Yes, it would be nice to use an Arg Parser library but we don't have that
/// kind of luxury with our current std crate implementation for Redox
#[derive(Clone, Debug, Default)]
pub struct ArgParser {
    flags: HashMap<Param, bool>,
    opts:  HashMap<Param, Option<String>>,
    pub args: Vec<String>,
}

impl ArgParser {
    /// Create a new ArgParser object
    pub fn new(flag_cap: usize, opt_cap: usize) -> Self {
        ArgParser {
            flags: HashMap::with_capacity(flag_cap),
            opts: HashMap::with_capacity(opt_cap),
            args: Vec::new(),
        }
    }

    /// Builder method for adding both short and long flags
    pub fn add_flag(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.flags.insert(Param::Short(short), false);
        }
        if !long.is_empty() {
            self.flags.insert(Param::Long(long.to_owned()), false);
        }
        self
    }

    /// Builder method for adding both short and long opts
    pub fn add_opt(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.opts.insert(Param::Short(short), None);
        }
        if !long.is_empty() {
            self.opts.insert(Param::Long(long.to_owned()), None);
        }
        self
    }

    /// Check if a flag has been used
    pub fn enabled_flag<F: IntoParam>(&self, flag: F) -> bool {
        *self.flags.get(&flag.into_param()).unwrap_or(&false)
    }

    /// Start parsing user inputted args for which flags are used
    pub fn initialize<A: Iterator<Item=String>>(&mut self, args: A) {
        let mut args = args.skip(1);
        while let Some(mut arg) = args.next() {
            if arg.starts_with("--") {
                // Remove both dashes
                arg.remove(0);
                arg.remove(0);
                if let Some(i) = arg.find('=') {
                    let (lhs, rhs) = arg.split_at(i);
                    if let Some(opt) = self.opts.get_mut(&Param::Long(lhs.to_owned())) {
                        *opt = Some(rhs.to_owned());
                    }
                }
                else {
                    if let Some(flag) = self.flags.get_mut(&Param::Long(arg)) {
                        *flag = true;
                    }
                }
            }
            else if arg.starts_with("-") {
                for ch in arg[1..].chars() {
                    if let Some(switch) = self.flags.get_mut(&Param::Short(ch)) {
                        *switch = true;
                    }
                    if let Some(value) = self.opts.get_mut(&Param::Short(ch)) {
                        *value = args.next();
                    }
                }
            }
            else {
                self.args.push(arg);
            }
        }
    }

    pub fn set_flag<F: IntoParam>(&mut self, flag: F, state: bool) {
        if let Some(switch) = self.flags.get_mut(&flag.into_param()) {
            *switch = state;
        }
    }
}

pub fn to_human_readable_string(size: u64) -> String {
    if size < 1024 {
        return format!("{}", size);
    }

    static UNITS: [&'static str; 7] = ["", "K", "M", "G", "T", "P", "E"];

    let sizef = size as f64;
    let digit_groups = (sizef.log10() / 1024f64.log10()) as i32;
    format!("{:.1}{}",
            sizef / 1024f64.powf(digit_groups as f64),
            UNITS[digit_groups as usize])
}
<commit_msg>Add `ArgParser::{set_opt(), has_opt()}` methods<commit_after>#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub enum Param {
    Short(char),
    Long(String),
}

pub trait IntoParam {
    fn into_param(self) -> Param;
}

impl IntoParam for &'static str {
    fn into_param(self) -> Param {
        Param::Long(self.to_owned())
    }
}

impl IntoParam for char {
    fn into_param(self) -> Param {
        Param::Short(self)
    }
}

use std::collections::HashMap;

/// Our homebrewed Arg Parser
///
/// Yes, it would be nice to use an Arg Parser library but we don't have that
/// kind of luxury with our current std crate implementation for Redox
#[derive(Clone, Debug, Default)]
pub struct ArgParser {
    flags: HashMap<Param, bool>,
    opts:  HashMap<Param, Option<String>>,
    pub args: Vec<String>,
}

impl ArgParser {
    /// Create a new ArgParser object
    pub fn new(flag_cap: usize, opt_cap: usize) -> Self {
        ArgParser {
            flags: HashMap::with_capacity(flag_cap),
            opts: HashMap::with_capacity(opt_cap),
            args: Vec::new(),
        }
    }

    /// Builder method for adding both short and long flags
    pub fn add_flag(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.flags.insert(Param::Short(short), false);
        }
        if !long.is_empty() {
            self.flags.insert(Param::Long(long.to_owned()), false);
        }
        self
    }

    /// Builder method for adding both short and long opts
    pub fn add_opt(mut self, short: &str, long: &str) -> Self {
        if let Some(short) = short.chars().next() {
            self.opts.insert(Param::Short(short), None);
        }
        if !long.is_empty() {
            self.opts.insert(Param::Long(long.to_owned()), None);
        }
        self
    }

    /// Check if a flag has been used
    pub fn enabled_flag<F: IntoParam>(&self, flag: F) -> bool {
        *self.flags.get(&flag.into_param()).unwrap_or(&false)
    }

    /// Start parsing user inputted args for which flags are used
    pub fn initialize<A: Iterator<Item=String>>(&mut self, args: A) {
        let mut args = args.skip(1);
        while let Some(mut arg) = args.next() {
            if arg.starts_with("--") {
                // Remove both dashes
                arg.remove(0);
                arg.remove(0);
                if let Some(i) = arg.find('=') {
                    let (lhs, rhs) = arg.split_at(i);
                    if let Some(opt) = self.opts.get_mut(&Param::Long(lhs.to_owned())) {
                        *opt = Some(rhs.to_owned());
                    }
                }
                else {
                    if let Some(flag) = self.flags.get_mut(&Param::Long(arg)) {
                        *flag = true;
                    }
                }
            }
            else if arg.starts_with("-") {
                for ch in arg[1..].chars() {
                    if let Some(switch) = self.flags.get_mut(&Param::Short(ch)) {
                        *switch = true;
                    }
                    if let Some(value) = self.opts.get_mut(&Param::Short(ch)) {
                        *value = args.next();
                    }
                }
            }
            else {
                self.args.push(arg);
            }
        }
    }

    pub fn set_flag<F: IntoParam>(&mut self, flag: F, state: bool) {
        if let Some(switch) = self.flags.get_mut(&flag.into_param()) {
            *switch = state;
        }
    }

    pub fn set_opt<O: IntoParam>(&mut self, opt: O, state: Option<String>) {
        if let Some(value) = self.opts.get_mut(&opt.into_param()) {
            *value = state;
        }
    }

    pub fn has_opt<O: IntoParam>(&mut self, opt: O) -> bool {
        if let Some(&Some(_)) = self.opts.get(&opt.into_param()) {
            return true;
        }
        false
    }
}

pub fn to_human_readable_string(size: u64) -> String {
    if size < 1024 {
        return format!("{}", size);
    }

    static UNITS: [&'static str; 7] = ["", "K", "M", "G", "T", "P", "E"];

    let sizef = size as f64;
    let digit_groups = (sizef.log10() / 1024f64.log10()) as i32;
    format!("{:.1}{}",
            sizef / 1024f64.powf(digit_groups as f64),
            UNITS[digit_groups as usize])
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate take_mut;

use std::io;
use std::error::Error;
use std::marker::PhantomData;
use std::cell;

#[derive(Debug)]
pub enum DecodingError {
    Corrupt(String),
    IoError(io::Error),
}

fn decode<O: serde::de::DeserializeOwned, R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<O, DecodingError> {
    reader.seek(io::SeekFrom::Start(offset)).map_err(|x| DecodingError::IoError(x))?;
    bincode::deserialize_from(    reader, bincode::Infinite)
    .map_err(|x| {
        match *x {
            bincode::ErrorKind::IoError(y) => DecodingError::IoError(y),
            _ => DecodingError::Corrupt(x.description().to_string()),
        }
    })
}

#[derive(Debug)]
pub enum EncodingError {
    Unknown(String),
    IoError(io::Error),
}

fn encode<O: serde::Serialize, W: io::Write+io::Seek>(writer: &mut W, obj: &O) -> Result<u64, EncodingError> {
    let offset = writer.seek(io::SeekFrom::End(0)).map_err(|x| EncodingError::IoError(x))?;
    bincode::serialize_into(writer, obj, bincode::Infinite)
    .map_err(|x| {
        match *x {
            bincode::ErrorKind::IoError(y) => EncodingError::IoError(y),
            _ => EncodingError::Unknown(x.description().to_string()),
        }
    }).map(|_| offset)
}

#[derive(Serialize, Deserialize, Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
enum NodeType {
    Root,
    Internal,
    Leaf
}

enum NodeRefInternal<K> {
    Unloaded(u64),
    Loaded(Box<Node<K>>),
}

struct NodeRef<K>(cell::UnsafeCell<NodeRefInternal<K>>);

// An on-disk representation, for space saving.
#[derive(Serialize, Deserialize)]
struct DiskNode<K> {
    node_type: NodeType,
    keys: Vec<K>,
    children: Vec<u64>,
}

struct Node<K> {
    node_type: NodeType,
    keys: Vec<K>,
    children: Vec<NodeRef<K>>,
    modified: bool,
}

impl<K: serde::de::DeserializeOwned> From<DiskNode<K>> for Node<K> {
    fn from(obj: DiskNode<K>) -> Node<K> {
        Node {
            node_type: obj.node_type,
            keys: obj.keys,
            children: obj.children.into_iter().map(|x| (NodeRef::from_offset(x))).collect(),
            modified: false,
        }
    }
}

impl<K: serde::de::DeserializeOwned> DiskNode<K> {
    fn load<R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<DiskNode<K>, DecodingError> {
        decode(reader, offset)
    }
}

fn load<K: serde::de::DeserializeOwned, R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<Node<K>, DecodingError> {
    Ok(DiskNode::<K>::load(reader, offset)?.into())
}

impl<K: serde::de::DeserializeOwned> NodeRef<K> {
    fn from_offset(offset: u64) -> NodeRef<K> {
        NodeRef(cell::UnsafeCell::new(NodeRefInternal::Unloaded(offset)))
    }

    fn load<R: io::Read+io::Seek>(&self, reader: &mut R) -> Result<(), DecodingError> {
        let internal = self.0.get();
        unsafe {
            if let NodeRefInternal::Unloaded(offset) = *internal {
                *internal = NodeRefInternal::Loaded(Box::new(load(reader, offset)?));
            }
        }
        Ok(())
    }

    fn get<R: io::Read+io::Seek>(&self, reader: &mut R) -> Result<&Node<K>, DecodingError> {
        self.load(reader)?;
        unsafe {
            Ok(match *self.0.get() {
                NodeRefInternal::Loaded(ref n) => n,
                _ => panic!("Nodes should be loaded."),
            })
        }
    }

    fn get_mut<R: io::Read+io::Seek>(&mut self, reader: &mut R) -> Result<&mut Node<K>, DecodingError> {
        self.load(reader)?;
        unsafe {
            Ok(match *self.0.get() {
                NodeRefInternal::Loaded(ref mut n) => {
                    n.modified = true;
                    n
                },
                _ => panic!("Node not loaded."),
            })
        }
    }

    fn offset_or_panic(&self, msg: &'static str) -> u64 {
        let internal = self.0.get();
        unsafe {
            match *internal {
                NodeRefInternal::Unloaded(offset) => offset,
                _ => panic!(msg),
            }
        }
    }
}

impl<K> Drop for NodeRef<K> {
    fn drop(&mut self) {
        unsafe { std::ptr::drop_in_place(self.0.get()); }
    }
}

impl<K: serde::de::DeserializeOwned+Eq+Ord> Node<K> {
    fn find_offset_for<R: io::Read+io::Seek>(&self, reader: &mut R, key: &K) -> Result<Option<u64>, DecodingError> {
        if self.node_type == NodeType::Leaf {
            if self.children.len() == 0 { return Ok(None) } //empty tree.
            match self.keys.binary_search(key) {
                Ok(ind) => Ok(Some(self.children[ind].offset_or_panic("This is a leaf, but somehow has a loaded child."))),
                Err(_) => Ok(None),
            }
        }
        else {
            self.children[self.index_of(key)].get(reader)?.find_offset_for(reader, key)
        }
    }

    fn index_of(&self, key: &K) -> usize{
        assert!(self.node_type != NodeType::Leaf);
        let ind = self.keys.binary_search(key);
        // Explanation: this returns the index of the child to the right of the last key smaller than key.
        // In this implementation, before is <= and after is >.
        // Before is the index of the key, after is the index of the key+1.
        // The not found case of binary_search is the key+1.
        match ind {
            Ok(index) | Err(index) => index,
        }
    }
}

struct BPTree<'a, R: 'a, K, V> {
    root_reference: NodeRef<K>,
    backing_io: &'a mut R,
    _phantom: PhantomData<V>
}

impl<'a, R: io::Read+io::Seek, K: serde::de::DeserializeOwned+Eq+Ord, V> BPTree<'a, R, K, V> {
    pub fn contains(&mut self, key: &K) -> Result<bool, DecodingError> {
        Ok(self.offset_for(key)?.is_some())
    }

    pub fn offset_for(&mut self, key: &K) -> Result<Option<u64>, DecodingError> {
        self.root_reference.get(self.backing_io)?.find_offset_for(self.backing_io, key)
    }
}
<commit_msg>Function to split nodes.<commit_after>#![allow(dead_code)]
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate bincode;
extern crate take_mut;

use std::io;
use std::error::Error;
use std::marker::PhantomData;
use std::cell;

#[derive(Debug)]
pub enum DecodingError {
    Corrupt(String),
    IoError(io::Error),
}

fn decode<O: serde::de::DeserializeOwned, R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<O, DecodingError> {
    reader.seek(io::SeekFrom::Start(offset)).map_err(|x| DecodingError::IoError(x))?;
    bincode::deserialize_from(    reader, bincode::Infinite)
    .map_err(|x| {
        match *x {
            bincode::ErrorKind::IoError(y) => DecodingError::IoError(y),
            _ => DecodingError::Corrupt(x.description().to_string()),
        }
    })
}

#[derive(Debug)]
pub enum EncodingError {
    Unknown(String),
    IoError(io::Error),
}

fn encode<O: serde::Serialize, W: io::Write+io::Seek>(writer: &mut W, obj: &O) -> Result<u64, EncodingError> {
    let offset = writer.seek(io::SeekFrom::End(0)).map_err(|x| EncodingError::IoError(x))?;
    bincode::serialize_into(writer, obj, bincode::Infinite)
    .map_err(|x| {
        match *x {
            bincode::ErrorKind::IoError(y) => EncodingError::IoError(y),
            _ => EncodingError::Unknown(x.description().to_string()),
        }
    }).map(|_| offset)
}

#[derive(Serialize, Deserialize, Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
enum NodeType {
    Root,
    Internal,
    Leaf
}

enum NodeRefInternal<K> {
    Unloaded(u64),
    Loaded(Box<Node<K>>),
}

struct NodeRef<K>(cell::UnsafeCell<NodeRefInternal<K>>);

// An on-disk representation, for space saving.
#[derive(Serialize, Deserialize)]
struct DiskNode<K> {
    node_type: NodeType,
    keys: Vec<K>,
    children: Vec<u64>,
}

struct Node<K> {
    node_type: NodeType,
    keys: Vec<K>,
    children: Vec<NodeRef<K>>,
    modified: bool,
}

impl<K: serde::de::DeserializeOwned> From<DiskNode<K>> for Node<K> {
    fn from(obj: DiskNode<K>) -> Node<K> {
        Node {
            node_type: obj.node_type,
            keys: obj.keys,
            children: obj.children.into_iter().map(|x| (NodeRef::from_offset(x))).collect(),
            modified: false,
        }
    }
}

impl<K: serde::de::DeserializeOwned> DiskNode<K> {
    fn load<R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<DiskNode<K>, DecodingError> {
        decode(reader, offset)
    }
}

fn load<K: serde::de::DeserializeOwned, R: io::Read+io::Seek>(reader: &mut R, offset: u64) -> Result<Node<K>, DecodingError> {
    Ok(DiskNode::<K>::load(reader, offset)?.into())
}

impl<K: serde::de::DeserializeOwned> NodeRef<K> {
    fn from_offset(offset: u64) -> NodeRef<K> {
        NodeRef(cell::UnsafeCell::new(NodeRefInternal::Unloaded(offset)))
    }

    fn load<R: io::Read+io::Seek>(&self, reader: &mut R) -> Result<(), DecodingError> {
        let internal = self.0.get();
        unsafe {
            if let NodeRefInternal::Unloaded(offset) = *internal {
                *internal = NodeRefInternal::Loaded(Box::new(load(reader, offset)?));
            }
        }
        Ok(())
    }

    fn get<R: io::Read+io::Seek>(&self, reader: &mut R) -> Result<&Node<K>, DecodingError> {
        self.load(reader)?;
        unsafe {
            Ok(match *self.0.get() {
                NodeRefInternal::Loaded(ref n) => n,
                _ => panic!("Nodes should be loaded."),
            })
        }
    }

    fn get_mut<R: io::Read+io::Seek>(&mut self, reader: &mut R) -> Result<&mut Node<K>, DecodingError> {
        self.load(reader)?;
        unsafe {
            Ok(match *self.0.get() {
                NodeRefInternal::Loaded(ref mut n) => {
                    n.modified = true;
                    n
                },
                _ => panic!("Node not loaded."),
            })
        }
    }

    fn offset_or_panic(&self, msg: &'static str) -> u64 {
        let internal = self.0.get();
        unsafe {
            match *internal {
                NodeRefInternal::Unloaded(offset) => offset,
                _ => panic!(msg),
            }
        }
    }
}

impl<K> Drop for NodeRef<K> {
    fn drop(&mut self) {
        unsafe { std::ptr::drop_in_place(self.0.get()); }
    }
}

impl<K: serde::de::DeserializeOwned+Eq+Ord+Clone> Node<K> {
    fn find_offset_for<R: io::Read+io::Seek>(&self, reader: &mut R, key: &K) -> Result<Option<u64>, DecodingError> {
        if self.node_type == NodeType::Leaf {
            if self.children.len() == 0 { return Ok(None) } //empty tree.
            match self.keys.binary_search(key) {
                Ok(ind) => Ok(Some(self.children[ind].offset_or_panic("This is a leaf, but somehow has a loaded child."))),
                Err(_) => Ok(None),
            }
        }
        else {
            self.children[self.index_of(key)].get(reader)?.find_offset_for(reader, key)
        }
    }

    fn index_of(&self, key: &K) -> usize{
        assert!(self.node_type != NodeType::Leaf);
        let ind = self.keys.binary_search(key);
        // Explanation: this returns the index of the child to the right of the last key smaller than key.
        // In this implementation, before is <= and after is >.
        // Before is the index of the key, after is the index of the key+1.
        // The not found case of binary_search is the key+1.
        match ind {
            Ok(index) | Err(index) => index,
        }
    }

    /// Modify this node in place to split in half, returning the upper half.
    fn split_in_place(&mut self) -> (K, Box<Node<K>>) {
        // Doing this based off keys is important.
        let half = self.keys.len()/2;
        let upper_keys = self.keys.drain(half..).collect::<Vec<_>>();
        let upper_children = self.children.drain(half..).collect::<Vec<_>>();
        assert!(self.children.len() > 1);
        assert!(self.keys.len() > 1);
        assert!(upper_children.len() > 1);
        assert!(upper_keys.len() > 1);
        let ret_key;
        let ret_node;
        match self.node_type {
            NodeType::Leaf => {
                ret_key = self.keys.last().unwrap().clone();
                ret_node = Node {
                    keys: upper_keys,
                    children: upper_children,
                    node_type: NodeType::Leaf,
                    modified: true,
                };
            }
            NodeType::Root | NodeType::Internal => {
                // A split of the root makes us an internal, and something else will construct the new root.
                self.node_type = NodeType::Internal;
                // We have one extra key in ourself right now. This is greater than any value beneath us.
                // In this implementation we go left for <=.
                ret_key = self.keys.pop().unwrap();
                ret_node = Node {
                    node_type: NodeType::Internal,
                    keys: upper_keys,
                    children: upper_children,
                    modified: true,
                }
            }
        }
        (ret_key, Box::new(ret_node))
    }
}

struct BPTree<'a, R: 'a, K, V> {
    root_reference: NodeRef<K>,
    backing_io: &'a mut R,
    _phantom: PhantomData<V>
}

impl<'a, R: io::Read+io::Seek, K: serde::de::DeserializeOwned+Eq+Ord+Clone, V> BPTree<'a, R, K, V> {
    pub fn contains(&mut self, key: &K) -> Result<bool, DecodingError> {
        Ok(self.offset_for(key)?.is_some())
    }

    pub fn offset_for(&mut self, key: &K) -> Result<Option<u64>, DecodingError> {
        self.root_reference.get(self.backing_io)?.find_offset_for(self.backing_io, key)
    }
}
<|endoftext|>