<commit_before>/// The sure stream.
///
/// The sure stream represents a linearization of a SureTree.  By keeping
/// representations as iterators across SureNodes instead of keeping an
/// entire tree in memory, we can process larger filesystem trees, using
/// temporary space on the hard disk instead of using memory.

use crate::{
    Result,
    suretree::AttMap,
};
use failure::{format_err, err_msg};
use flate2::{write::GzEncoder, read::GzDecoder, Compression};
use std::{
    fs::File,
    io::{self, BufWriter, BufRead, BufReader, Read, Write},
    path::{Path, PathBuf},
};
use weave::{
    NamingConvention,
};

mod compare;
pub mod fs;
mod fullpath;
mod hashes;

pub use fullpath::into_tracker;
pub use hashes::{HashCombiner, HashUpdater, Source};
pub use compare::compare_trees;

#[derive(Clone, Debug)]
pub enum SureNode {
    Enter {
        name: String,
        atts: AttMap,
    },
    Leave,
    File {
        name: String,
        atts: AttMap,
    },
    Sep,
}

impl SureNode {
    pub fn is_enter(&self) -> bool {
        match self {
            SureNode::Enter { .. } => true,
            _ => false,
        }
    }

    pub fn is_reg_file(&self) -> bool {
        match self {
            SureNode::File { atts, .. } => atts["kind"] == "file",
            _ => false,
        }
    }

    pub fn is_file(&self) -> bool {
        match self {
            SureNode::File { .. } => true,
            _ => false,
        }
    }

    pub fn is_leave(&self) -> bool {
        match self {
            SureNode::Leave => true,
            _ => false,
        }
    }

    pub fn is_sep(&self) -> bool {
        match self {
            SureNode::Sep => true,
            _ => false,
        }
    }

    pub fn needs_hash(&self) -> bool {
        match self {
            SureNode::File { atts, .. } => atts["kind"] == "file" && !atts.contains_key("sha1"),
            _ => false,
        }
    }

    pub fn size(&self) -> u64 {
        match self {
            SureNode::File { atts, .. } =>
                atts.get("size").map(|x| x.parse().unwrap()).unwrap_or(0),
            _ => 0,
        }
    }

    /// Get the name of this node.  Panics if the node type does not have
    /// an associated name.
    pub fn name(&self) -> &str {
        match self {
            SureNode::File { ref name, .. } => name,
            SureNode::Enter { ref name, .. } => name,
            _ => panic!("Node does not have a name"),
        }
    }

    /// Get a nice representation of the kind of this node.  Returns "???"
    /// if the kind isn't meaningful.
    pub fn kind(&self) -> &str {
        self.atts()
            .map(|a| {
                a.get("kind")
                    .map(|k| &k[..])
                    .unwrap_or("???")
            })
            .unwrap_or("???")
    }

    /// Access the nodes attributes.
    pub fn atts(&self) -> Option<&AttMap> {
        match self {
            SureNode::File { ref atts, .. } => Some(atts),
            SureNode::Enter { ref atts, .. } => Some(atts),
            _ => None,
        }
    }

    /// Access the nodes attributes mutably.
    pub fn atts_mut(&mut self) -> Option<&mut AttMap> {
        match self {
            SureNode::File { ref mut atts, .. } => Some(atts),
            SureNode::Enter { ref mut atts, .. } => Some(atts),
            _ => None,
        }
    }
}

// TODO: These might be possible to make more generic, but it gets messy,
// as it might just be best to assume failure.

/// Write a sure iterator to a standard gzipped file of the given name.
pub fn save<P, I>(name: P, nodes: I) -> Result<()>
    where P: AsRef<Path>,
          I: Iterator<Item = Result<SureNode>>,
{
    let wr = File::create(name)?;
    let wr = GzEncoder::new(wr, Compression::default());
    save_to(wr, nodes)
}

/// Write a sure iterator to a new temp file with a given naming
/// convention.  Returns the name of the file, if it could be created.  The
/// data will not be written compressed.
pub fn save_naming<I, N>(naming: &N, nodes: I) -> Result<PathBuf>
    where N: NamingConvention,
          I: Iterator<Item = Result<SureNode>>,
{
    let (tmp_name, mut tmp_file) = naming.temp_file()?;
    save_to(&mut tmp_file, nodes)?;
    Ok(tmp_name)
}

/// Save a sure tree to the given writer.
pub fn save_to<W, I>(wr: W, nodes: I) -> Result<()>
    where W: Write,
          I: Iterator<Item = Result<SureNode>>,
{
    let mut wr = BufWriter::new(wr);

    writeln!(&mut wr, "asure-2.0")?;
    writeln!(&mut wr, "-----")?;

    for node in nodes {
        match node? {
            SureNode::Enter { name, atts } => header(&mut wr, 'd', &name, &atts)?,
            SureNode::File { name, atts } => header(&mut wr, 'f', &name, &atts)?,
            SureNode::Sep => writeln!(&mut wr, "-")?,
            SureNode::Leave => writeln!(&mut wr, "u")?,
        }
    }
    Ok(())
}

/// For pushed based writing, we can also write using a NodeWriter.
pub struct NodeWriter<W: Write> {
    writer: BufWriter<W>,
}

impl<W: Write> NodeWriter<W> {
    pub fn new(writer: W) -> Result<NodeWriter<W>> {
        let mut wr = BufWriter::new(writer);
        writeln!(&mut wr, "asure-2.0")?;
        writeln!(&mut wr, "-----")?;

        Ok(NodeWriter {
            writer: wr,
        })
    }

    pub fn write_node(&mut self, node: &SureNode) -> Result<()> {
        match node {
            SureNode::Enter { name, atts } => header(&mut self.writer, 'd', &name, &atts)?,
            SureNode::File { name, atts } => header(&mut self.writer, 'f', &name, &atts)?,
            SureNode::Sep => writeln!(&mut self.writer, "-")?,
            SureNode::Leave => writeln!(&mut self.writer, "u")?,
        }
        Ok(())
    }
}

fn header<W: Write>(out: &mut W, kind: char, name: &str, atts: &AttMap) -> Result<()> {
    write!(out, "{}{} [", kind, name)?;

    for (k, v) in atts {
        write!(out, "{} {} ", k, v)?;
    }
    writeln!(out, "]")?;
    Ok(())
}

/// Load and iterate a sure tree from a standard gzip compressed surefile.
pub fn load<P: AsRef<Path>>(name: P) -> Result<ReadIterator<GzDecoder<File>>> {
    let rd = File::open(name)?;
    let rd = GzDecoder::new(rd);
    load_from(rd)
}

/// Load a surenode sequence from the given reader.
pub fn load_from<R: Read>(rd: R) -> Result<ReadIterator<R>> {
    let rd = BufReader::new(rd);
    let mut lines = rd.split('\n' as u8);

    fixed(&mut lines, b"asure-2.0")?;
    fixed(&mut lines, b"-----")?;

    Ok(ReadIterator {
        lines: lines,
        depth: 0,
        done: false,
    })
}

fn fixed<I>(inp: &mut I, exp: &[u8]) -> Result<()>
    where I: Iterator<Item = io::Result<Vec<u8>>>
{
    match inp.next() {
        Some(Ok(ref text)) if &text[..] == exp => Ok(()),
        Some(Ok(ref text)) => Err(format_err!(
                "Unexpected line: {:?}, expect {:?}",
                String::from_utf8_lossy(text),
                String::from_utf8_lossy(exp))),
        Some(Err(e)) => Err(format_err!("Error reading surefile: {:?}", e)),
        None => Err(err_msg("Unexpected eof on surefile")),
    }
}

pub struct ReadIterator<R> {
    lines: io::Split<BufReader<R>>,
    depth: usize,
    done: bool,
}

impl<R: Read> Iterator for ReadIterator<R> {
    type Item = Result<SureNode>;

    fn next(&mut self) -> Option<Result<SureNode>> {
        if self.done {
            return None;
        }

        let line = match self.get_line() {
            Ok(line) => line,
            Err(e) => return Some(Err(e)),
        };

        match line[0] {
            b'd' => {
                let (dname, datts) = decode_entity(&line[1..]);
                self.depth += 1;
                Some(Ok(SureNode::Enter{name: dname, atts: datts}))
            }
            b'f' => {
                let (fname, fatts) = decode_entity(&line[1..]);
                Some(Ok(SureNode::File{name: fname, atts: fatts}))
            }
            b'-' => Some(Ok(SureNode::Sep)),
            b'u' => {
                self.depth -= 1;
                if self.depth == 0 {
                    self.done = true;
                }
                Some(Ok(SureNode::Leave))
            }
            ch => Some(Err(format_err!("Invalid surefile line start: {}", ch))),
        }
    }
}

impl<R: Read> ReadIterator<R> {
    fn get_line(&mut self) -> Result<Vec<u8>> {
        match self.lines.next() {
            None => return Err(err_msg("surefile is truncated")),
            Some(l) => Ok(l?),
        }
    }
}

// TODO: This should return Result to handle errors.
pub(crate) fn decode_entity(text: &[u8]) -> (String, AttMap) {
    let (name, mut text) = get_delim(text, b' ');
    assert!(text[0] == b'[');
    text = &text[1..];

    let mut atts = AttMap::new();
    while text[0] != b']' {
        let (key, t2) = get_delim(text, b' ');
        let (value, t2) = get_delim(t2, b' ');
        text = t2;

        atts.insert(key, value);
    }

    (name, atts)
}

fn get_delim(text: &[u8], delim: u8) -> (String, &[u8]) {
    let mut it = text.iter();
    let space = it.position(|&s| s == delim).unwrap();
    (
        String::from_utf8(text[..space].to_owned()).unwrap(),
        &text[space + 1..],
    )
}
<commit_msg>Add a `get_name` method to `SureNode`<commit_after>/// The sure stream.
///
/// The sure stream represents a linearization of a SureTree.  By keeping
/// representations as iterators across SureNodes instead of keeping an
/// entire tree in memory, we can process larger filesystem trees, using
/// temporary space on the hard disk instead of using memory.

use crate::{
    Result,
    suretree::AttMap,
};
use failure::{format_err, err_msg};
use flate2::{write::GzEncoder, read::GzDecoder, Compression};
use std::{
    fs::File,
    io::{self, BufWriter, BufRead, BufReader, Read, Write},
    path::{Path, PathBuf},
};
use weave::{
    NamingConvention,
};

mod compare;
pub mod fs;
mod fullpath;
mod hashes;

pub use fullpath::into_tracker;
pub use hashes::{HashCombiner, HashUpdater, Source};
pub use compare::compare_trees;

#[derive(Clone, Debug)]
pub enum SureNode {
    Enter {
        name: String,
        atts: AttMap,
    },
    Leave,
    File {
        name: String,
        atts: AttMap,
    },
    Sep,
}

impl SureNode {
    pub fn is_enter(&self) -> bool {
        match self {
            SureNode::Enter { .. } => true,
            _ => false,
        }
    }

    pub fn is_reg_file(&self) -> bool {
        match self {
            SureNode::File { atts, .. } => atts["kind"] == "file",
            _ => false,
        }
    }

    pub fn is_file(&self) -> bool {
        match self {
            SureNode::File { .. } => true,
            _ => false,
        }
    }

    pub fn is_leave(&self) -> bool {
        match self {
            SureNode::Leave => true,
            _ => false,
        }
    }

    pub fn is_sep(&self) -> bool {
        match self {
            SureNode::Sep => true,
            _ => false,
        }
    }

    pub fn needs_hash(&self) -> bool {
        match self {
            SureNode::File { atts, .. } => atts["kind"] == "file" && !atts.contains_key("sha1"),
            _ => false,
        }
    }

    pub fn size(&self) -> u64 {
        match self {
            SureNode::File { atts, .. } =>
                atts.get("size").map(|x| x.parse().unwrap()).unwrap_or(0),
            _ => 0,
        }
    }

    /// Get the name of this node.  Panics if the node type does not have
    /// an associated name.
    pub fn name(&self) -> &str {
        match self {
            SureNode::File { ref name, .. } => name,
            SureNode::Enter { ref name, .. } => name,
            _ => panic!("Node does not have a name"),
        }
    }

    /// Safely get the name of this node.
    pub fn get_name(&self) -> Option<&str> {
        match self {
            SureNode::File { ref name, .. } => Some(name),
            SureNode::Enter { ref name, .. } => Some(name),
            _ => None,
        }
    }

    /// Get a nice representation of the kind of this node.  Returns "???"
    /// if the kind isn't meaningful.
    pub fn kind(&self) -> &str {
        self.atts()
            .map(|a| {
                a.get("kind")
                    .map(|k| &k[..])
                    .unwrap_or("???")
            })
            .unwrap_or("???")
    }

    /// Access the nodes attributes.
    pub fn atts(&self) -> Option<&AttMap> {
        match self {
            SureNode::File { ref atts, .. } => Some(atts),
            SureNode::Enter { ref atts, .. } => Some(atts),
            _ => None,
        }
    }

    /// Access the nodes attributes mutably.
    pub fn atts_mut(&mut self) -> Option<&mut AttMap> {
        match self {
            SureNode::File { ref mut atts, .. } => Some(atts),
            SureNode::Enter { ref mut atts, .. } => Some(atts),
            _ => None,
        }
    }
}

// TODO: These might be possible to make more generic, but it gets messy,
// as it might just be best to assume failure.

/// Write a sure iterator to a standard gzipped file of the given name.
pub fn save<P, I>(name: P, nodes: I) -> Result<()>
    where P: AsRef<Path>,
          I: Iterator<Item = Result<SureNode>>,
{
    let wr = File::create(name)?;
    let wr = GzEncoder::new(wr, Compression::default());
    save_to(wr, nodes)
}

/// Write a sure iterator to a new temp file with a given naming
/// convention.  Returns the name of the file, if it could be created.  The
/// data will not be written compressed.
pub fn save_naming<I, N>(naming: &N, nodes: I) -> Result<PathBuf>
    where N: NamingConvention,
          I: Iterator<Item = Result<SureNode>>,
{
    let (tmp_name, mut tmp_file) = naming.temp_file()?;
    save_to(&mut tmp_file, nodes)?;
    Ok(tmp_name)
}

/// Save a sure tree to the given writer.
pub fn save_to<W, I>(wr: W, nodes: I) -> Result<()>
    where W: Write,
          I: Iterator<Item = Result<SureNode>>,
{
    let mut wr = BufWriter::new(wr);

    writeln!(&mut wr, "asure-2.0")?;
    writeln!(&mut wr, "-----")?;

    for node in nodes {
        match node? {
            SureNode::Enter { name, atts } => header(&mut wr, 'd', &name, &atts)?,
            SureNode::File { name, atts } => header(&mut wr, 'f', &name, &atts)?,
            SureNode::Sep => writeln!(&mut wr, "-")?,
            SureNode::Leave => writeln!(&mut wr, "u")?,
        }
    }
    Ok(())
}

/// For pushed based writing, we can also write using a NodeWriter.
pub struct NodeWriter<W: Write> {
    writer: BufWriter<W>,
}

impl<W: Write> NodeWriter<W> {
    pub fn new(writer: W) -> Result<NodeWriter<W>> {
        let mut wr = BufWriter::new(writer);
        writeln!(&mut wr, "asure-2.0")?;
        writeln!(&mut wr, "-----")?;

        Ok(NodeWriter {
            writer: wr,
        })
    }

    pub fn write_node(&mut self, node: &SureNode) -> Result<()> {
        match node {
            SureNode::Enter { name, atts } => header(&mut self.writer, 'd', &name, &atts)?,
            SureNode::File { name, atts } => header(&mut self.writer, 'f', &name, &atts)?,
            SureNode::Sep => writeln!(&mut self.writer, "-")?,
            SureNode::Leave => writeln!(&mut self.writer, "u")?,
        }
        Ok(())
    }
}

fn header<W: Write>(out: &mut W, kind: char, name: &str, atts: &AttMap) -> Result<()> {
    write!(out, "{}{} [", kind, name)?;

    for (k, v) in atts {
        write!(out, "{} {} ", k, v)?;
    }
    writeln!(out, "]")?;
    Ok(())
}

/// Load and iterate a sure tree from a standard gzip compressed surefile.
pub fn load<P: AsRef<Path>>(name: P) -> Result<ReadIterator<GzDecoder<File>>> {
    let rd = File::open(name)?;
    let rd = GzDecoder::new(rd);
    load_from(rd)
}

/// Load a surenode sequence from the given reader.
pub fn load_from<R: Read>(rd: R) -> Result<ReadIterator<R>> {
    let rd = BufReader::new(rd);
    let mut lines = rd.split('\n' as u8);

    fixed(&mut lines, b"asure-2.0")?;
    fixed(&mut lines, b"-----")?;

    Ok(ReadIterator {
        lines: lines,
        depth: 0,
        done: false,
    })
}

fn fixed<I>(inp: &mut I, exp: &[u8]) -> Result<()>
    where I: Iterator<Item = io::Result<Vec<u8>>>
{
    match inp.next() {
        Some(Ok(ref text)) if &text[..] == exp => Ok(()),
        Some(Ok(ref text)) => Err(format_err!(
                "Unexpected line: {:?}, expect {:?}",
                String::from_utf8_lossy(text),
                String::from_utf8_lossy(exp))),
        Some(Err(e)) => Err(format_err!("Error reading surefile: {:?}", e)),
        None => Err(err_msg("Unexpected eof on surefile")),
    }
}

pub struct ReadIterator<R> {
    lines: io::Split<BufReader<R>>,
    depth: usize,
    done: bool,
}

impl<R: Read> Iterator for ReadIterator<R> {
    type Item = Result<SureNode>;

    fn next(&mut self) -> Option<Result<SureNode>> {
        if self.done {
            return None;
        }

        let line = match self.get_line() {
            Ok(line) => line,
            Err(e) => return Some(Err(e)),
        };

        match line[0] {
            b'd' => {
                let (dname, datts) = decode_entity(&line[1..]);
                self.depth += 1;
                Some(Ok(SureNode::Enter{name: dname, atts: datts}))
            }
            b'f' => {
                let (fname, fatts) = decode_entity(&line[1..]);
                Some(Ok(SureNode::File{name: fname, atts: fatts}))
            }
            b'-' => Some(Ok(SureNode::Sep)),
            b'u' => {
                self.depth -= 1;
                if self.depth == 0 {
                    self.done = true;
                }
                Some(Ok(SureNode::Leave))
            }
            ch => Some(Err(format_err!("Invalid surefile line start: {}", ch))),
        }
    }
}

impl<R: Read> ReadIterator<R> {
    fn get_line(&mut self) -> Result<Vec<u8>> {
        match self.lines.next() {
            None => return Err(err_msg("surefile is truncated")),
            Some(l) => Ok(l?),
        }
    }
}

// TODO: This should return Result to handle errors.
pub(crate) fn decode_entity(text: &[u8]) -> (String, AttMap) {
    let (name, mut text) = get_delim(text, b' ');
    assert!(text[0] == b'[');
    text = &text[1..];

    let mut atts = AttMap::new();
    while text[0] != b']' {
        let (key, t2) = get_delim(text, b' ');
        let (value, t2) = get_delim(t2, b' ');
        text = t2;

        atts.insert(key, value);
    }

    (name, atts)
}

fn get_delim(text: &[u8], delim: u8) -> (String, &[u8]) {
    let mut it = text.iter();
    let space = it.position(|&s| s == delim).unwrap();
    (
        String::from_utf8(text[..space].to_owned()).unwrap(),
        &text[space + 1..],
    )
}
<|endoftext|>


<commit_before>use std::time::SystemTime;

const PI: f64 = 3.141592654;

/// RAND_MAX is a const
/// Please don't assume that it is any value
pub const RAND_MAX: u32 = 32767;

pub enum Rand {
    Basic(u32),
    PMrand(u32, u32),
    Gauss(u32, u32),
    BMgauss(u32, f64, f64, bool),
    Marsaglia(u32, f64, f64, f64, bool),
}

impl Rand {
    /// a lazy way to get a random solver
    pub fn new() -> Self {
        Rand::Basic(time_get() as u32)
    }

    /// set seed of solver
    pub fn srand(&mut self, seed: u32) {
        match *self {
            Rand::Basic(_) => *self = Rand::Basic(seed),
            Rand::PMrand(_, a) => *self = Rand::PMrand(seed, a),
            Rand::Gauss(_, nsum) => *self = Rand::Gauss(seed, nsum),
            Rand::BMgauss(_, u, v, phase) => *self = Rand::BMgauss(seed, u, v, phase),
            Rand::Marsaglia(_, v1, v2, s, phase) => *self = Rand::Marsaglia(seed, v1, v2, s, phase),
        }
    }

    /// get a random number
    pub fn rand(&mut self) -> f64 {
        match *self {
            Rand::Basic(seed) => {
                let mut foo = seed;
                let bar = basic(&mut foo);
                self.srand(foo);
                bar as f64
            }
            Rand::PMrand(seed, a) => {
                let mut foo = seed;
                let bar = pmrand(&mut foo, a);
                self.srand(foo);
                bar as f64
            }
            Rand::Gauss(seed, nsum) => {
                let mut foo = seed;
                let bar = gauss(&mut foo, nsum);
                self.srand(foo);
                bar
            }
            Rand::BMgauss(seed, u, v, phase) => {
                let mut foo_seed = seed;
                let mut foo_u = u;
                let mut foo_v = v;
                let mut foo_phase = phase;
                let bar = bmgauss(&mut foo_seed, &mut foo_u, &mut foo_v, &mut foo_phase);
                *self = Rand::BMgauss(foo_seed, foo_u, foo_v, foo_phase);
                bar
            }
            Rand::Marsaglia(seed, v1, v2, s, phase) => {
                let mut foo_seed = seed;
                let mut foo_v1 = v1;
                let mut foo_v2 = v2;
                let mut foo_s = s;
                let mut foo_phase = phase;
                let bar = marsaglia(&mut foo_seed,
                                    &mut foo_v1,
                                    &mut foo_v2,
                                    &mut foo_s,
                                    &mut foo_phase);
                *self = Rand::Marsaglia(foo_seed, foo_v1, foo_v2, foo_s, foo_phase);
                bar
            }
        }
    }
}

fn time_get() -> i64 {
    let sys_time = SystemTime::now();
    let foo_string = format!("{:?}", sys_time);
    let mut seed: i64 = 0;
    let mut flag = false;
    for num in foo_string.chars() {
        match num {
            e @ '0'...'9' => {
                flag = true;
                seed = seed * 10 + (e as u8 - 48) as i64;
                if seed >= i32::max_value() as i64 {
                    break;
                }
            }
            _ => {
                if flag {
                    break;
                }
            }
        }
    }
    seed
}

/// basic is a random function
/// # Describe Code
/// ```BASIC
/// function basic(seed as u32) as u32
///     seed = seed * 1103515245 + 12345
///     basic = seed >> 16 & RAND_MAX
/// end function
/// ```
fn basic(seed: &mut u32) -> u32 {
    *seed = (((*seed as u64 * 1103515245) as u32) as u64 + 12345) as u32;
    *seed >> 16 & RAND_MAX
}

/// pmrand is a random function by Park and Miller
/// # Describe Code
/// ```BASIC
/// function pmrand(seed as u32, byval a as u32) as u32
///     m = 2147483647
///     q = m / a
///     r = m mod as
///     hi = seed / q
///     lo = seed mod q
///     test = a * lo - r * hi
///     if test > 0 then
///         seed = test
///     else
///         seed = test + m
///     end if
///     pmrand = seed
/// end function
/// ```
fn pmrand(seed: &mut u32, a: u32) -> u32 {
    let m: u64 = 2147483647;
    let q = m / a as u64;
    let r = m % a as u64;
    let hi = *seed as u64 / q;
    let lo = *seed as u64 % q;
    let test = a as u64 * lo - r * hi;
    if test > 0 {
        *seed = test as u32;
    } else {
        *seed = (test + m) as u32;
    }
    *seed
}

/// gauss is a normal random function
/// # Describe Code
/// ```BASIC
/// function gauss(seed as u32, byval nsum as u32) as f64
///     x = 0
///     for i = 1 to nsum
///         x = x + basic(seed) / RAND_MAX
///     next i
///     x = x - nsum / 2
///     x = x / ((nsum / 12) ^ 0.5)
///     gauss = x
/// end function
/// ```
fn gauss(seed: &mut u32, nsum: u32) -> f64 {
    let mut x = 0.0;
    for _ in 0..nsum {
        x += basic(seed) as f64 / RAND_MAX as f64;
    }
    x -= nsum as f64 / 2.0;
    x /= (nsum as f64 / 12.0).sqrt();
    x
}

/// bmgauss is a normal random function by Box and Muller
/// # Describe Code
/// ```BASIC
/// function bmgauss(seed as u32, u as f64, v as f64, phase as bool) as f64
///     if phase then
///         phase = false
///         u = (basic(seed) + 1) / (RAND_MAX + 2)
///         v = basic(seed) / (RAND_MAX + 1)
///         bmgauss = sin(2 * PI * v)
///     else
///         phase = true
///         bmgauss = cos(2 * PI * v)
///     end if
///     bmgauss = bmgauss * (-2 * (log(u) ^ 0.5))
/// end function
/// ```
fn bmgauss(seed: &mut u32, u: &mut f64, v: &mut f64, phase: &mut bool) -> f64 {
    if *phase {
        *phase = false;
        *u = (basic(seed) + 1) as f64 / (RAND_MAX + 2) as f64;
        *v = basic(seed) as f64 / (RAND_MAX + 1) as f64;
        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).sin()
    } else {
        *phase = true;
        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).cos()
    }
}

/// marsaglia is a normal random function by Marsaglia
/// # Describe Code
/// ```BASIC
/// function marsaglia (seed as u32, v1 as f64, v2 as f64, s as f64, phase as bool) as f64
///     if phase then
///         phase = false
///         u1 = basic(seed) / RAND_MAX
///         u2 = basic(seed) / RAND_MAX
///         v1 = 2 * u1 - 1
///         v2 = 2 * u2 - 1
///         marsaglia = v1
///     else
///         phase = true
///         marsaglia = v2
///     end if
///     marsaglia = marsaglia * ((-2 * log(s) / s) ^ 0.5)
/// end function
/// ```
fn marsaglia(seed: &mut u32, v1: &mut f64, v2: &mut f64, s: &mut f64, phase: &mut bool) -> f64 {
    if *phase {
        *phase = false;
        let u1 = basic(seed) as f64 / RAND_MAX as f64;
        let u2 = basic(seed) as f64 / RAND_MAX as f64;
        *v1 = 2.0 * u1 - 1.0;
        *v2 = 2.0 * u2 - 1.0;
        *v1 * (-2.0 * (*s).log10() / (*s)).sqrt()
    } else {
        *phase = true;
        *v2 * (-2.0 * (*s).log10() / (*s)).sqrt()
    }
}
<commit_msg>Update 0.1.2<commit_after>use std::time::SystemTime;

const PI: f64 = 3.141592654;

/// RAND_MAX is a const
/// Please don't assume that it is any value
pub const RAND_MAX: u32 = 32767;

pub enum Rand {
    Basic(u32),
    PMrand(u32, u32),
    Gauss(u32, u32),
    BMgauss(u32, f64, f64, bool),
    Marsaglia(u32, f64, f64, f64, bool),
}

impl Rand {
    /// a lazy way to get a random solver
    pub fn new() -> Self {
        Rand::Basic(time_get() as u32)
    }

    /// set seed of solver
    pub fn srand(&mut self, seed: u32) {
        match *self {
            Rand::Basic(_) => *self = Rand::Basic(seed),
            Rand::PMrand(_, a) => *self = Rand::PMrand(seed, a),
            Rand::Gauss(_, nsum) => *self = Rand::Gauss(seed, nsum),
            Rand::BMgauss(_, u, v, phase) => *self = Rand::BMgauss(seed, u, v, phase),
            Rand::Marsaglia(_, v1, v2, s, phase) => *self = Rand::Marsaglia(seed, v1, v2, s, phase),
        }
    }

    pub fn lazy_srand(&mut self) {
        self.srand(time_get() as u32);
    }

    /// get a random number
    pub fn rand(&mut self) -> f64 {
        match *self {
            Rand::Basic(seed) => {
                let mut foo = seed;
                let bar = basic(&mut foo);
                self.srand(foo);
                bar as f64
            }
            Rand::PMrand(seed, a) => {
                let mut foo = seed;
                let bar = pmrand(&mut foo, a);
                self.srand(foo);
                bar as f64
            }
            Rand::Gauss(seed, nsum) => {
                let mut foo = seed;
                let bar = gauss(&mut foo, nsum);
                self.srand(foo);
                bar
            }
            Rand::BMgauss(seed, u, v, phase) => {
                let mut foo_seed = seed;
                let mut foo_u = u;
                let mut foo_v = v;
                let mut foo_phase = phase;
                let bar = bmgauss(&mut foo_seed, &mut foo_u, &mut foo_v, &mut foo_phase);
                *self = Rand::BMgauss(foo_seed, foo_u, foo_v, foo_phase);
                bar
            }
            Rand::Marsaglia(seed, v1, v2, s, phase) => {
                let mut foo_seed = seed;
                let mut foo_v1 = v1;
                let mut foo_v2 = v2;
                let mut foo_s = s;
                let mut foo_phase = phase;
                let bar = marsaglia(&mut foo_seed,
                                    &mut foo_v1,
                                    &mut foo_v2,
                                    &mut foo_s,
                                    &mut foo_phase);
                *self = Rand::Marsaglia(foo_seed, foo_v1, foo_v2, foo_s, foo_phase);
                bar
            }
        }
    }
}

fn time_get() -> i64 {
    let sys_time = SystemTime::now();
    let foo_string = format!("{:?}", sys_time);
    let mut seed: i64 = 0;
    let mut flag = false;
    for num in foo_string.chars() {
        match num {
            e @ '0'...'9' => {
                flag = true;
                seed = seed * 10 + (e as u8 - 48) as i64;
                if seed >= i32::max_value() as i64 {
                    break;
                }
            }
            _ => {
                if flag {
                    break;
                }
            }
        }
    }
    seed
}

/// basic is a random function
/// # Describe Code
/// ```BASIC
/// function basic(seed as u32) as u32
///     seed = seed * 1103515245 + 12345
///     basic = seed >> 16 & RAND_MAX
/// end function
/// ```
fn basic(seed: &mut u32) -> u32 {
    *seed = (((*seed as u64 * 1103515245) as u32) as u64 + 12345) as u32;
    *seed >> 16 & RAND_MAX
}

/// pmrand is a random function by Park and Miller
/// # Describe Code
/// ```BASIC
/// function pmrand(seed as u32, byval a as u32) as u32
///     m = 2147483647
///     q = m / a
///     r = m mod as
///     hi = seed / q
///     lo = seed mod q
///     test = a * lo - r * hi
///     if test > 0 then
///         seed = test
///     else
///         seed = test + m
///     end if
///     pmrand = seed
/// end function
/// ```
fn pmrand(seed: &mut u32, a: u32) -> u32 {
    let m: u64 = 2147483647;
    let q = m / a as u64;
    let r = m % a as u64;
    let hi = *seed as u64 / q;
    let lo = *seed as u64 % q;
    let test = a as u64 * lo - r * hi;
    if test > 0 {
        *seed = test as u32;
    } else {
        *seed = (test + m) as u32;
    }
    *seed
}

/// gauss is a normal random function
/// # Describe Code
/// ```BASIC
/// function gauss(seed as u32, byval nsum as u32) as f64
///     x = 0
///     for i = 1 to nsum
///         x = x + basic(seed) / RAND_MAX
///     next i
///     x = x - nsum / 2
///     x = x / ((nsum / 12) ^ 0.5)
///     gauss = x
/// end function
/// ```
fn gauss(seed: &mut u32, nsum: u32) -> f64 {
    let mut x = 0.0;
    for _ in 0..nsum {
        x += basic(seed) as f64 / RAND_MAX as f64;
    }
    x -= nsum as f64 / 2.0;
    x /= (nsum as f64 / 12.0).sqrt();
    x
}

/// bmgauss is a normal random function by Box and Muller
/// # Describe Code
/// ```BASIC
/// function bmgauss(seed as u32, u as f64, v as f64, phase as bool) as f64
///     if phase then
///         phase = false
///         u = (basic(seed) + 1) / (RAND_MAX + 2)
///         v = basic(seed) / (RAND_MAX + 1)
///         bmgauss = sin(2 * PI * v)
///     else
///         phase = true
///         bmgauss = cos(2 * PI * v)
///     end if
///     bmgauss = bmgauss * (-2 * (log(u) ^ 0.5))
/// end function
/// ```
fn bmgauss(seed: &mut u32, u: &mut f64, v: &mut f64, phase: &mut bool) -> f64 {
    if *phase {
        *phase = false;
        *u = (basic(seed) + 1) as f64 / (RAND_MAX + 2) as f64;
        *v = basic(seed) as f64 / (RAND_MAX + 1) as f64;
        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).sin()
    } else {
        *phase = true;
        (-2.0 * (*u).log10()).sqrt() * (2.0 * PI * (*v)).cos()
    }
}

/// marsaglia is a normal random function by Marsaglia
/// # Describe Code
/// ```BASIC
/// function marsaglia (seed as u32, v1 as f64, v2 as f64, s as f64, phase as bool) as f64
///     if phase then
///         phase = false
///         u1 = basic(seed) / RAND_MAX
///         u2 = basic(seed) / RAND_MAX
///         v1 = 2 * u1 - 1
///         v2 = 2 * u2 - 1
///         marsaglia = v1
///     else
///         phase = true
///         marsaglia = v2
///     end if
///     marsaglia = marsaglia * ((-2 * log(s) / s) ^ 0.5)
/// end function
/// ```
fn marsaglia(seed: &mut u32, v1: &mut f64, v2: &mut f64, s: &mut f64, phase: &mut bool) -> f64 {
    if *phase {
        *phase = false;
        let u1 = basic(seed) as f64 / RAND_MAX as f64;
        let u2 = basic(seed) as f64 / RAND_MAX as f64;
        *v1 = 2.0 * u1 - 1.0;
        *v2 = 2.0 * u2 - 1.0;
        *v1 * (-2.0 * (*s).log10() / (*s)).sqrt()
    } else {
        *phase = true;
        *v2 * (-2.0 * (*s).log10() / (*s)).sqrt()
    }
}
<|endoftext|>


<commit_before>use index::{Index, OpenOptions, Batch};
use json_value::{JsonValue, PrettyPrint};

use std::io::{Write, BufRead};
use std::mem;

fn is_command(str: &str) -> bool {
    let commands = ["find", "add", "create", "drop", "open", "pretty", "commit", "del", "load",
                    "dumpkeys", "params"];
    for command in commands.iter() {
        if str.starts_with(command) {
            return true;
        }
    }
    false
}

pub fn repl(r: &mut BufRead, w: &mut Write, test_mode: bool) {
    let mut index: Option<Index> = None;
    let mut batch = Batch::new();
    let mut lines = String::new();
    let mut pretty = PrettyPrint::new("", "", "");
    let mut params = None;
    loop {
        // read in command until we get to a end semi-colon
        if r.read_line(&mut lines).unwrap() > 0 {
            if test_mode && lines == "\n" || lines.starts_with("#") {
                // we preserve blank lines and comments in test mode
                w.write_all(lines.as_bytes()).unwrap();
                lines.clear();
                continue;
            }
            if test_mode && !is_command(&lines) {
                // we drop non-command lines
                lines.clear();
                continue;
            } else if !is_command(&lines) {
                w.write_all(b"Unrecognized command!\n").unwrap();
                lines.clear();
                continue;
            }
            // check for end semi-colon
            if !lines.trim_right().ends_with(";") {
                while r.read_line(&mut lines).unwrap() > 0 {
                    // loop until we get the end semi-colon
                    if lines.trim_right().ends_with(";") {
                        break;
                    }
                }
            }
        } else {
            // commit anything written
            if index.is_some() {
                let mut batch2 = Batch::new();
                mem::swap(&mut batch, &mut batch2);
                if let Err(reason) = index.as_mut().unwrap().flush(batch2) {
                    write!(w, "{}\n", reason).unwrap();
                }
            }
            return;
        }
        if test_mode {
            // echo the command
            w.write_all(lines.as_bytes()).unwrap();
        }
        lines = lines.trim_right().to_string();
        if lines.ends_with(";") {
            // strip the semi-colon off
            lines.pop();
        } else {
            write!(w, "Unterminated command, no semi-colon (;) {}\n", lines).unwrap();
        }
        if lines.starts_with("params") {
            params = Some(lines[6..].trim_left().to_string());
        } else if lines.starts_with("pretty") {
            if lines[6..].trim_left().starts_with("on") {
                pretty = PrettyPrint::new("  ", "\n", " ");
            } else {
                pretty = PrettyPrint::new("", "", "");
            }
        } else if lines.starts_with("create") {
            let dbname = lines[6..].trim_left();
            match Index::open(dbname, Some(OpenOptions::Create)) {
                Ok(index_new) => index = Some(index_new),
                Err(reason) => write!(w, "{}\n", reason).unwrap(),
            }
        } else if lines.starts_with("drop") {
            let dbname = lines[4..].trim_left();
            match Index::drop(dbname) {
                Ok(()) => (),
                Err(reason) => write!(w, "{}\n", reason).unwrap(),
            }
        } else if lines.starts_with("open") {
            let dbname = lines[4..].trim_left();
            match Index::open(dbname, None) {
                Ok(index_new) => index = Some(index_new),
                Err(reason) => write!(w, "{}\n", reason).unwrap(),
            }
        } else if lines.starts_with("dumpkeys") {
            if index.is_some() {
                match index.as_mut().unwrap().all_keys() {
                    Ok(keys) => {
                        for key in keys {
                            write!(w, "{}\n", key).unwrap();
                        }
                    }
                    Err(reason) => {
                        write!(w, "{}\n", reason).unwrap();
                    }
                }
            } else {
                write!(w, "Index isn't open\n").unwrap();
            }
        } else if lines.starts_with("add") {
            if index.is_some() {
                match index.as_mut().unwrap().add(&lines[3..], &mut batch) {
                    Ok(id) => write!(w, "{}\n", JsonValue::str_to_literal(&id)).unwrap(),
                    Err(reason) => write!(w, "{}\n", reason).unwrap(),
                }
            } else {
                write!(w, "Index isn't open\n").unwrap();
            }
        } else if lines.starts_with("del") {
            if index.is_some() {
                match index
                          .as_mut()
                          .unwrap()
                          .delete(&lines[3..].trim_left(), &mut batch) {
                    Ok(true) => write!(w, "ok\n").unwrap(),
                    Ok(false) => write!(w, "not found\n").unwrap(),
                    Err(reason) => write!(w, "{}\n", reason).unwrap(),
                }
            } else {
                write!(w, "Index isn't open\n").unwrap();
            }
        } else if lines.starts_with("commit") {
            if index.is_some() {
                let mut batch2 = Batch::new();
                mem::swap(&mut batch, &mut batch2);
                if let Err(reason) = index.as_mut().unwrap().flush(batch2) {
                    write!(w, "{}\n", reason).unwrap();
                }
            } else {
                write!(w, "Index isn't open\n").unwrap();
            }
        } else if lines.starts_with("find") {
            if index.is_some() {
                let mut batch2 = Batch::new();
                mem::swap(&mut batch, &mut batch2);
                if let Err(reason) = index.as_mut().unwrap().flush(batch2) {
                    write!(w, "{}\n", reason).unwrap();
                } else {
                    match index.as_ref().unwrap().query(&lines, params.take()) {
                        Ok(results) => {
                            let mut results = results.peekable();

                            w.write_all(b"[").unwrap();
                            if results.peek().is_some() {
                                w.write_all(b"\n").unwrap();
                            }
                            pretty.push();
                            while let Some(json) = results.next() {
                                json.render(w, &mut pretty).unwrap();
                                if results.peek().is_some() {
                                    w.write_all(b",").unwrap();
                                }
                                w.write_all(b"\n").unwrap();
                            }
                            w.write_all(b"]\n").unwrap();
                        }
                        Err(reason) => write!(w, "{}\n", reason).unwrap(),
                    }
                }
            } else {
                write!(w, "Index isn't open\n").unwrap();
            }
        }
        lines.clear();
    }
}
<commit_msg>Refactor repl and make more robust and less repeating code.<commit_after>use index::{Index, OpenOptions, Batch};
use json_value::{JsonValue, PrettyPrint};

use std::io::{Write, BufRead};
use std::mem;

fn is_command(str: &str) -> bool {
    let commands = ["find", "add", "create", "drop", "open", "pretty", "commit", "del",
                    "dumpkeys", "params"];
    for command in commands.iter() {
        if str.starts_with(command) {
            return true;
        }
    }
    false
}

fn next_command(r: &mut BufRead, w: &mut Write, test_mode: bool) -> Option<String> {
    let mut lines = String::new();
    loop {
        // read in command until we get to a end semi-colon
        if r.read_line(&mut lines).unwrap() > 0 {
            if test_mode && lines == "\n" || lines.starts_with("#") {
                // we preserve blank lines and comments in test mode
                w.write_all(lines.as_bytes()).unwrap();
                lines.clear();
                continue;
            }
            if test_mode && !is_command(&lines) {
                // we drop non-command lines
                lines.clear();
                continue;
            } else if !is_command(&lines) {
                w.write_all(b"Unrecognized command!\n").unwrap();
                lines.clear();
                continue;
            }
            // check for end semi-colon
            if !lines.trim_right().ends_with(";") {
                while r.read_line(&mut lines).unwrap() > 0 {
                    // loop until we get the end semi-colon
                    if lines.trim_right().ends_with(";") {
                        break;
                    }
                }
            }
        } else {
            return None;
        }

        if test_mode {
            // echo the command
            w.write_all(lines.as_bytes()).unwrap();
        }

        lines = lines.trim_right().to_string();
        if lines.ends_with(";") {
            // strip the semi-colon off
            lines.pop();
            return Some(lines);
        } else {
            panic!("Unterminated command, no semi-colon (;) {}\n", lines);
        }
    }
}

pub fn repl(r: &mut BufRead, w: &mut Write, test_mode: bool) {
    let mut pretty = PrettyPrint::new("", "", "");
    loop {
        if let Some(cmd) = next_command(r, w, test_mode) {
            if cmd.starts_with("open") {
                let dbname = cmd[4..].trim_left();
                match Index::open(dbname, None) {
                    Ok(index) => {
                        repl_opened(index, r, w, test_mode, pretty);
                        return;
                    }
                    Err(reason) => write!(w, "{}\n", reason).unwrap(),
                }
            } else if cmd.starts_with("create") {
                let dbname = cmd[6..].trim_left();
                match Index::open(dbname, Some(OpenOptions::Create)) {
                    Ok(index) => {
                        repl_opened(index, r, w, test_mode, pretty);
                        return;
                    }
                    Err(reason) => write!(w, "{}\n", reason).unwrap(),
                }
            } else if cmd.starts_with("pretty") {
                if cmd[6..].trim_left().starts_with("on") {
                    pretty = PrettyPrint::new("  ", "\n", " ");
                } else {
                    pretty = PrettyPrint::new("", "", "");
                }
            } else if cmd.starts_with("drop") {
                let dbname = cmd[4..].trim_left();
                match Index::drop(dbname) {
                    Ok(()) => (),
                    Err(reason) => write!(w, "{}\n", reason).unwrap(),
                }
            } else {
                write!(w, "Index isn't open\n").unwrap();
            }
        } else {
            break;
        }
    }
}

fn flush_batch(index: &mut Index, batch: &mut Batch, w: &mut Write) {
    let mut batch2 = Batch::new();
    mem::swap(batch, &mut batch2);
    if let Err(reason) = index.flush(batch2) {
        write!(w, "{}\n", reason).unwrap();
    }
}

fn repl_opened(mut index: Index,
               r: &mut BufRead,
               w: &mut Write,
               test_mode: bool,
               mut pretty: PrettyPrint) {
    let mut batch = Batch::new();
    let mut params = None;
    loop {
        let cmd = if let Some(cmd) = next_command(r, w, test_mode) {
            cmd
        } else {
            flush_batch(&mut index, &mut batch, w);
            return;
        };
        if cmd.starts_with("params") {
            params = Some(cmd[6..].trim_left().to_string());
        } else if cmd.starts_with("pretty") {
            if cmd[6..].trim_left().starts_with("on") {
                pretty = PrettyPrint::new("  ", "\n", " ");
            } else {
                pretty = PrettyPrint::new("", "", "");
            }
        } else if cmd.starts_with("create") {
            flush_batch(&mut index, &mut batch, w);
            let dbname = cmd[6..].trim_left();
            match Index::open(dbname, Some(OpenOptions::Create)) {
                Ok(index_new) => index = index_new,
                Err(reason) => write!(w, "{}\n", reason).unwrap(),
            }
        } else if cmd.starts_with("drop") {
            let dbname = cmd[4..].trim_left();
            match Index::drop(dbname) {
                Ok(()) => (),
                Err(reason) => write!(w, "{}\n", reason).unwrap(),
            }
        } else if cmd.starts_with("open") {
            let dbname = cmd[4..].trim_left();
            match Index::open(dbname, None) {
                Ok(index_new) => index = index_new,
                Err(reason) => write!(w, "{}\n", reason).unwrap(),
            }
        } else if cmd.starts_with("dumpkeys") {
            flush_batch(&mut index, &mut batch, w);
            match index.all_keys() {
                Ok(keys) => {
                    for key in keys {
                        write!(w, "{}\n", key).unwrap();
                    }
                }
                Err(reason) => {
                    write!(w, "{}\n", reason).unwrap();
                }
            }
        } else if cmd.starts_with("add") {
            match index.add(&cmd[3..], &mut batch) {
                Ok(id) => write!(w, "{}\n", JsonValue::str_to_literal(&id)).unwrap(),
                Err(reason) => write!(w, "{}\n", reason).unwrap(),
            }
        } else if cmd.starts_with("del") {
            match index.delete(&cmd[3..].trim_left(), &mut batch) {
                Ok(true) => write!(w, "ok\n").unwrap(),
                Ok(false) => write!(w, "not found\n").unwrap(),
                Err(reason) => write!(w, "{}\n", reason).unwrap(),
            }
        } else if cmd.starts_with("commit") {
            flush_batch(&mut index, &mut batch, w);
        } else if cmd.starts_with("find") {
            flush_batch(&mut index, &mut batch, w);
            match index.query(&cmd, params.take()) {
                Ok(results) => {
                    let mut results = results.peekable();

                    w.write_all(b"[").unwrap();
                    if results.peek().is_some() {
                        w.write_all(b"\n").unwrap();
                    }
                    pretty.push();
                    while let Some(json) = results.next() {
                        json.render(w, &mut pretty).unwrap();
                        if results.peek().is_some() {
                            w.write_all(b",").unwrap();
                        }
                        w.write_all(b"\n").unwrap();
                    }
                    w.write_all(b"]\n").unwrap();
                }
                Err(reason) => write!(w, "{}\n", reason).unwrap(),
            }
        }
    }
}<|endoftext|>


<commit_before>extern mod linenoise;

mod rush {
    extern mod linenoise;
    extern mod core;
    use core::task::spawn;
    use core::comm::{stream,Port,Chan,SharedChan};

    fn write_str(wr: io::Writer, s: &str) { str::byte_slice(s, |v| wr.write(v)) }

    fn exec_command(command: &~str) -> Port<~str> {
        let (strout,strin): (Port<~str>, Chan<~str>) = stream();
        let com = copy *command;
        do spawn {
            let command_split = str::split_char(str::trim(com), ' ');
            let prog = command_split.head();
            let args = command_split.tail();
            let mut prog = core::run::start_program(*prog, args);
            let rd = prog.output();
            let buf = io::with_bytes_writer(|wr| {
                let mut bytes = [0, ..4096];
                while !rd.eof() {
                    let nread = rd.read(bytes, bytes.len());
                    wr.write(bytes.view(0, nread));
                }
            });
            strin.send(str::from_bytes(buf));
        }
        strout
    }

    pub fn handle_input(line: &str) {
        linenoise::history_add(line);
        linenoise::history_save("history.txt");
        let commands = str::split_char(line, '|');
        let mut stdouts : ~[Port<~str>] = core::vec::map(commands, exec_command);
        for stdouts.each |stdout| {
            io::println(stdout.recv());
        }
    }

}

fn main() {
    linenoise::set_multiline(true);
    loop {
        let line = linenoise::init("rush: ");
        rush::handle_input(line);
    }
}
<commit_msg>Playing with tasks<commit_after>extern mod linenoise;

mod rush {
    extern mod linenoise;
    extern mod core;
    use core::task::spawn;
    use core::comm::{stream,Port,Chan,SharedChan};

    struct CommandIO {
        in: Chan<~str>,
        out: Port<~str>
    }

    fn write_str(wr: io::Writer, s: &str) {
        io::println("Writing str");
        io::println(s);
        str::byte_slice(s, |v| wr.write(v))
    }

    fn exec_command(command: &~str) -> CommandIO {
        let (stdout_output, stdout_input): (Port<~str>, Chan<~str>) = stream();
        let (stdin_output, stdin_input): (Port<~str>, Chan<~str>) = stream();
        let com = copy *command;

        do spawn {
            let command_split = str::split_char(str::trim(com), ' ');
            let prog = command_split.head();
            let args = command_split.tail();
            let mut prog = core::run::start_program(*prog, args);
            if stdin_output.peek() {
                write_str(prog.input(), stdin_output.recv());
            }
            let rd = prog.output();
            let buf = io::with_bytes_writer(|wr| {
                let mut bytes = [0, ..4096];
                while !rd.eof() {
                    let nread = rd.read(bytes, bytes.len());
                    wr.write(bytes.view(0, nread));
                }
            });
            stdout_input.send(str::from_bytes(buf));
        }
        CommandIO {in: stdin_input, out: stdout_output}
    }

    fn link_channels(prog1: &CommandIO, prog2: &CommandIO) {
        io::println("link1");
        if prog1.out.peek() {
            prog2.in.send(prog1.out.recv());
        }
        io::println("link2");
    }

    pub fn handle_input(line: &str) {
        linenoise::history_add(line);
        linenoise::history_save("history.txt");
        let commands = str::split_char(line, '|');
        let (strout, strin): (Port<~str>, Chan<~str>) = stream();
        let mut initial_io = CommandIO {in: strin, out: strout};
        let io_channels = vec::map(commands, exec_command);
        let last = io_channels.last();
        loop {
            io_channels.each(|&io| {
                link_channels(&initial_io, &io);
                initial_io = io;
                true
            });
            if last.out.peek() {
                io::println(last.out.recv());
            }
        }
    }

}

fn main() {
    linenoise::set_multiline(true);
    loop {
        let line = linenoise::init("rush: ");
        rush::handle_input(line);
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;

use serde_json::value::Value;

use priority::TaskPriority;

pub type DateTime= String; // FIXME
pub type Project = String;
pub type Status  = String;
pub type Tag     = String;
pub type UUID    = String; // FIXME
pub type Urgency = f64;

pub struct Task {
    id: u64,
    desc: String,
    entry: DateTime,
    modified: DateTime,
    priority: TaskPriority,
    project: Project,
    status: Status,
    tags: Vec<Tag>,
    uuid: UUID,
    urgency: Urgency,
}

/*
 * TODO: We do not fail if the JSON parsing fails. This panics. We rely on taskwarrior to be nice
 * to us. I guess this should be fixed.
 */
impl Task {

    pub fn from_value(v: Value) -> Option<Task> {
        if !v.is_object() {
            return None;
        }

        let map = v.as_object().unwrap();

        let keys = [ "id", "description", "modified", "priority", "project",
            "status", "tags", "uuid", "urgency"];

        if keys.iter().any(|x| map.contains_key(*x)) {
            return None
        }

        Some(Task {
            id       : get_id(&map),
            desc     : get_desc(&map),
            entry    : get_entry(&map),
            modified : get_modified(&map),
            priority : TaskPriority::from(get_priority(&map)),
            project  : get_project(&map),
            status   : get_status(&map),
            tags     : get_tags(&map),
            uuid     : get_uuid(&map),
            urgency  : get_urgency(&map),
        })
    }

}

fn get_id(map: &BTreeMap<String, Value>) -> u64 {
    map.get("id").unwrap().as_u64().unwrap()
}

fn get_desc(map: &BTreeMap<String, Value>) -> String {
    map.get("description").unwrap().as_string().map(String::from).unwrap()
}

fn get_entry(map: &BTreeMap<String, Value>) -> String {
    map.get("entry").unwrap().as_string().map(String::from).unwrap()
}

fn get_modified(map: &BTreeMap<String, Value>) -> String {
    map.get("modified").unwrap().as_string().map(String::from).unwrap()
}

fn get_priority(map: &BTreeMap<String, Value>) -> &str {
    map.get("priority").unwrap().as_string().unwrap()
}

fn get_project(map: &BTreeMap<String, Value>) -> String {
    map.get("project").unwrap().as_string().map(String::from).unwrap()
}

fn get_status(map: &BTreeMap<String, Value>) -> String {
    map.get("status").unwrap().as_string().map(String::from).unwrap()
}

fn get_tags(map: &BTreeMap<String, Value>) -> Vec<Tag> {
    map.get("tags")
        .unwrap()
        .as_array()
        .unwrap()
        .clone()
        .into_iter()
        .map(|item| item.as_string().map(String::from).unwrap())
        .collect()
}

fn get_uuid(map: &BTreeMap<String, Value>) -> String {
    map.get("uuid").unwrap().as_string().map(String::from).unwrap()
}

fn get_urgency(map: &BTreeMap<String, Value>) -> f64 {
    map.get("urgency").unwrap().as_f64().unwrap()
}

<commit_msg>Add Task::new()<commit_after>use std::collections::BTreeMap;

use serde_json::value::Value;

use priority::TaskPriority;

pub type DateTime= String; // FIXME
pub type Project = String;
pub type Status  = String;
pub type Tag     = String;
pub type UUID    = String; // FIXME
pub type Urgency = f64;

pub struct Task {
    id: u64,
    desc: String,
    entry: DateTime,
    modified: DateTime,
    priority: TaskPriority,
    project: Project,
    status: Status,
    tags: Vec<Tag>,
    uuid: UUID,
    urgency: Urgency,
}

/*
 * TODO: We do not fail if the JSON parsing fails. This panics. We rely on taskwarrior to be nice
 * to us. I guess this should be fixed.
 */
impl Task {

    pub fn new(id: u64, desc: String, entry: DateTime, modified: DateTime,
        priority: TaskPriority, project: Project, status: Status,
        tags: Vec<Tag>, uuid: UUID, urgency: Urgency)
        -> Task
    {
        Task {
            id       : id,
            desc     : desc,
            entry    : entry,
            modified : modified,
            priority : priority,
            project  : project,
            status   : status,
            tags     : tags,
            uuid     : uuid,
            urgency  : urgency,
        }
    }

    pub fn from_value(v: Value) -> Option<Task> {
        if !v.is_object() {
            return None;
        }

        let map = v.as_object().unwrap();

        let keys = [ "id", "description", "modified", "priority", "project",
            "status", "tags", "uuid", "urgency"];

        if keys.iter().any(|x| map.contains_key(*x)) {
            return None
        }

        Some(Task {
            id       : get_id(&map),
            desc     : get_desc(&map),
            entry    : get_entry(&map),
            modified : get_modified(&map),
            priority : TaskPriority::from(get_priority(&map)),
            project  : get_project(&map),
            status   : get_status(&map),
            tags     : get_tags(&map),
            uuid     : get_uuid(&map),
            urgency  : get_urgency(&map),
        })
    }

}

fn get_id(map: &BTreeMap<String, Value>) -> u64 {
    map.get("id").unwrap().as_u64().unwrap()
}

fn get_desc(map: &BTreeMap<String, Value>) -> String {
    map.get("description").unwrap().as_string().map(String::from).unwrap()
}

fn get_entry(map: &BTreeMap<String, Value>) -> String {
    map.get("entry").unwrap().as_string().map(String::from).unwrap()
}

fn get_modified(map: &BTreeMap<String, Value>) -> String {
    map.get("modified").unwrap().as_string().map(String::from).unwrap()
}

fn get_priority(map: &BTreeMap<String, Value>) -> &str {
    map.get("priority").unwrap().as_string().unwrap()
}

fn get_project(map: &BTreeMap<String, Value>) -> String {
    map.get("project").unwrap().as_string().map(String::from).unwrap()
}

fn get_status(map: &BTreeMap<String, Value>) -> String {
    map.get("status").unwrap().as_string().map(String::from).unwrap()
}

fn get_tags(map: &BTreeMap<String, Value>) -> Vec<Tag> {
    map.get("tags")
        .unwrap()
        .as_array()
        .unwrap()
        .clone()
        .into_iter()
        .map(|item| item.as_string().map(String::from).unwrap())
        .collect()
}

fn get_uuid(map: &BTreeMap<String, Value>) -> String {
    map.get("uuid").unwrap().as_string().map(String::from).unwrap()
}

fn get_urgency(map: &BTreeMap<String, Value>) -> f64 {
    map.get("urgency").unwrap().as_f64().unwrap()
}

<|endoftext|>


<commit_before>use super::*;
use context;

use std::env;
use std::fs;
use std::io::{BufReader, BufRead, Write};

fn assert_cursor_pos(s: &str, cursor: usize, expected_pos: CursorPosition) {
    let buf = Buffer::from(s.to_owned());
    let words = context::get_buffer_words(&buf);
    let pos = CursorPosition::get(cursor, &words[..]);
    assert!(expected_pos == pos,
            format!("buffer: {:?}, cursor: {}, expected pos: {:?}, pos: {:?}",
                    s,
                    cursor,
                    expected_pos,
                    pos));
}

#[test]
fn test_get_cursor_position() {
    use CursorPosition::*;

    let tests = &[("hi", 0, OnWordLeftEdge(0)),
                  ("hi", 1, InWord(0)),
                  ("hi", 2, OnWordRightEdge(0)),
                  ("abc  abc", 4, InSpace(Some(0), Some(1))),
                  ("abc  abc", 5, OnWordLeftEdge(1)),
                  ("abc  abc", 6, InWord(1)),
                  ("abc  abc", 8, OnWordRightEdge(1)),
                  (" a", 0, InSpace(None, Some(0))),
                  ("a ", 2, InSpace(Some(0), None))];

    for t in tests {
        assert_cursor_pos(t.0, t.1, t.2);
    }
}

fn assert_buffer_actions(start: &str, expected: &str, actions: &[Action]) {
    let mut buf = Buffer::from(start.to_owned());
    for a in actions {
        a.do_on(&mut buf);
    }

    assert_eq!(expected, String::from(buf));
}

#[test]
fn test_buffer_actions() {
    assert_buffer_actions("",
                          "h",
                          &[Action::Insert {
                                start: 0,
                                text: "hi".chars().collect(),
                            },
                            Action::Remove {
                                start: 1,
                                text: ".".chars().collect(),
                            }]);
}

#[test]
fn test_history_indexing() {
    let mut h = History::new();
    h.push(Buffer::from("a")).unwrap();
    h.push(Buffer::from("b")).unwrap();
    h.push(Buffer::from("c")).unwrap();
    assert_eq!(h.len(), 3);
    assert_eq!(String::from(h.buffers[0].clone()), "a".to_string());
    assert_eq!(String::from(h.buffers[1].clone()), "b".to_string());
    assert_eq!(String::from(h.buffers[2].clone()), "c".to_string());
}

#[test]
fn test_in_memory_history_truncating() {
    let mut h = History::new();
    h.set_max_size(2);
    for _ in 0..4 {
        h.push(Buffer::from("a")).unwrap();
    }
    assert_eq!(h.len(), 2);
}

#[test]
fn test_in_file_history_truncating() {
    let mut tmp_file = env::temp_dir();
    tmp_file.push("liner_test_file123.txt");

    {
        let mut h = History::new();
        h.set_file_name(String::from(tmp_file.to_string_lossy().into_owned()));
        h.set_max_file_size(5);
        for _ in 0..20 {
            h.push(Buffer::from("a")).unwrap();
        }
    }

    let f = fs::File::open(tmp_file.clone()).unwrap();
    let r = BufReader::new(f);
    let count = r.lines().count();
    assert_eq!(count, 5);

    fs::remove_file(tmp_file).unwrap();
}

static TEXT: &'static str = "a
b
c
d
";

#[test]
fn test_reading_from_file() {
    let mut tmp_file = env::temp_dir();
    tmp_file.push("liner_test_file456.txt");
    {
        let mut f = fs::OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(tmp_file.clone())
            .unwrap();
        f.write_all(TEXT.as_bytes()).unwrap();
    }
    let mut h = History::new();
    h.set_file_name(String::from(tmp_file.to_string_lossy().into_owned()));
    let _ = h.load_history();
    assert_eq!(String::from(h.buffers[0].clone()), "a".to_string());
    assert_eq!(String::from(h.buffers[1].clone()), "b".to_string());
    assert_eq!(String::from(h.buffers[2].clone()), "c".to_string());
    assert_eq!(String::from(h.buffers[3].clone()), "d".to_string());
}
<commit_msg>fix tests<commit_after>use super::*;
use context;

use std::env;
use std::fs;
use std::io::{BufReader, BufRead, Write};

fn assert_cursor_pos(s: &str, cursor: usize, expected_pos: CursorPosition) {
    let buf = Buffer::from(s.to_owned());
    let words = context::get_buffer_words(&buf);
    let pos = CursorPosition::get(cursor, &words[..]);
    assert!(expected_pos == pos,
            format!("buffer: {:?}, cursor: {}, expected pos: {:?}, pos: {:?}",
                    s,
                    cursor,
                    expected_pos,
                    pos));
}

#[test]
fn test_get_cursor_position() {
    use CursorPosition::*;

    let tests = &[("hi", 0, OnWordLeftEdge(0)),
                  ("hi", 1, InWord(0)),
                  ("hi", 2, OnWordRightEdge(0)),
                  ("abc  abc", 4, InSpace(Some(0), Some(1))),
                  ("abc  abc", 5, OnWordLeftEdge(1)),
                  ("abc  abc", 6, InWord(1)),
                  ("abc  abc", 8, OnWordRightEdge(1)),
                  (" a", 0, InSpace(None, Some(0))),
                  ("a ", 2, InSpace(Some(0), None))];

    for t in tests {
        assert_cursor_pos(t.0, t.1, t.2);
    }
}

fn assert_buffer_actions(start: &str, expected: &str, actions: &[Action]) {
    let mut buf = Buffer::from(start.to_owned());
    for a in actions {
        a.do_on(&mut buf);
    }

    assert_eq!(expected, String::from(buf));
}

#[test]
fn test_buffer_actions() {
    assert_buffer_actions("",
                          "h",
                          &[Action::Insert {
                                start: 0,
                                text: "hi".chars().collect(),
                            },
                            Action::Remove {
                                start: 1,
                                text: ".".chars().collect(),
                            }]);
}

#[test]
fn test_history_indexing() {
    let mut h = History::new();
    h.push(Buffer::from("a")).unwrap();
    h.push(Buffer::from("b")).unwrap();
    h.push(Buffer::from("c")).unwrap();
    assert_eq!(h.len(), 3);
    assert_eq!(String::from(h.buffers[0].clone()), "a".to_string());
    assert_eq!(String::from(h.buffers[1].clone()), "b".to_string());
    assert_eq!(String::from(h.buffers[2].clone()), "c".to_string());
}

#[test]
fn test_in_memory_history_truncating() {
    let mut h = History::new();
    h.set_max_size(2);
    for _ in 0..4 {
        h.push(Buffer::from("a")).unwrap();
    }
    assert_eq!(h.len(), 2);
}

#[test]
fn test_in_file_history_truncating() {
    let mut tmp_file = env::temp_dir();
    tmp_file.push("liner_test_file123.txt");

    {
        let mut h = History::new();
        h.set_file_name(Some(String::from(tmp_file.to_string_lossy().into_owned())));
        h.set_max_file_size(5);
        for _ in 0..20 {
            h.push(Buffer::from("a")).unwrap();
        }
    }

    let f = fs::File::open(tmp_file.clone()).unwrap();
    let r = BufReader::new(f);
    let count = r.lines().count();
    assert_eq!(count, 5);

    fs::remove_file(tmp_file).unwrap();
}

static TEXT: &'static str = "a
b
c
d
";

#[test]
fn test_reading_from_file() {
    let mut tmp_file = env::temp_dir();
    tmp_file.push("liner_test_file456.txt");
    {
        let mut f = fs::OpenOptions::new()
            .read(true)
            .write(true)
            .create(true)
            .open(tmp_file.clone())
            .unwrap();
        f.write_all(TEXT.as_bytes()).unwrap();
    }
    let mut h = History::new();
    h.set_file_name(Some(String::from(tmp_file.to_string_lossy().into_owned())));
    let _ = h.load_history();
    assert_eq!(String::from(h.buffers[0].clone()), "a".to_string());
    assert_eq!(String::from(h.buffers[1].clone()), "b".to_string());
    assert_eq!(String::from(h.buffers[2].clone()), "c".to_string());
    assert_eq!(String::from(h.buffers[3].clone()), "d".to_string());
}
<|endoftext|>


<commit_before>macro_rules! grammar {
    { for $grammar:ty { $($grammar_defn:tt)* } } => {
        impl $crate::Grammar for $grammar { }
        declare_nonterminals! { $grammar, $($grammar_defn)* }
    }
}

macro_rules! declare_nonterminals {
    ( $grammar:ty, $nonterminal:ident: $ty:ty = $defn:tt => $body:expr ;
      $($remainder:tt)* ) => {
        declare_map_nonterminal! { $grammar, $nonterminal, $ty, $defn, $body }
        declare_nonterminals! { $grammar, $($remainder)* }
    };
    ( $grammar:ty, $nonterminal:ident: $ty:ty = $defn:tt ;
      $($remainder:tt)* ) => {
        declare_identity_nonterminal! { $grammar, $nonterminal, $ty, $defn }
        declare_nonterminals! { $grammar, $($remainder)* }
    };
    ( $grammar:ty, ) => {
    };
}

macro_rules! declare_map_nonterminal {
    ($grammar:ty, $nonterminal:ident, $ty:ty, $defn:tt, $body:expr) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $nonterminal;

        impl $crate::Parser<$grammar> for $nonterminal {
            type Output = $ty;

            fn pretty_print(&self) -> String {
                format!("{:?}", self)
            }

            fn parse<'a>(&self,
                         grammar: &'a $grammar,
                         start: $crate::Input<'a>)
                         -> $crate::ParseResult<'a,$ty>
            {
                let parser = named_item!($defn);
                let (end, named_item_pat!($defn)) =
                    try!($crate::Parser::parse(&parser, grammar, start));
                Ok((end,$body))
            }
        }
    }
}

macro_rules! declare_identity_nonterminal {
    ($grammar:ty, $nonterminal:ident, $ty:ty, $defn:tt) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $nonterminal;

        impl $crate::Parser<$grammar> for $nonterminal {
            type Output = $ty;

            fn pretty_print(&self) -> String {
                format!("{:?}", self)
            }

            fn parse<'a>(&self,
                         grammar: &'a $grammar,
                         start: $crate::Input<'a>)
                         -> $crate::ParseResult<'a,$ty> {
                             let parser = item!($defn);
                             $crate::Parser::parse(&parser, grammar, start)
                         }
        }
    }
}

macro_rules! named_item {
    ( ( $($a:tt)* ) ) => {
        named_items!($($a)*)
    };
    ( $a:tt ) => {
        item!($a)
    }
}

macro_rules! named_items {
    ( < $name:ident : $a:tt > , $($bs:tt)* ) => {
        {
            let bs = named_items!($($bs)*);
            items!($a, bs)
        }
    };
    ( < $name:ident : $a:tt > ) => {
        item!($a)
    };
    ( $a:tt, $($bs:tt)* ) => {
        {
            let bs = named_items!($($bs)*);
            items!($a, bs)
        }
    };
    ( $a:tt ) => {
        item!($a)
    };
    ( ) => {
        Empty
    };
}

macro_rules! named_item_pat {
    ( ( $($a:tt)* ) ) => {
        named_items_pat!($($a)*)
    };
    ( $a:tt ) => {
        _
    }
}

macro_rules! named_items_pat {
    ( < $name:ident : $a:tt > , $($bs:tt)* ) => {
        ($name, named_items_pat!($($bs)*))
    };
    ( < $name:ident : $a:tt > ) => {
        $name
    };
    ( $a:tt, $($bs:tt)* ) => {
        (_, named_items_pat!($($bs)*))
    };
    ( $a:tt ) => {
        _
    };
    ( ) => {
        ()
    };
}

macro_rules! items {
    ( $a:tt, $($bs:tt)* ) => {
        $crate::util::Join { first: item!($a), second: items!($($bs)*), }
    };
    ( $a:tt | $($bs:tt)* ) => {
        $crate::util::Or { a: item!($a), b: items!($($bs)*) }
    };
    ( $a:tt ) => {
        item!($a)
    };
    ( ) => {
        Empty
    }
}

macro_rules! item {
    { ( ) } => {
        Empty
    };

    { ( $tt:tt ) } => {
        item!($tt)
    };

    { ( $($tt:tt)* ) } => {
        items!($($tt)*)
    };

    { [ $($tt:tt)* ] } => {
        $crate::util::Optional { parser: items!($($tt)*) }
    };

    { { + $($tt:tt)* } } => {
        $crate::util::Repeat { parser: items!($($tt)*), min: 1,
                               separator: $crate::util::Whitespace }
    };

    { { * $($tt:tt)* } } => {
        $crate::util::Repeat { parser: items!($($tt)*), min: 0,
                               separator: $crate::util::Whitespace }
    };

    { { $($tt:tt)* } } => {
        $crate::util::Repeat { parser: items!($($tt)*), min: 0,
                               separator: $crate::util::Whitespace }
    };

    { $name:expr } => {
        $name
    };
}

mod silly_grammar {
    pub struct Foo;

    grammar! {
        for Foo {
            Hi: u32 = ("Hi") => 1;
            Ho: u32 = "Ho" => 2;

            HiOrHo: u32 = (Hi|Ho);

            Sum: u32 = (Sum1 | HiOrHo);
            Sum1: u32 = (<x:HiOrHo>, "+", <y:Sum>) => {x + y*10};

            HiHo: () = (Hi, Ho) => ();

            Rep: Vec<u32> = {HiOrHo};
        }
    }

    fn should_parse_prefix<G,P:?Sized>(grammar: &G,
                                       parser: &P,
                                       text: &str)
                                       -> P::Output
        where G: ::Grammar, P: ::Parser<G>
    {
        parser.parse_prefix(grammar, text).unwrap().1
    }

    #[test]
    fn parse_hi_from_hi() {
        assert_eq!(1, should_parse_prefix(&Foo, &Hi, "Hi"));
    }

    #[test]
    #[should_panic]
    fn parse_hi_from_ho() {
        assert_eq!(2, should_parse_prefix(&Foo, &Hi, "Ho"));
    }

    #[test]
    fn parse_hiorho_from_hi() {
        assert_eq!(1, should_parse_prefix(&Foo, &HiOrHo, "Hi"));
    }

    #[test]
    fn parse_hiorho_from_ho() {
        assert_eq!(2, should_parse_prefix(&Foo, &HiOrHo, "Ho"));
    }

    #[test]
    fn parse_hiho_from_ho() {
        assert_eq!((), should_parse_prefix(&Foo, &HiHo, "Hi Ho"));
    }

    #[test]
    fn parse_sum_from_ho() {
        assert_eq!(1221, should_parse_prefix(&Foo, &Sum, "Hi + Ho + Ho + Hi"));
    }

    #[test]
    fn parse_repeat() {
        assert_eq!(vec![1, 2, 2, 1, 2], should_parse_prefix(&Foo, &Rep, "Hi Ho Ho Hi Ho"));
    }
}

mod classy {
    use regex::Regex;
    use std::collections::HashSet;
    use Parser;

    #[derive(Debug)]
    pub struct ClassDefn {
        name: String,
        members: Vec<MemberDefn>
    }

    #[derive(Debug)]
    pub enum MemberDefn {
        Field(Box<FieldDefn>),
        Method(Box<MethodDefn>),
    }

    #[derive(Debug)]
    pub struct FieldDefn {
        name: String,
        ty: TypeRef
    }

    #[derive(Debug)]
    pub struct MethodDefn {
        name: String,
        arg_tys: Vec<TypeRef>,
        ret_ty: TypeRef
    }

    #[derive(Debug)]
    pub struct TypeRef {
        id: String
    }

    #[derive(Debug)]
    pub struct Classy {
        identifier: Regex,
        keywords: HashSet<String>,
    }

    impl Classy {
        fn new() -> Classy {
            Classy {
                identifier: Regex::new("^[a-zA-Z_][a-zA-Z_0-9]*").unwrap(),
                keywords: vec!["class"].into_iter().map(|x| x.to_string()).collect(),
            }
        }
    }

    #[allow(non_camel_case_types)]
    #[derive(Debug)]
    struct ID;

    impl Parser<Classy> for ID {
        type Output = String;

        fn pretty_print(&self) -> String {
            format!("{:?}", self)
        }

        fn parse<'a>(&self,
                     grammar: &'a Classy,
                     start: ::Input<'a>)
                     -> ::ParseResult<'a,String>
        {
            match grammar.identifier.find(&start.text[start.offset..]) {
                Some((_, offset)) => {
                    let end = start.offset_by(offset);
                    let matched = &start.text[start.offset..end.offset];
                    if !grammar.keywords.contains(matched) {
                        return Ok((end, matched.to_string()));
                    }
                }
                None => { }
            }

            Err(::Error { expected: "identifier", offset: start.offset })
        }
    }

    grammar! {
        for Classy {
            CLASS: ClassDefn =
                ("class", <name:ID>, "{", <members:{MEMBER}>, "}") => {
                    ClassDefn { name: name, members: members }
                };

            MEMBER: MemberDefn =
                (FIELD_DEFN | METHOD_DEFN);

            FIELD_DEFN: MemberDefn =
                (<name:ID>, ":", <ty:TYPE_REF>, ";") => {
                    MemberDefn::Field(Box::new(
                        FieldDefn { name: name, ty: ty }))
                };

            TYPE_REF: TypeRef =
                (<id:ID>) => {
                    TypeRef { id: id }
                };

            METHOD_DEFN: MemberDefn =
                (<name:ID>, "(", <args:{TYPE_REF}>, ")", "->", <ret:TYPE_REF>, ";") => {
                    MemberDefn::Method(Box::new(
                        MethodDefn { name: name, arg_tys: args, ret_ty: ret }))
                };
        }
    }

    #[test]
    fn parse_a_class() {
        let classy = Classy::new();
        CLASS.parse_prefix(
            &classy,
            "class x { f: u32; g: i32; h(i32) -> u32; }").unwrap();
    }
}

<commit_msg>Rename the macros<commit_after>macro_rules! rusty_peg_grammar {
    { for $grammar:ty { $($grammar_defn:tt)* } } => {
        impl $crate::Grammar for $grammar { }
        rusty_peg_declare_nonterminals! { $grammar, $($grammar_defn)* }
    }
}

macro_rules! rusty_peg_declare_nonterminals {
    ( $grammar:ty, $nonterminal:ident: $ty:ty = $defn:tt => $body:expr ;
      $($remainder:tt)* ) => {
        rusty_peg_declare_map_nonterminal! { $grammar, $nonterminal, $ty, $defn, $body }
        rusty_peg_declare_nonterminals! { $grammar, $($remainder)* }
    };
    ( $grammar:ty, $nonterminal:ident: $ty:ty = $defn:tt ;
      $($remainder:tt)* ) => {
        rusty_peg_declare_identity_nonterminal! { $grammar, $nonterminal, $ty, $defn }
        rusty_peg_declare_nonterminals! { $grammar, $($remainder)* }
    };
    ( $grammar:ty, ) => {
    };
}

macro_rules! rusty_peg_declare_map_nonterminal {
    ($grammar:ty, $nonterminal:ident, $ty:ty, $defn:tt, $body:expr) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $nonterminal;

        impl $crate::Parser<$grammar> for $nonterminal {
            type Output = $ty;

            fn pretty_print(&self) -> String {
                format!("{:?}", self)
            }

            fn parse<'a>(&self,
                         grammar: &'a $grammar,
                         start: $crate::Input<'a>)
                         -> $crate::ParseResult<'a,$ty>
            {
                let parser = rusty_peg_named_item!($defn);
                let (end, rusty_peg_named_item_pat!($defn)) =
                    try!($crate::Parser::parse(&parser, grammar, start));
                Ok((end,$body))
            }
        }
    }
}

macro_rules! rusty_peg_declare_identity_nonterminal {
    ($grammar:ty, $nonterminal:ident, $ty:ty, $defn:tt) => {
        #[allow(non_camel_case_types)]
        #[derive(Debug)]
        pub struct $nonterminal;

        impl $crate::Parser<$grammar> for $nonterminal {
            type Output = $ty;

            fn pretty_print(&self) -> String {
                format!("{:?}", self)
            }

            fn parse<'a>(&self,
                         grammar: &'a $grammar,
                         start: $crate::Input<'a>)
                         -> $crate::ParseResult<'a,$ty> {
                             let parser = rusty_peg_item!($defn);
                             $crate::Parser::parse(&parser, grammar, start)
                         }
        }
    }
}

macro_rules! rusty_peg_named_item {
    ( ( $($a:tt)* ) ) => {
        rusty_peg_named_items!($($a)*)
    };
    ( $a:tt ) => {
        rusty_peg_item!($a)
    }
}

macro_rules! rusty_peg_named_items {
    ( < $name:ident : $a:tt > , $($bs:tt)* ) => {
        {
            let bs = rusty_peg_named_items!($($bs)*);
            rusty_peg_items!($a, bs)
        }
    };
    ( < $name:ident : $a:tt > ) => {
        rusty_peg_item!($a)
    };
    ( $a:tt, $($bs:tt)* ) => {
        {
            let bs = rusty_peg_named_items!($($bs)*);
            rusty_peg_items!($a, bs)
        }
    };
    ( $a:tt ) => {
        rusty_peg_item!($a)
    };
    ( ) => {
        Empty
    };
}

macro_rules! rusty_peg_named_item_pat {
    ( ( $($a:tt)* ) ) => {
        rusty_peg_named_items_pat!($($a)*)
    };
    ( $a:tt ) => {
        _
    }
}

macro_rules! rusty_peg_named_items_pat {
    ( < $name:ident : $a:tt > , $($bs:tt)* ) => {
        ($name, rusty_peg_named_items_pat!($($bs)*))
    };
    ( < $name:ident : $a:tt > ) => {
        $name
    };
    ( $a:tt, $($bs:tt)* ) => {
        (_, rusty_peg_named_items_pat!($($bs)*))
    };
    ( $a:tt ) => {
        _
    };
    ( ) => {
        ()
    };
}

macro_rules! rusty_peg_items {
    ( $a:tt, $($bs:tt)* ) => {
        $crate::util::Join { first: rusty_peg_item!($a), second: rusty_peg_items!($($bs)*), }
    };
    ( $a:tt | $($bs:tt)* ) => {
        $crate::util::Or { a: rusty_peg_item!($a), b: rusty_peg_items!($($bs)*) }
    };
    ( $a:tt ) => {
        rusty_peg_item!($a)
    };
    ( ) => {
        Empty
    }
}

macro_rules! rusty_peg_item {
    { ( ) } => {
        Empty
    };

    { ( $tt:tt ) } => {
        rusty_peg_item!($tt)
    };

    { ( $($tt:tt)* ) } => {
        rusty_peg_items!($($tt)*)
    };

    { [ $($tt:tt)* ] } => {
        $crate::util::Optional { parser: rusty_peg_items!($($tt)*) }
    };

    { { + $($tt:tt)* } } => {
        $crate::util::Repeat { parser: rusty_peg_items!($($tt)*), min: 1,
                               separator: $crate::util::Whitespace }
    };

    { { * $($tt:tt)* } } => {
        $crate::util::Repeat { parser: rusty_peg_items!($($tt)*), min: 0,
                               separator: $crate::util::Whitespace }
    };

    { { $($tt:tt)* } } => {
        $crate::util::Repeat { parser: rusty_peg_items!($($tt)*), min: 0,
                               separator: $crate::util::Whitespace }
    };

    { $name:expr } => {
        $name
    };
}

mod silly_grammar {
    pub struct Foo;

    rusty_peg_grammar! {
        for Foo {
            Hi: u32 = ("Hi") => 1;
            Ho: u32 = "Ho" => 2;

            HiOrHo: u32 = (Hi|Ho);

            Sum: u32 = (Sum1 | HiOrHo);
            Sum1: u32 = (<x:HiOrHo>, "+", <y:Sum>) => {x + y*10};

            HiHo: () = (Hi, Ho) => ();

            Rep: Vec<u32> = {HiOrHo};
        }
    }

    fn should_parse_prefix<G,P:?Sized>(grammar: &G,
                                       parser: &P,
                                       text: &str)
                                       -> P::Output
        where G: ::Grammar, P: ::Parser<G>
    {
        parser.parse_prefix(grammar, text).unwrap().1
    }

    #[test]
    fn parse_hi_from_hi() {
        assert_eq!(1, should_parse_prefix(&Foo, &Hi, "Hi"));
    }

    #[test]
    #[should_panic]
    fn parse_hi_from_ho() {
        assert_eq!(2, should_parse_prefix(&Foo, &Hi, "Ho"));
    }

    #[test]
    fn parse_hiorho_from_hi() {
        assert_eq!(1, should_parse_prefix(&Foo, &HiOrHo, "Hi"));
    }

    #[test]
    fn parse_hiorho_from_ho() {
        assert_eq!(2, should_parse_prefix(&Foo, &HiOrHo, "Ho"));
    }

    #[test]
    fn parse_hiho_from_ho() {
        assert_eq!((), should_parse_prefix(&Foo, &HiHo, "Hi Ho"));
    }

    #[test]
    fn parse_sum_from_ho() {
        assert_eq!(1221, should_parse_prefix(&Foo, &Sum, "Hi + Ho + Ho + Hi"));
    }

    #[test]
    fn parse_repeat() {
        assert_eq!(vec![1, 2, 2, 1, 2], should_parse_prefix(&Foo, &Rep, "Hi Ho Ho Hi Ho"));
    }
}

mod classy {
    use regex::Regex;
    use std::collections::HashSet;
    use Parser;

    #[derive(Debug)]
    pub struct ClassDefn {
        name: String,
        members: Vec<MemberDefn>
    }

    #[derive(Debug)]
    pub enum MemberDefn {
        Field(Box<FieldDefn>),
        Method(Box<MethodDefn>),
    }

    #[derive(Debug)]
    pub struct FieldDefn {
        name: String,
        ty: TypeRef
    }

    #[derive(Debug)]
    pub struct MethodDefn {
        name: String,
        arg_tys: Vec<TypeRef>,
        ret_ty: TypeRef
    }

    #[derive(Debug)]
    pub struct TypeRef {
        id: String
    }

    #[derive(Debug)]
    pub struct Classy {
        identifier: Regex,
        keywords: HashSet<String>,
    }

    impl Classy {
        fn new() -> Classy {
            Classy {
                identifier: Regex::new("^[a-zA-Z_][a-zA-Z_0-9]*").unwrap(),
                keywords: vec!["class"].into_iter().map(|x| x.to_string()).collect(),
            }
        }
    }

    #[allow(non_camel_case_types)]
    #[derive(Debug)]
    struct ID;

    impl Parser<Classy> for ID {
        type Output = String;

        fn pretty_print(&self) -> String {
            format!("{:?}", self)
        }

        fn parse<'a>(&self,
                     grammar: &'a Classy,
                     start: ::Input<'a>)
                     -> ::ParseResult<'a,String>
        {
            match grammar.identifier.find(&start.text[start.offset..]) {
                Some((_, offset)) => {
                    let end = start.offset_by(offset);
                    let matched = &start.text[start.offset..end.offset];
                    if !grammar.keywords.contains(matched) {
                        return Ok((end, matched.to_string()));
                    }
                }
                None => { }
            }

            Err(::Error { expected: "identifier", offset: start.offset })
        }
    }

    rusty_peg_grammar! {
        for Classy {
            CLASS: ClassDefn =
                ("class", <name:ID>, "{", <members:{MEMBER}>, "}") => {
                    ClassDefn { name: name, members: members }
                };

            MEMBER: MemberDefn =
                (FIELD_DEFN | METHOD_DEFN);

            FIELD_DEFN: MemberDefn =
                (<name:ID>, ":", <ty:TYPE_REF>, ";") => {
                    MemberDefn::Field(Box::new(
                        FieldDefn { name: name, ty: ty }))
                };

            TYPE_REF: TypeRef =
                (<id:ID>) => {
                    TypeRef { id: id }
                };

            METHOD_DEFN: MemberDefn =
                (<name:ID>, "(", <args:{TYPE_REF}>, ")", "->", <ret:TYPE_REF>, ";") => {
                    MemberDefn::Method(Box::new(
                        MethodDefn { name: name, arg_tys: args, ret_ty: ret }))
                };
        }
    }

    #[test]
    fn parse_a_class() {
        let classy = Classy::new();
        let (_, result) =
            CLASS.parse_prefix(
                &classy,
                "class x { f: u32; g: i32; h(i32) -> u32; }").unwrap();

        assert_eq!(
            normalize_space(&format!("{:#?}", result)),
            normalize_space("ClassDefn {
                name: \"x\",
                members: [
                    Field(
                        FieldDefn {
                            name: \"f\",
                            ty: TypeRef {
                                id: \"u32\"
                            }
                        }
                        ),
                    Field(
                        FieldDefn {
                            name: \"g\",
                            ty: TypeRef {
                                id: \"i32\"
                            }
                        }
                        ),
                    Method(
                        MethodDefn {
                            name: \"h\",
                            arg_tys: [
                                TypeRef {
                                    id: \"i32\"
                                }
                                ],
                            ret_ty: TypeRef {
                                id: \"u32\"
                            }
                        }
                        )
                    ]
            }"));
    }

    fn normalize_space(text: &str) {
        Regex::new(r"\s+").unwrap().replace_all(text, " ");
    }
}

<|endoftext|>


<commit_before>extern crate sync;

use std::os::args;
use std::path::Path;

#[allow(dead_code)]
mod gdal;

fn main() {
    let memory_driver = gdal::get_driver("MEM").unwrap();

    let source = gdal::open(&Path::new(args()[1])).unwrap();
    println!(
        "size: {}, bands: {}",
        source.get_raster_size(),
        source.get_raster_count()
    );

    let tile = memory_driver.create("", 256, 256, 3).unwrap();
    println!("tile size: {}", tile.get_raster_size());
}
<commit_msg>take a tile from the raster image<commit_after>extern crate sync;

use std::os::args;
use std::path::Path;
use std::io::{File, TempDir, stdio};

#[allow(dead_code)]
mod gdal;

fn main() {
    let memory_driver = gdal::get_driver("MEM").unwrap();
    let png_driver = gdal::get_driver("PNG").unwrap();

    let source = gdal::open(&Path::new(args()[1])).unwrap();
    println!(
        "size: {}, bands: {}",
        source.get_raster_size(),
        source.get_raster_count()
    );

    let tile = memory_driver.create("", 256, 256, 3).unwrap();
    for band in range(1, 4) {
        let raster = source.read_raster(band, 10000, 1600, 3000, 2000, 256, 256);
        tile.write_raster(band, 0, 0, 256, 256, raster);
    }

    let tmp = TempDir::new("rustile").unwrap();
    let tile_path = tmp.path().join("tile.png");
    tile.create_copy(png_driver, tile_path.as_str().unwrap());
    let tile_data = File::open(&tile_path).read_to_end().unwrap();
    assert!(stdio::stdout_raw().write(tile_data).is_ok());
}
<|endoftext|>