<commit_before>//! Test runner.
//!
//! This module implements the `TestRunner` struct which manages executing tests as well as
//! scanning directories for tests.

use std::error::Error;
use std::ffi::OsStr;
use std::mem;
use std::panic::catch_unwind;
use std::path::{Path, PathBuf};
use filetest::{TestResult, runone};
use CommandResult;

#[derive(PartialEq, Eq, Debug)]
enum QueueEntry {
    New(PathBuf),
    Running,
    Done(PathBuf, TestResult),
}

pub struct TestRunner {
    // Directories that have not yet been scanned.
    dir_stack: Vec<PathBuf>,

    // Filenames of tests to run.
    tests: Vec<QueueEntry>,

    // Pointer into `tests` where the `New` entries begin.
    new_tests: usize,

    // Number of contiguous finished tests at the front of `tests`.
    finished_tests: usize,

    errors: usize,
}

impl TestRunner {
    /// Create a new blank TrstRunner.
    pub fn new() -> TestRunner {
        TestRunner {
            dir_stack: Vec::new(),
            tests: Vec::new(),
            new_tests: 0,
            finished_tests: 0,
            errors: 0,
        }
    }

    /// Add a directory path to be scanned later.
    ///
    /// If `dir` turns out to be a regular file, it is silently ignored.
    /// Otherwise, any problems reading the directory are reported.
    pub fn push_dir<P: Into<PathBuf>>(&mut self, dir: P) {
        self.dir_stack.push(dir.into());
    }

    /// Add a test to be executed later.
    ///
    /// Any problems reading `file` as a test case file will be reported as a test failure.
    pub fn push_test<P: Into<PathBuf>>(&mut self, file: P) {
        self.tests.push(QueueEntry::New(file.into()));
    }

    /// Take a new test for running as a job.
    /// Leaves the queue entry marked as `Runnning`.
    fn take_job(&mut self) -> Option<Job> {
        let index = self.new_tests;
        if index == self.tests.len() {
            return None;
        }
        self.new_tests += 1;

        let entry = mem::replace(&mut self.tests[index], QueueEntry::Running);
        if let QueueEntry::New(path) = entry {
            Some(Job::new(index, path))
        } else {
            // Oh, sorry about that. Put the entry back.
            self.tests[index] = entry;
            None
        }
    }

    /// Report the end of a job.
    fn finish_job(&mut self, job: Job, result: TestResult) {
        assert_eq!(self.tests[job.index], QueueEntry::Running);
        if let Err(ref e) = result {
            self.job_error(&job.path, e);
        }
        self.tests[job.index] = QueueEntry::Done(job.path, result);
        if job.index == self.finished_tests {
            while let Some(&QueueEntry::Done(_, _)) = self.tests.get(self.finished_tests) {
                self.finished_tests += 1;
            }
        }
    }

    /// Scan any directories pushed so far.
    /// Push any potential test cases found.
    pub fn scan_dirs(&mut self) {
        // This recursive search tries to minimize statting in a directory hierarchy containing
        // mostly test cases.
        //
        // - Directory entries with a "cton" extension are presumed to be test case files.
        // - Directory entries with no extension are presumed to be subdirectories.
        // - Anything else is ignored.
        //
        while let Some(dir) = self.dir_stack.pop() {
            match dir.read_dir() {
                Err(err) => {
                    // Fail silently if `dir` was actually a regular file.
                    // This lets us skip spurious extensionless files without statting everything
                    // needlessly.
                    if !dir.is_file() {
                        self.path_error(dir, err);
                    }
                }
                Ok(entries) => {
                    // Read all directory entries. Avoid statting.
                    for entry_result in entries {
                        match entry_result {
                            Err(err) => {
                                // Not sure why this would happen. `read_dir` succeeds, but there's
                                // a problem with an entry. I/O error during a getdirentries
                                // syscall seems to be the reason. The implementation in
                                // libstd/sys/unix/fs.rs seems to suggest that breaking now would
                                // be a good idea, or the iterator could keep returning the same
                                // error forever.
                                self.path_error(dir, err);
                                break;
                            }
                            Ok(entry) => {
                                let path = entry.path();
                                // Recognize directories and tests by extension.
                                // Yes, this means we ignore directories with '.' in their name.
                                match path.extension().and_then(OsStr::to_str) {
                                    Some("cton") => self.push_test(path),
                                    Some(_) => {}
                                    None => self.push_dir(path),
                                }
                            }
                        }
                    }
                }
            }
            // Get the new jobs running before moving on to the next directory.
            self.schedule_jobs();
        }
    }

    /// Report an error related to a path.
    fn path_error<E: Error>(&mut self, path: PathBuf, err: E) {
        self.errors += 1;
        println!("{}: {}", path.to_string_lossy(), err);
    }

    /// Report an error related to a job.
    fn job_error(&mut self, path: &Path, err: &str) {
        self.errors += 1;
        println!("FAIL {}: {}", path.to_string_lossy(), err);
    }

    /// Schedule and new jobs to run.
    fn schedule_jobs(&mut self) {
        while let Some(job) = self.take_job() {
            let result = job.run();
            self.finish_job(job, result);
        }
    }

    /// Scan pushed directories for tests and run them.
    pub fn run(&mut self) -> CommandResult {
        self.scan_dirs();
        self.schedule_jobs();
        println!("{} tests", self.tests.len());
        match self.errors {
            0 => Ok(()),
            1 => Err("1 failure".to_string()),
            n => Err(format!("{} failures", n)),
        }
    }
}

/// A test file waiting to be run.
struct Job {
    index: usize,
    path: PathBuf,
}

impl Job {
    pub fn new(index: usize, path: PathBuf) -> Job {
        Job {
            index: index,
            path: path,
        }
    }

    pub fn run(&self) -> TestResult {
        match catch_unwind(|| runone::run(self.path.as_path())) {
            Err(msg) => Err(format!("panic: {:?}", msg)),
            Ok(result) => result,
        }
    }
}
<commit_msg>Simplify job queue.<commit_after>//! Test runner.
//!
//! This module implements the `TestRunner` struct which manages executing tests as well as
//! scanning directories for tests.

use std::error::Error;
use std::ffi::OsStr;
use std::path::{Path, PathBuf};
use filetest::{TestResult, runone};
use CommandResult;

struct QueueEntry {
    path: PathBuf,
    state: State,
}

#[derive(PartialEq, Eq, Debug)]
enum State {
    New,
    Running,
    Done(TestResult),
}

impl QueueEntry {
    pub fn path(&self) -> &Path {
        self.path.as_path()
    }
}

pub struct TestRunner {
    // Directories that have not yet been scanned.
    dir_stack: Vec<PathBuf>,

    // Filenames of tests to run.
    tests: Vec<QueueEntry>,

    // Pointer into `tests` where the `New` entries begin.
    new_tests: usize,

    // Number of contiguous finished tests at the front of `tests`.
    finished_tests: usize,

    errors: usize,
}

impl TestRunner {
    /// Create a new blank TrstRunner.
    pub fn new() -> TestRunner {
        TestRunner {
            dir_stack: Vec::new(),
            tests: Vec::new(),
            new_tests: 0,
            finished_tests: 0,
            errors: 0,
        }
    }

    /// Add a directory path to be scanned later.
    ///
    /// If `dir` turns out to be a regular file, it is silently ignored.
    /// Otherwise, any problems reading the directory are reported.
    pub fn push_dir<P: Into<PathBuf>>(&mut self, dir: P) {
        self.dir_stack.push(dir.into());
    }

    /// Add a test to be executed later.
    ///
    /// Any problems reading `file` as a test case file will be reported as a test failure.
    pub fn push_test<P: Into<PathBuf>>(&mut self, file: P) {
        self.tests.push(QueueEntry {
            path: file.into(),
            state: State::New,
        });
    }

    /// Take a new test for running as a job.
    /// Leaves the queue entry marked as `Runnning`.
    fn take_job(&mut self) -> Option<usize> {
        let jobid = self.new_tests;
        if jobid == self.tests.len() {
            return None;
        }
        self.new_tests += 1;
        assert_eq!(self.tests[jobid].state, State::New);
        self.tests[jobid].state = State::Running;
        Some(jobid)
    }

    /// Report the end of a job.
    fn finish_job(&mut self, jobid: usize, result: TestResult) {
        assert_eq!(self.tests[jobid].state, State::Running);
        if let Err(ref e) = result {
            self.job_error(jobid, e);
        }
        self.tests[jobid].state = State::Done(result);
        if jobid == self.finished_tests {
            while let Some(&QueueEntry { state: State::Done(_), .. }) = self.tests
                .get(self.finished_tests) {
                self.finished_tests += 1;
            }
        }
    }

    /// Scan any directories pushed so far.
    /// Push any potential test cases found.
    pub fn scan_dirs(&mut self) {
        // This recursive search tries to minimize statting in a directory hierarchy containing
        // mostly test cases.
        //
        // - Directory entries with a "cton" extension are presumed to be test case files.
        // - Directory entries with no extension are presumed to be subdirectories.
        // - Anything else is ignored.
        //
        while let Some(dir) = self.dir_stack.pop() {
            match dir.read_dir() {
                Err(err) => {
                    // Fail silently if `dir` was actually a regular file.
                    // This lets us skip spurious extensionless files without statting everything
                    // needlessly.
                    if !dir.is_file() {
                        self.path_error(dir, err);
                    }
                }
                Ok(entries) => {
                    // Read all directory entries. Avoid statting.
                    for entry_result in entries {
                        match entry_result {
                            Err(err) => {
                                // Not sure why this would happen. `read_dir` succeeds, but there's
                                // a problem with an entry. I/O error during a getdirentries
                                // syscall seems to be the reason. The implementation in
                                // libstd/sys/unix/fs.rs seems to suggest that breaking now would
                                // be a good idea, or the iterator could keep returning the same
                                // error forever.
                                self.path_error(dir, err);
                                break;
                            }
                            Ok(entry) => {
                                let path = entry.path();
                                // Recognize directories and tests by extension.
                                // Yes, this means we ignore directories with '.' in their name.
                                match path.extension().and_then(OsStr::to_str) {
                                    Some("cton") => self.push_test(path),
                                    Some(_) => {}
                                    None => self.push_dir(path),
                                }
                            }
                        }
                    }
                }
            }
            // Get the new jobs running before moving on to the next directory.
            self.schedule_jobs();
        }
    }

    /// Report an error related to a path.
    fn path_error<E: Error>(&mut self, path: PathBuf, err: E) {
        self.errors += 1;
        println!("{}: {}", path.to_string_lossy(), err);
    }

    /// Report an error related to a job.
    fn job_error(&mut self, jobid: usize, err: &str) {
        self.errors += 1;
        println!("FAIL {}: {}", self.tests[jobid].path.to_string_lossy(), err);
    }

    /// Schedule and new jobs to run.
    fn schedule_jobs(&mut self) {
        while let Some(jobid) = self.take_job() {
            let result = runone::run(self.tests[jobid].path());
            self.finish_job(jobid, result);
        }
    }

    /// Scan pushed directories for tests and run them.
    pub fn run(&mut self) -> CommandResult {
        self.scan_dirs();
        self.schedule_jobs();
        println!("{} tests", self.tests.len());
        match self.errors {
            0 => Ok(()),
            1 => Err("1 failure".to_string()),
            n => Err(format!("{} failures", n)),
        }
    }
}
<|endoftext|>


<commit_before>use decoders::*;
use decoders::tiff::*;
use decoders::ljpeg::*;
use std::f32::NAN;
use std::cmp;
use itertools::Itertools;

#[derive(Debug, Clone)]
pub struct Cr2Decoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> Cr2Decoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> Cr2Decoder<'a> {
    Cr2Decoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for Cr2Decoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let raw = fetch_ifd!(&self.tiff, Tag::Cr2Id);
    let offset = fetch_tag!(raw, Tag::StripOffsets).get_usize(0);
    let src = &self.buffer[offset..];

    let (width, height, image) = {
      let decompressor = try!(LjpegDecompressor::new(src, true));
      let width = decompressor.width();
      let height = decompressor.height();
      let mut ljpegout = vec![0 as u16; width*height];
      try!(decompressor.decode(&mut ljpegout, 0, width, width, height));

      // Take each of the vertical fields and put them into the right location
      // FIXME: Doing this at the decode would reduce about 10% in runtime but I haven't
      //        been able to do it without hairy code
      let mut out = vec![0 as u16; width*height];
      let canoncol = fetch_tag!(raw, Tag::Cr2StripeWidths).get_usize(1);
      for (field, fieldstart) in (0..width).step(canoncol).enumerate() {
        let fieldwidth = cmp::min((field+1)*canoncol,width) - field*canoncol;
        let fieldpos = field*canoncol*height;
        for row in 0..height {
          for col in 0..fieldwidth {
            out[row*width+fieldstart+col] = ljpegout[fieldpos+row*fieldwidth+col];
          }
        }
      }

      (width, height, out)
    };
    ok_image(camera, width, height, try!(self.get_wb()), image)
  }
}

impl<'a> Cr2Decoder<'a> {
  fn get_wb(&self) -> Result<[f32;4], String> {
    let levels = fetch_tag!(self.tiff, Tag::Cr2ColorData);
    let offset = 63;
    Ok([levels.get_force_u16(offset) as f32, levels.get_force_u16(offset+1) as f32,
        levels.get_force_u16(offset+3) as f32, NAN])
  }
}
<commit_msg>CR2: make the vertical field adjustment 40% faster<commit_after>use decoders::*;
use decoders::tiff::*;
use decoders::ljpeg::*;
use std::f32::NAN;
use std::cmp;
use itertools::Itertools;

#[derive(Debug, Clone)]
pub struct Cr2Decoder<'a> {
  buffer: &'a [u8],
  rawloader: &'a RawLoader,
  tiff: TiffIFD<'a>,
}

impl<'a> Cr2Decoder<'a> {
  pub fn new(buf: &'a [u8], tiff: TiffIFD<'a>, rawloader: &'a RawLoader) -> Cr2Decoder<'a> {
    Cr2Decoder {
      buffer: buf,
      tiff: tiff,
      rawloader: rawloader,
    }
  }
}

impl<'a> Decoder for Cr2Decoder<'a> {
  fn image(&self) -> Result<Image,String> {
    let camera = try!(self.rawloader.check_supported(&self.tiff));
    let raw = fetch_ifd!(&self.tiff, Tag::Cr2Id);
    let offset = fetch_tag!(raw, Tag::StripOffsets).get_usize(0);
    let src = &self.buffer[offset..];

    let (width, height, image) = {
      let decompressor = try!(LjpegDecompressor::new(src, true));
      let width = decompressor.width();
      let height = decompressor.height();
      let mut ljpegout = vec![0 as u16; width*height];
      try!(decompressor.decode(&mut ljpegout, 0, width, width, height));

      // Take each of the vertical fields and put them into the right location
      // FIXME: Doing this at the decode would reduce about 5% in runtime but I haven't
      //        been able to do it without hairy code
      let mut out = vec![0 as u16; width*height];
      let canoncol = fetch_tag!(raw, Tag::Cr2StripeWidths).get_usize(1);
      for (field, fieldstart) in (0..width).step(canoncol).enumerate() {
        let fieldwidth = cmp::min((field+1)*canoncol,width) - field*canoncol;
        let fieldpos = field*canoncol*height;
        for row in 0..height {
          let outpos = row*width+fieldstart;
          let inpos = fieldpos+row*fieldwidth;
          let outb = &mut out[outpos..outpos+fieldwidth];
          let inb = &ljpegout[inpos..inpos+fieldwidth];
          outb.copy_from_slice(inb);
        }
      }

      (width, height, out)
    };
    ok_image(camera, width, height, try!(self.get_wb()), image)
  }
}

impl<'a> Cr2Decoder<'a> {
  fn get_wb(&self) -> Result<[f32;4], String> {
    let levels = fetch_tag!(self.tiff, Tag::Cr2ColorData);
    let offset = 63;
    Ok([levels.get_force_u16(offset) as f32, levels.get_force_u16(offset+1) as f32,
        levels.get_force_u16(offset+3) as f32, NAN])
  }
}
<|endoftext|>


<commit_before>// Solution for http://rosettacode.org/wiki/Execute_a_Markov_algorithm
// written for Rust 0.9

// Individual markov rule
struct MarkovRule {
    pattern: ~str,
    replacement: ~str,
    stop: bool
}

impl MarkovRule {
    fn new(pattern: ~str, replacement: ~str, stop: bool) -> MarkovRule {
        MarkovRule {pattern: pattern, replacement: replacement, stop: stop}
    }
}

// Struct for the complete markov algorithm
struct MarkovAlgorithm {
    rules: ~[MarkovRule]
}

impl MarkovAlgorithm {

    // parse an algorithm description to build a markov algorithm
    pub fn build_from_string(s: &str) -> Option<MarkovAlgorithm> {
        let mut rules: ~[MarkovRule] = ~[];
        for line in s.lines() {
            // skip comment lines
            if (line.char_len() > 0) && (line.char_at(0) == '#')
            {
                continue;
            }

            // check for -> (must be preceded by whitespace)
            // invalid ruleset if absent
            // whitespace rules mean there's 2 possible variations: " ->" and "\t->"
            let arrow_pos = line.find_str(" ->").or_else(||{line.find_str("\t->")});
            match arrow_pos {
                None => {
                    // Ruleset is invalid
                    println!("Invalid rule \"{}\"", line);
                    return None
                }
                Some(arrow) => {
                    // extract pattern (trim trailing whitespace)
                    let pattern = line.slice_to(arrow).trim_right();

                    // get the string after the arrow
                    // this adds 3 to skip the arrow itself
                    let line_end = line.slice_from(arrow + 3).trim_left();

                    // check for . (stop)
                    let stop = (line_end.char_len() > 0) && (line_end.char_at(0) == '.');

                    // extract replacement
                    let replacement = if stop {line_end.slice_from(1)} else {line_end};

                    // add to rules
                    let new_rule = MarkovRule::new(pattern.to_owned(), replacement.to_owned(), stop);
                    rules.push(new_rule);
                }
            }
        }
        let rule_set = MarkovAlgorithm{rules: rules};
        Some(rule_set)
    }

    // transform a text string by applying the markov algorithm
    pub fn apply(&self, input: &str) -> ~str {

        // get a writable version of the input to work with
        let mut state = input.into_owned();

        // Don't allow input to be used after this
        drop(input);

        // loop while operations are possible
        loop {
            // find the first rule that is applicable
            // (pattern string is in state)
            let mut rule_iterator = self.rules.iter();
            let possible_rule = rule_iterator.find(|rule|{
                state.find_str(rule.pattern).is_some()
            });

            match possible_rule {
                // stop if no rule found
                None => { break; }
                Some(rule) => {
                    // replace the first instnace (only) of the pattern
                    // Note: cannot use str::replace as that replaces all instances

                    // unwrap is safe here as the code for finding a rule
                    // already established that the pattern is present
                    let pos = state.find_str(rule.pattern).unwrap();
                    let width = rule.pattern.len();

                    // string parts
                    let left = state.slice_to(pos).to_owned();
                    let right = state.slice_from(pos + width).to_owned();

                    // construct new string
                    state = left + rule.replacement + right;

                    // stop if required
                    if rule.stop { break; }
                }
            }
        }

        state
    }
}

// Demonstration of rosetta code samples

struct RCSample {
    ruleset: ~str,
    input: ~str,
    expected_result: ~str
}

fn main() {
    // Sample markow algorithms from rosetta code
    // Left aligned to avoid extra whitespace in strings
    let samples = [
        RCSample{
            ruleset:
~"# This rules file is extracted from Wikipedia:
# http://en.wikipedia.org/wiki/Markov_Algorithm
A -> apple
B -> bag
S -> shop
T -> the
the shop -> my brother
a never used -> .terminating rule",
            input: ~"I bought a B of As from T S.",
            expected_result: ~"I bought a bag of apples from my brother."
        },
        RCSample{
            ruleset:
~"# Slightly modified from the rules on Wikipedia
A -> apple
B -> bag
S -> .shop
T -> the
the shop -> my brother
a never used -> .terminating rule",
            input: ~"I bought a B of As from T S.",
            expected_result: ~"I bought a bag of apples from T shop."
        },
        RCSample{
            ruleset:
~"# BNF Syntax testing rules
A -> apple
WWWW -> with
Bgage -> ->.*
B -> bag
->.* -> money
W -> WW
S -> .shop
T -> the
the shop -> my brother
a never used -> .terminating rule",
            input: ~"I bought a B of As W my Bgage from T S.",
            expected_result: ~"I bought a bag of apples with my money from T shop."
        },
        RCSample{
            ruleset:
~"### Unary Multiplication Engine, for testing Markov Algorithm implementations
### By Donal Fellows.
# Unary addition engine
_+1 -> _1+
1+1 -> 11+
# Pass for converting from the splitting of multiplication into ordinary
# addition
1! -> !1
,! -> !+
_! -> _
# Unary multiplication by duplicating left side, right side times
1*1 -> x,@y
1x -> xX
X, -> 1,1
X1 -> 1X
_x -> _X
,x -> ,X
y1 -> 1y
y_ -> _
# Next phase of applying
1@1 -> x,@y
1@_ -> @_
,@_ -> !_
++ -> +
# Termination cleanup for addition
_1 -> 1
1+_ -> 1
_+_ -> ",
            input: ~"_1111*11111_",
            expected_result: ~"11111111111111111111"
        },
        RCSample{
            ruleset:
~"# Turing machine: three-state busy beaver
#
# state A, symbol 0 => write 1, move right, new state B
A0 -> 1B
# state A, symbol 1 => write 1, move left, new state C
0A1 -> C01
1A1 -> C11
# state B, symbol 0 => write 1, move left, new state A
0B0 -> A01
1B0 -> A11
# state B, symbol 1 => write 1, move right, new state B
B1 -> 1B
# state C, symbol 0 => write 1, move left, new state B
0C0 -> B01
1C0 -> B11
# state C, symbol 1 => write 1, move left, halt
0C1 -> H01
1C1 -> H11",
            input: ~"000000A000000",
            expected_result: ~"00011H1111000"
        },
    ];

    for (index, sample) in samples.iter().enumerate() {
        let markov_algorithm = MarkovAlgorithm::build_from_string(sample.ruleset);

        let output = markov_algorithm.map(|algorithm|{
            algorithm.apply(sample.input)
        });

        output.map(|output_string|{
            println!("Sample {}", (index + 1))
            println!("Expected: {}", sample.expected_result)
            println!("Actual : {}", output_string);
            assert!(sample.expected_result == output_string);
        });
    }
}
<commit_msg>Fixed markov algorithm<commit_after>// Solution for http://rosettacode.org/wiki/Execute_a_Markov_algorithm

// Individual markov rule
struct MarkovRule {
    pattern: ~str,
    replacement: ~str,
    stop: bool
}

impl MarkovRule {
    fn new(pattern: ~str, replacement: ~str, stop: bool) -> MarkovRule {
        MarkovRule {pattern: pattern, replacement: replacement, stop: stop}
    }
}

// Struct for the complete markov algorithm
struct MarkovAlgorithm {
    rules: Vec<MarkovRule>
}

impl MarkovAlgorithm {

    // parse an algorithm description to build a markov algorithm
    pub fn build_from_string(s: &str) -> Option<MarkovAlgorithm> {
        let mut rules: Vec<MarkovRule> = vec!();
        for line in s.lines() {
            // skip comment lines
            if (line.char_len() > 0) && (line.char_at(0) == '#')
            {
                continue;
            }

            // check for -> (must be preceded by whitespace)
            // invalid ruleset if absent
            // whitespace rules mean there's 2 possible variations: " ->" and "\t->"
            let arrow_pos = line.find_str(" ->").or_else(||{line.find_str("\t->")});
            match arrow_pos {
                None => {
                    // Ruleset is invalid
                    println!("Invalid rule \"{}\"", line);
                    return None
                }
                Some(arrow) => {
                    // extract pattern (trim trailing whitespace)
                    let pattern = line.slice_to(arrow).trim_right();

                    // get the string after the arrow
                    // this adds 3 to skip the arrow itself
                    let line_end = line.slice_from(arrow + 3).trim_left();

                    // check for . (stop)
                    let stop = (line_end.char_len() > 0) && (line_end.char_at(0) == '.');

                    // extract replacement
                    let replacement = if stop {line_end.slice_from(1)} else {line_end};

                    // add to rules
                    let new_rule = MarkovRule::new(pattern.to_owned(), replacement.to_owned(), stop);
                    rules.push(new_rule);
                }
            }
        }
        let rule_set = MarkovAlgorithm{rules: rules};
        Some(rule_set)
    }

    // transform a text string by applying the markov algorithm
    pub fn apply(&self, input: &str) -> ~str {

        // get a writable version of the input to work with
        let mut state = input.into_owned();

        // Don't allow input to be used after this
        drop(input);

        // loop while operations are possible
        loop {
            // find the first rule that is applicable
            // (pattern string is in state)
            let mut rule_iterator = self.rules.iter();
            let possible_rule = rule_iterator.find(|rule|{
                state.find_str(rule.pattern).is_some()
            });

            match possible_rule {
                // stop if no rule found
                None => { break; }
                Some(rule) => {
                    // replace the first instnace (only) of the pattern
                    // Note: cannot use str::replace as that replaces all instances

                    // unwrap is safe here as the code for finding a rule
                    // already established that the pattern is present
                    let pos = state.find_str(rule.pattern).unwrap();
                    let width = rule.pattern.len();

                    // string parts
                    let left = state.slice_to(pos).to_owned();
                    let right = state.slice_from(pos + width).to_owned();

                    // construct new string
                    state = left + rule.replacement + right;

                    // stop if required
                    if rule.stop { break; }
                }
            }
        }

        state
    }
}

// Demonstration of rosetta code samples

struct RCSample {
    ruleset: ~str,
    input: ~str,
    expected_result: ~str
}

fn main() {
    // Sample markow algorithms from rosetta code
    // Left aligned to avoid extra whitespace in strings
    let samples = [
        RCSample{
            ruleset:
~"# This rules file is extracted from Wikipedia:
# http://en.wikipedia.org/wiki/Markov_Algorithm
A -> apple
B -> bag
S -> shop
T -> the
the shop -> my brother
a never used -> .terminating rule",
            input: ~"I bought a B of As from T S.",
            expected_result: ~"I bought a bag of apples from my brother."
        },
        RCSample{
            ruleset:
~"# Slightly modified from the rules on Wikipedia
A -> apple
B -> bag
S -> .shop
T -> the
the shop -> my brother
a never used -> .terminating rule",
            input: ~"I bought a B of As from T S.",
            expected_result: ~"I bought a bag of apples from T shop."
        },
        RCSample{
            ruleset:
~"# BNF Syntax testing rules
A -> apple
WWWW -> with
Bgage -> ->.*
B -> bag
->.* -> money
W -> WW
S -> .shop
T -> the
the shop -> my brother
a never used -> .terminating rule",
            input: ~"I bought a B of As W my Bgage from T S.",
            expected_result: ~"I bought a bag of apples with my money from T shop."
        },
        RCSample{
            ruleset:
~"### Unary Multiplication Engine, for testing Markov Algorithm implementations
### By Donal Fellows.
# Unary addition engine
_+1 -> _1+
1+1 -> 11+
# Pass for converting from the splitting of multiplication into ordinary
# addition
1! -> !1
,! -> !+
_! -> _
# Unary multiplication by duplicating left side, right side times
1*1 -> x,@y
1x -> xX
X, -> 1,1
X1 -> 1X
_x -> _X
,x -> ,X
y1 -> 1y
y_ -> _
# Next phase of applying
1@1 -> x,@y
1@_ -> @_
,@_ -> !_
++ -> +
# Termination cleanup for addition
_1 -> 1
1+_ -> 1
_+_ -> ",
            input: ~"_1111*11111_",
            expected_result: ~"11111111111111111111"
        },
        RCSample{
            ruleset:
~"# Turing machine: three-state busy beaver
#
# state A, symbol 0 => write 1, move right, new state B
A0 -> 1B
# state A, symbol 1 => write 1, move left, new state C
0A1 -> C01
1A1 -> C11
# state B, symbol 0 => write 1, move left, new state A
0B0 -> A01
1B0 -> A11
# state B, symbol 1 => write 1, move right, new state B
B1 -> 1B
# state C, symbol 0 => write 1, move left, new state B
0C0 -> B01
1C0 -> B11
# state C, symbol 1 => write 1, move left, halt
0C1 -> H01
1C1 -> H11",
            input: ~"000000A000000",
            expected_result: ~"00011H1111000"
        },
    ];

    for (index, sample) in samples.iter().enumerate() {
        let markov_algorithm = MarkovAlgorithm::build_from_string(sample.ruleset);

        let output = markov_algorithm.map(|algorithm|{
            algorithm.apply(sample.input)
        });

        output.map(|output_string|{
            println!("Sample {}", (index + 1))
            println!("Expected: {}", sample.expected_result)
            println!("Actual : {}", output_string);
            assert!(sample.expected_result == output_string);
        });
    }
}
<|endoftext|>


<commit_before>// This is a part of rust-encoding.
// Copyright (c) 2013, Kang Seonghoon.
// See README.md and LICENSE.txt for details.

/*!
 * Character encoding support for Rust. It is based on [WHATWG Encoding
 * Standard](http://encoding.spec.whatwg.org/), and also provides an advanced interface for
 * error detection and recovery.
 */

#![crate_id = "encoding#0.1.0"]
#![crate_type = "lib"]
#![comment = "Character encoding support for Rust"]
#![license = "MIT"]

#![feature(globs, macro_rules)]

pub use self::types::*; // reexport

mod util;
#[cfg(test)] mod testutils;

pub mod types;

/// Indices used for character encoding implementation. Semi-internal.
pub mod index {
    pub mod ibm866;
    pub mod iso_8859_2;
    pub mod iso_8859_3;
    pub mod iso_8859_4;
    pub mod iso_8859_5;
    pub mod iso_8859_6;
    pub mod iso_8859_7;
    pub mod iso_8859_8;
    pub mod iso_8859_10;
    pub mod iso_8859_13;
    pub mod iso_8859_14;
    pub mod iso_8859_15;
    pub mod iso_8859_16;
    pub mod koi8_r;
    pub mod koi8_u;
    pub mod macintosh;
    pub mod windows_874;
    pub mod windows_1250;
    pub mod windows_1251;
    pub mod windows_1252;
    pub mod windows_1253;
    pub mod windows_1254;
    pub mod windows_1255;
    pub mod windows_1256;
    pub mod windows_1257;
    pub mod windows_1258;
    pub mod x_mac_cyrillic;
    pub mod big5;
    pub mod euc_kr;
    pub mod gbk;
    pub mod gb18030;
    pub mod jis0208;
    pub mod jis0212;
}

/// Codec implementations.
pub mod codec {
    pub mod error;
    pub mod ascii;
    pub mod singlebyte;
    pub mod utf_8;
    pub mod utf_16;
    pub mod korean;
    pub mod japanese;
    pub mod simpchinese;
    pub mod tradchinese;
    pub mod whatwg;
}

pub mod all;
pub mod label;

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

    #[test]
    fn test_readme() {
        assert_eq!(all::ISO_8859_1.encode("caf\xe9", EncodeStrict), Ok(vec!(99,97,102,233)));

        assert!(all::ISO_8859_2.encode("Acme\xa9", EncodeStrict).is_err());
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeReplace), Ok(vec!(65,99,109,101,63)));
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeIgnore), Ok(vec!(65,99,109,101)));
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeNcrEscape),
                   Ok(vec!(65,99,109,101,38,35,49,54,57,59))); // Acme©

        assert_eq!(all::ISO_8859_1.decode([99,97,102,233], DecodeStrict),
                   Ok(StrBuf::from_str("caf\xe9")));

        assert!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeStrict).is_err());
        assert_eq!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeReplace),
                   Ok(StrBuf::from_str("Acme\ufffd")));
        assert_eq!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeIgnore),
                   Ok(StrBuf::from_str("Acme")));
    }

    #[test]
    fn test_readme_hex_ncr_escape() {
        // hexadecimal numeric character reference replacement
        fn hex_ncr_escape(_encoder: &Encoder, input: &str, output: &mut ByteWriter) -> bool {
            let escapes: Vec<~str> =
                input.chars().map(|ch| format!("&\\#x{:x};", ch as int)).collect();
            let escapes = escapes.concat();
            output.write_bytes(escapes.as_bytes());
            true
        }
        static HexNcrEscape: EncoderTrap = EncoderTrap(hex_ncr_escape);
        let orig = ~"Hello, 世界!";
        let encoded = all::ASCII.encode(orig, HexNcrEscape).unwrap();
        let decoded = all::ASCII.decode(encoded.as_slice(), DecodeStrict).unwrap();
        assert_eq!(decoded, StrBuf::from_str("Hello, 世界!"));
    }

    #[test]
    fn test_readme_whatwg() {
        let euckr = label::encoding_from_whatwg_label("euc-kr").unwrap();
        assert_eq!(euckr.name(), "windows-949");
        assert_eq!(euckr.whatwg_name(), Some("euc-kr")); // for the sake of compatibility
        let broken = &[0xbf, 0xec, 0xbf, 0xcd, 0xff, 0xbe, 0xd3];
        assert_eq!(euckr.decode(broken, DecodeReplace),
                   Ok(StrBuf::from_str("\uc6b0\uc640\ufffd\uc559")));

        // corresponding rust-encoding native API:
        assert_eq!(all::WINDOWS_949.decode(broken, DecodeReplace),
                   Ok(StrBuf::from_str("\uc6b0\uc640\ufffd\uc559")));
    }

    #[test]
    fn test_decode() {
        fn test_one(input: &[u8], expected_result: &str, expected_encoding: &str) {
            let (result, used_encoding) = decode(
                input, DecodeStrict, all::ISO_8859_1 as EncodingRef);
            let result = result.unwrap();
            assert_eq!(used_encoding.name(), expected_encoding);
            assert_eq!(result.as_slice(), expected_result);
        }

        test_one([0xEF, 0xBB, 0xBF, 0xC3, 0xA9], "é", "utf-8");
        test_one([0xC3, 0xA9], "Ã©", "iso-8859-1");

        test_one([0xFE, 0xFF, 0x00, 0xE9], "é", "utf-16be");
        test_one([0x00, 0xE9], "\x00é", "iso-8859-1");

        test_one([0xFF, 0xFE, 0xE9, 0x00], "é", "utf-16le");
        test_one([0xE9, 0x00], "é\x00", "iso-8859-1");
    }
}

<commit_msg>Replace glob reexport<commit_after>// This is a part of rust-encoding.
// Copyright (c) 2013, Kang Seonghoon.
// See README.md and LICENSE.txt for details.

/*!
 * Character encoding support for Rust. It is based on [WHATWG Encoding
 * Standard](http://encoding.spec.whatwg.org/), and also provides an advanced interface for
 * error detection and recovery.
 */

#![crate_id = "encoding#0.1.0"]
#![crate_type = "lib"]
#![comment = "Character encoding support for Rust"]
#![license = "MIT"]

#![feature(globs, macro_rules)]

pub use self::types::{CodecError, ByteWriter, StringWriter,
                      Encoder, Decoder, EncodingRef, Encoding,
                      EncoderTrapFunc, DecoderTrapFunc, DecoderTrap,
                      EncoderTrap, decode}; // reexport

mod util;
#[cfg(test)] mod testutils;

pub mod types;

/// Indices used for character encoding implementation. Semi-internal.
pub mod index {
    pub mod ibm866;
    pub mod iso_8859_2;
    pub mod iso_8859_3;
    pub mod iso_8859_4;
    pub mod iso_8859_5;
    pub mod iso_8859_6;
    pub mod iso_8859_7;
    pub mod iso_8859_8;
    pub mod iso_8859_10;
    pub mod iso_8859_13;
    pub mod iso_8859_14;
    pub mod iso_8859_15;
    pub mod iso_8859_16;
    pub mod koi8_r;
    pub mod koi8_u;
    pub mod macintosh;
    pub mod windows_874;
    pub mod windows_1250;
    pub mod windows_1251;
    pub mod windows_1252;
    pub mod windows_1253;
    pub mod windows_1254;
    pub mod windows_1255;
    pub mod windows_1256;
    pub mod windows_1257;
    pub mod windows_1258;
    pub mod x_mac_cyrillic;
    pub mod big5;
    pub mod euc_kr;
    pub mod gbk;
    pub mod gb18030;
    pub mod jis0208;
    pub mod jis0212;
}

/// Codec implementations.
pub mod codec {
    pub mod error;
    pub mod ascii;
    pub mod singlebyte;
    pub mod utf_8;
    pub mod utf_16;
    pub mod korean;
    pub mod japanese;
    pub mod simpchinese;
    pub mod tradchinese;
    pub mod whatwg;
}

pub mod all;
pub mod label;

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

    #[test]
    fn test_readme() {
        assert_eq!(all::ISO_8859_1.encode("caf\xe9", EncodeStrict), Ok(vec!(99,97,102,233)));

        assert!(all::ISO_8859_2.encode("Acme\xa9", EncodeStrict).is_err());
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeReplace), Ok(vec!(65,99,109,101,63)));
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeIgnore), Ok(vec!(65,99,109,101)));
        assert_eq!(all::ISO_8859_2.encode("Acme\xa9", EncodeNcrEscape),
                   Ok(vec!(65,99,109,101,38,35,49,54,57,59))); // Acme©

        assert_eq!(all::ISO_8859_1.decode([99,97,102,233], DecodeStrict),
                   Ok(StrBuf::from_str("caf\xe9")));

        assert!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeStrict).is_err());
        assert_eq!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeReplace),
                   Ok(StrBuf::from_str("Acme\ufffd")));
        assert_eq!(all::ISO_8859_6.decode([65,99,109,101,169], DecodeIgnore),
                   Ok(StrBuf::from_str("Acme")));
    }

    #[test]
    fn test_readme_hex_ncr_escape() {
        // hexadecimal numeric character reference replacement
        fn hex_ncr_escape(_encoder: &Encoder, input: &str, output: &mut ByteWriter) -> bool {
            let escapes: Vec<~str> =
                input.chars().map(|ch| format!("&\\#x{:x};", ch as int)).collect();
            let escapes = escapes.concat();
            output.write_bytes(escapes.as_bytes());
            true
        }
        static HexNcrEscape: EncoderTrap = EncoderTrap(hex_ncr_escape);
        let orig = ~"Hello, 世界!";
        let encoded = all::ASCII.encode(orig, HexNcrEscape).unwrap();
        let decoded = all::ASCII.decode(encoded.as_slice(), DecodeStrict).unwrap();
        assert_eq!(decoded, StrBuf::from_str("Hello, 世界!"));
    }

    #[test]
    fn test_readme_whatwg() {
        let euckr = label::encoding_from_whatwg_label("euc-kr").unwrap();
        assert_eq!(euckr.name(), "windows-949");
        assert_eq!(euckr.whatwg_name(), Some("euc-kr")); // for the sake of compatibility
        let broken = &[0xbf, 0xec, 0xbf, 0xcd, 0xff, 0xbe, 0xd3];
        assert_eq!(euckr.decode(broken, DecodeReplace),
                   Ok(StrBuf::from_str("\uc6b0\uc640\ufffd\uc559")));

        // corresponding rust-encoding native API:
        assert_eq!(all::WINDOWS_949.decode(broken, DecodeReplace),
                   Ok(StrBuf::from_str("\uc6b0\uc640\ufffd\uc559")));
    }

    #[test]
    fn test_decode() {
        fn test_one(input: &[u8], expected_result: &str, expected_encoding: &str) {
            let (result, used_encoding) = decode(
                input, DecodeStrict, all::ISO_8859_1 as EncodingRef);
            let result = result.unwrap();
            assert_eq!(used_encoding.name(), expected_encoding);
            assert_eq!(result.as_slice(), expected_result);
        }

        test_one([0xEF, 0xBB, 0xBF, 0xC3, 0xA9], "é", "utf-8");
        test_one([0xC3, 0xA9], "Ã©", "iso-8859-1");

        test_one([0xFE, 0xFF, 0x00, 0xE9], "é", "utf-16be");
        test_one([0x00, 0xE9], "\x00é", "iso-8859-1");

        test_one([0xFF, 0xFE, 0xE9, 0x00], "é", "utf-16le");
        test_one([0xE9, 0x00], "é\x00", "iso-8859-1");
    }
}

<|endoftext|>


<commit_before>//extern crate serde_json;
use rustc_serialize::json;

use std::error::Error;
use std::fs;
use std::fs::File;
use std::io::{ BufReader, BufRead, Read };
use std::path::{ Path, PathBuf };
use std::str::FromStr;

use download;
use verify;

macro_rules! custom_try {
    ($x:expr) => (match $x {
        Ok(x) => x,
        Err(why) => return Err(format!("An error occured during package finding. {}", why)),
    });
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct Package {
    name: String,
    version: String,
    crc32: String,
    url: String,
    dependencies: Vec<Package>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PackageList {
    packages: Vec<Package>,
    version: i32
}

pub fn update_package_list(url: &str, path: &Path) -> Result<bool, String> {
    if (path.extension().is_some() && path.extension().unwrap_or("") != ".json") ||
       (path.extension().is_none())
    {
        return Err(String::from(
            format!("Extension of package list is not .json: {}", path.to_str().unwrap_or("Invalid File"))
        ));
    }

    let mut path_temp = PathBuf::new();
    path_temp.push(path);
    path_temp.set_extension("json.tmp");

    if download::download_file(url, path_temp.as_path()).is_err() {
        return Err(String::from("Error occured while downloading package list"))
    }

    if verify::verify_file_crc32(&custom_try!(File::open(&path_temp))) ==
       verify::verify_file_crc32(&custom_try!(File::open(&path)))
    {
        fs::remove_file(path_temp);
        return Ok(false)
    } else {
        fs::remove_file(path);
        fs::rename(path_temp, path);
        return Ok(true)
    }
}

pub fn find_package(name: &str, path:&Path) -> Result<Vec<Package>, String> {
    let mut list = custom_try!(File::open(path));
    let mut reader = BufReader::new(list);
    let mut buffer = String::new();

    reader.read_to_string(&mut buffer);
    let package_list: PackageList = custom_try!(json::decode(&buffer));

    let filtered = package_list.packages
                    .into_iter()
                    .filter(|x| !x.name.contains(name))
                    .collect::<Vec<_>>();

    match filtered.len() {
        0 => Err(String::from("Package not found")),
        _ => Ok(filtered)
    }
}
<commit_msg>Add new function to simplify future code<commit_after>//extern crate serde_json;
use rustc_serialize::json;

use std::error::Error;
use std::fs;
use std::fs::File;
use std::io::{ BufReader, BufRead, Read };
use std::path::{ Path, PathBuf };
use std::str::FromStr;

use download;
use verify;

macro_rules! custom_try {
    ($x:expr) => (match $x {
        Ok(x) => x,
        Err(why) => return Err(format!("An error occured during package finding. {}", why)),
    });
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct Package {
    name: String,
    version: String,
    crc32: String,
    url: String,
    dependencies: Vec<Package>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PackageList {
    packages: Vec<Package>,
    version: i32
}

pub fn update_package_list(url: &str, path: &Path) -> Result<bool, String> {
    if (path.extension().is_some() && path.extension().unwrap_or("") != ".json") ||
       (path.extension().is_none())
    {
        return Err(String::from(
            format!("Extension of package list is not .json: {}", path.to_str().unwrap_or("Invalid File"))
        ));
    }

    let mut path_temp = PathBuf::new();
    path_temp.push(path);
    path_temp.set_extension("json.tmp");

    if download::download_file(url, path_temp.as_path()).is_err() {
        return Err(String::from("Error occured while downloading package list"))
    }

    if verify::verify_file_crc32(&custom_try!(File::open(&path_temp))) ==
       verify::verify_file_crc32(&custom_try!(File::open(&path)))
    {
        fs::remove_file(path_temp);
        return Ok(false)
    } else {
        fs::remove_file(path);
        fs::rename(path_temp, path);
        return Ok(true)
    }
}

pub fn find_package(name: &str, path:&Path) -> Result<Vec<Package>, String> {
    let mut list = custom_try!(File::open(path));
    let mut reader = BufReader::new(list);
    let mut buffer = String::new();

    reader.read_to_string(&mut buffer);
    let package_list: PackageList = custom_try!(json::decode(&buffer));

    let filtered = package_list.packages
                    .into_iter()
                    .filter(|x| !x.name.contains(name))
                    .collect::<Vec<_>>();

    match filtered.len() {
        0 => Err(String::from("Package not found")),
        _ => Ok(filtered)
    }
}

pub fn download_and_find(name: &str, url:&str, path:&Path) -> Result<Vec<Package>, String>{
    if update_package_list(url, path).is_ok() {
        return find_package(name, path)
    } else {
        return Err(String::from("Error occured while downloading package list"))
    }
}
<|endoftext|>


<commit_before>//! The element nodes.

use std::fmt;

use node::{Attributes, Children, Node, Value};

#[doc(hidden)]
pub struct Element {
    name: String,
    attributes: Attributes,
    children: Children,
}

impl Element {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        Element { name: name.into(), attributes: Attributes::new(), children: Children::new() }
    }
}

impl fmt::Display for Element {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(formatter, "<{}", self.name));
        let mut attributes = self.attributes.iter().collect::<Vec<_>>();
        attributes.sort_by_key(|pair| pair.0.as_str());
        for (name, value) in attributes {
            match (value.contains("'"), value.contains('"')) {
                (true, false) | (false, false) => {
                    try!(write!(formatter, r#" {}="{}""#, name, value));
                },
                (false, true) => {
                    try!(write!(formatter, r#" {}='{}'"#, name, value));
                },
                _ => {},
            }
        }
        if self.children.is_empty() {
            return write!(formatter, "/>");
        }
        try!(write!(formatter, ">"));
        for child in self.children.iter() {
            try!(write!(formatter, "\n{}", child));
        }
        write!(formatter, "\n</{}>", self.name)
    }
}

impl Node for Element {
    #[inline]
    fn append<T>(&mut self, node: T) where T: Node {
        self.children.push(Box::new(node));
    }

    #[inline]
    fn assign<T, U>(&mut self, name: T, value: U) where T: Into<String>, U: Into<Value> {
        self.attributes.insert(name.into(), value.into());
    }
}

macro_rules! implement {
    ($(#[$doc:meta] struct $struct_name:ident($tag_name:expr))*) => (
        $(
            #[$doc]
            pub struct $struct_name {
                inner: Element,
            }

            impl $struct_name {
                /// Create a node.
                #[inline]
                pub fn new() -> Self {
                    $struct_name { inner: Element::new($tag_name) }
                }
            }

            node! { $struct_name::inner }
        )*
    );
}

implement! {
    #[doc = "An [`animate`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateElement"]
    struct Animate("animate")

    #[doc = "An [`animateColor`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateColorElement"]
    struct AnimateColor("animateColor")

    #[doc = "An [`animateMotion`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateMotionElement"]
    struct AnimateMotion("animateMotion")

    #[doc = "An [`animateTransform`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateTransformElement"]
    struct AnimateTransform("animateTransform")

    #[doc = "A [`circle`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#CircleElement"]
    struct Circle("circle")

    #[doc = "A [`clipPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#ClipPathElement"]
    struct ClipPath("clipPath")

    #[doc = "A [`defs`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DefsElement"]
    struct Definitions("defs")

    #[doc = "A [`desc`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DescElement"]
    struct Description("desc")

    #[doc = "An [`ellipse`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#EllipseElement"]
    struct Ellipse("ellipse")

    #[doc = "A [`filter`][1] element.
    [1]: https://www.w3.org/TR/SVG/filters.html#FilterElement"]
    struct Filter("filter")

    #[doc = "A [`g`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#GElement"]
    struct Group("g")

    #[doc = "An [`image`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#ImageElement"]
    struct Image("image")

    #[doc = "A [`line`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#LineElement"]
    struct Line("line")

    #[doc = "A [`linearGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#LinearGradientElement"]
    struct LinearGradient("linearGradient")

    #[doc = "An [`a`][1] element.
    [1]: https://www.w3.org/TR/SVG/linking.html#AElement"]
    struct Link("a")

    #[doc = "A [`marker`][1] element.
    [1]: https://www.w3.org/TR/SVG/painting.html#MarkerElement"]
    struct Marker("marker")

    #[doc = "A [`mask`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#MaskElement"]
    struct Mask("mask")

    #[doc = "An [`mpath`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#MPathElement"]
    struct MotionPath("mpath")

    #[doc = "A [`path`][1] element.
    [1]: https://www.w3.org/TR/SVG/paths.html#PathElement"]
    struct Path("path")

    #[doc = "A [`polygon`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolygonElement"]
    struct Polygon("polygon")

    #[doc = "A [`polyline`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolylineElement"]
    struct Polyline("polyline")

    #[doc = "A [`radialGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#RadialGradientElement"]
    struct RadialGradient("radialGradient")

    #[doc = "A [`rect`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#RectElement"]
    struct Rectangle("rect")

    #[doc = "A [`stop`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#StopElement"]
    struct Stop("stop")

    #[doc = "A [`symbol`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SymbolElement"]
    struct Symbol("symbol")

    #[doc = "A [`text`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextElement"]
    struct Text("text")

    #[doc = "A [`textPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextPathElement"]
    struct TextPath("textPath")

    #[doc = "A [`title`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#TitleElement"]
    struct Title("title")

    #[doc = "A [`use`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#UseElement"]
    struct Use("use")
}

macro_rules! implement {
    (@itemize $i:item) => ($i);
    (
        $(
            #[$doc:meta]
            struct $struct_name:ident($tag_name:expr)
            [$($pn:ident: $($pt:tt)*),*] [$inner:ident $(,$an:ident: $at:ty)*] $body:block
        )*
    ) => (
        $(
            #[$doc]
            pub struct $struct_name {
                inner: Element,
            }

            implement! { @itemize
                impl $struct_name {
                    /// Create a node.
                    #[inline]
                    pub fn new<$($pn: $($pt)*),*>($($an: $at),*) -> Self {
                        #[inline(always)]
                        fn initialize<$($pn: $($pt)*),*>($inner: &mut Element $(, $an: $at)*) $body
                        let mut inner = Element::new($tag_name);
                        initialize(&mut inner $(, $an)*);
                        $struct_name { inner: inner }
                    }
                }
            }

            node! { $struct_name::inner }
        )*
    );
}

implement! {
    #[doc = "An [`svg`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SVGElement"]
    struct SVG("svg") [] [inner] {
        inner.assign("xmlns", "http://www.w3.org/2000/svg");
    }

    #[doc = "A [`script`][1] element.
    [1]: https://www.w3.org/TR/SVG/script.html#ScriptElement"]
    struct Script("script") [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }

    #[doc = "A [`style`][1] element.
    [1]: https://www.w3.org/TR/SVG/styling.html#StyleElement"]
    struct Style("style") [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }
}

pub mod path;

#[cfg(test)]
mod tests {
    use node::Node;
    use super::{Element, Style};

    #[test]
    fn element_display() {
        let mut element = Element::new("foo");
        element.assign("x", -10);
        element.assign("y", "10px");
        element.assign("s", (12.5, 13.0));
        element.assign("c", "green");
        element.append(Element::new("bar"));
        assert_eq!(element.to_string(), "\
            <foo c=\"green\" s=\"12.5 13\" x=\"-10\" y=\"10px\">\n\
            <bar/>\n\
            </foo>\
        ");
    }

    #[test]
    fn element_display_quotes() {
        let mut element = Element::new("foo");
        element.assign("s", "'single'");
        element.assign("d", r#""double""#);
        element.assign("m", r#""mixed'"#);
        assert_eq!(element.to_string(), r#"<foo d='"double"' s="'single'"/>"#);
    }

    #[test]
    fn text_display() {
        let element = Style::new("* { font-family: foo; }");
        assert_eq!(element.to_string(), "\
            <style>\n\
            * { font-family: foo; }\n\
            </style>\
        ");
    }
}
<commit_msg>Rename a test<commit_after>//! The element nodes.

use std::fmt;

use node::{Attributes, Children, Node, Value};

#[doc(hidden)]
pub struct Element {
    name: String,
    attributes: Attributes,
    children: Children,
}

impl Element {
    pub fn new<T>(name: T) -> Self where T: Into<String> {
        Element { name: name.into(), attributes: Attributes::new(), children: Children::new() }
    }
}

impl fmt::Display for Element {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(formatter, "<{}", self.name));
        let mut attributes = self.attributes.iter().collect::<Vec<_>>();
        attributes.sort_by_key(|pair| pair.0.as_str());
        for (name, value) in attributes {
            match (value.contains("'"), value.contains('"')) {
                (true, false) | (false, false) => {
                    try!(write!(formatter, r#" {}="{}""#, name, value));
                },
                (false, true) => {
                    try!(write!(formatter, r#" {}='{}'"#, name, value));
                },
                _ => {},
            }
        }
        if self.children.is_empty() {
            return write!(formatter, "/>");
        }
        try!(write!(formatter, ">"));
        for child in self.children.iter() {
            try!(write!(formatter, "\n{}", child));
        }
        write!(formatter, "\n</{}>", self.name)
    }
}

impl Node for Element {
    #[inline]
    fn append<T>(&mut self, node: T) where T: Node {
        self.children.push(Box::new(node));
    }

    #[inline]
    fn assign<T, U>(&mut self, name: T, value: U) where T: Into<String>, U: Into<Value> {
        self.attributes.insert(name.into(), value.into());
    }
}

macro_rules! implement {
    ($(#[$doc:meta] struct $struct_name:ident($tag_name:expr))*) => (
        $(
            #[$doc]
            pub struct $struct_name {
                inner: Element,
            }

            impl $struct_name {
                /// Create a node.
                #[inline]
                pub fn new() -> Self {
                    $struct_name { inner: Element::new($tag_name) }
                }
            }

            node! { $struct_name::inner }
        )*
    );
}

implement! {
    #[doc = "An [`animate`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateElement"]
    struct Animate("animate")

    #[doc = "An [`animateColor`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateColorElement"]
    struct AnimateColor("animateColor")

    #[doc = "An [`animateMotion`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateMotionElement"]
    struct AnimateMotion("animateMotion")

    #[doc = "An [`animateTransform`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#AnimateTransformElement"]
    struct AnimateTransform("animateTransform")

    #[doc = "A [`circle`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#CircleElement"]
    struct Circle("circle")

    #[doc = "A [`clipPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#ClipPathElement"]
    struct ClipPath("clipPath")

    #[doc = "A [`defs`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DefsElement"]
    struct Definitions("defs")

    #[doc = "A [`desc`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#DescElement"]
    struct Description("desc")

    #[doc = "An [`ellipse`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#EllipseElement"]
    struct Ellipse("ellipse")

    #[doc = "A [`filter`][1] element.
    [1]: https://www.w3.org/TR/SVG/filters.html#FilterElement"]
    struct Filter("filter")

    #[doc = "A [`g`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#GElement"]
    struct Group("g")

    #[doc = "An [`image`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#ImageElement"]
    struct Image("image")

    #[doc = "A [`line`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#LineElement"]
    struct Line("line")

    #[doc = "A [`linearGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#LinearGradientElement"]
    struct LinearGradient("linearGradient")

    #[doc = "An [`a`][1] element.
    [1]: https://www.w3.org/TR/SVG/linking.html#AElement"]
    struct Link("a")

    #[doc = "A [`marker`][1] element.
    [1]: https://www.w3.org/TR/SVG/painting.html#MarkerElement"]
    struct Marker("marker")

    #[doc = "A [`mask`][1] element.
    [1]: https://www.w3.org/TR/SVG/masking.html#MaskElement"]
    struct Mask("mask")

    #[doc = "An [`mpath`][1] element.
    [1]: https://www.w3.org/TR/SVG/animate.html#MPathElement"]
    struct MotionPath("mpath")

    #[doc = "A [`path`][1] element.
    [1]: https://www.w3.org/TR/SVG/paths.html#PathElement"]
    struct Path("path")

    #[doc = "A [`polygon`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolygonElement"]
    struct Polygon("polygon")

    #[doc = "A [`polyline`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#PolylineElement"]
    struct Polyline("polyline")

    #[doc = "A [`radialGradient`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#RadialGradientElement"]
    struct RadialGradient("radialGradient")

    #[doc = "A [`rect`][1] element.
    [1]: https://www.w3.org/TR/SVG/shapes.html#RectElement"]
    struct Rectangle("rect")

    #[doc = "A [`stop`][1] element.
    [1]: https://www.w3.org/TR/SVG/pservers.html#StopElement"]
    struct Stop("stop")

    #[doc = "A [`symbol`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SymbolElement"]
    struct Symbol("symbol")

    #[doc = "A [`text`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextElement"]
    struct Text("text")

    #[doc = "A [`textPath`][1] element.
    [1]: https://www.w3.org/TR/SVG/text.html#TextPathElement"]
    struct TextPath("textPath")

    #[doc = "A [`title`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#TitleElement"]
    struct Title("title")

    #[doc = "A [`use`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#UseElement"]
    struct Use("use")
}

macro_rules! implement {
    (@itemize $i:item) => ($i);
    (
        $(
            #[$doc:meta]
            struct $struct_name:ident($tag_name:expr)
            [$($pn:ident: $($pt:tt)*),*] [$inner:ident $(,$an:ident: $at:ty)*] $body:block
        )*
    ) => (
        $(
            #[$doc]
            pub struct $struct_name {
                inner: Element,
            }

            implement! { @itemize
                impl $struct_name {
                    /// Create a node.
                    #[inline]
                    pub fn new<$($pn: $($pt)*),*>($($an: $at),*) -> Self {
                        #[inline(always)]
                        fn initialize<$($pn: $($pt)*),*>($inner: &mut Element $(, $an: $at)*) $body
                        let mut inner = Element::new($tag_name);
                        initialize(&mut inner $(, $an)*);
                        $struct_name { inner: inner }
                    }
                }
            }

            node! { $struct_name::inner }
        )*
    );
}

implement! {
    #[doc = "An [`svg`][1] element.
    [1]: https://www.w3.org/TR/SVG/struct.html#SVGElement"]
    struct SVG("svg") [] [inner] {
        inner.assign("xmlns", "http://www.w3.org/2000/svg");
    }

    #[doc = "A [`script`][1] element.
    [1]: https://www.w3.org/TR/SVG/script.html#ScriptElement"]
    struct Script("script") [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }

    #[doc = "A [`style`][1] element.
    [1]: https://www.w3.org/TR/SVG/styling.html#StyleElement"]
    struct Style("style") [T: Into<String>] [inner, content: T] {
        inner.append(::node::Text::new(content));
    }
}

pub mod path;

#[cfg(test)]
mod tests {
    use node::Node;
    use super::{Element, Style};

    #[test]
    fn element_display() {
        let mut element = Element::new("foo");
        element.assign("x", -10);
        element.assign("y", "10px");
        element.assign("s", (12.5, 13.0));
        element.assign("c", "green");
        element.append(Element::new("bar"));
        assert_eq!(element.to_string(), "\
            <foo c=\"green\" s=\"12.5 13\" x=\"-10\" y=\"10px\">\n\
            <bar/>\n\
            </foo>\
        ");
    }

    #[test]
    fn element_display_quotes() {
        let mut element = Element::new("foo");
        element.assign("s", "'single'");
        element.assign("d", r#""double""#);
        element.assign("m", r#""mixed'"#);
        assert_eq!(element.to_string(), r#"<foo d='"double"' s="'single'"/>"#);
    }

    #[test]
    fn style_display() {
        let element = Style::new("* { font-family: foo; }");
        assert_eq!(element.to_string(), "\
            <style>\n\
            * { font-family: foo; }\n\
            </style>\
        ");
    }
}
<|endoftext|>


<commit_before>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use metadata::StreamInfo;
use utility::{crc8, crc16, to_u32};

pub fn frame_parser<'a>(input: &'a [u8], stream_info: &StreamInfo)
                        -> IResult<'a, &'a [u8], Frame> {
  let result = chain!(input,
    frame_header: apply!(header, stream_info) ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  );

  match result {
    IResult::Done(i, frame)   => {
      // All frame bytes before the crc-16
      let end         = (input.len() - i.len()) - 2;
      let Footer(crc) = frame.footer;

      if crc16(&input[0..end]) == crc {
        IResult::Done(i, frame)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      ((bytes[1] as u16) >> 2);
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
  match be_u8(input) {
    IResult::Done(i, byte)    => {
      let block_byte  = byte >> 4;
      let sample_byte = byte & 0x0f;
      let is_valid    = block_byte != 0b0000 && sample_byte != 0b1111;

      if is_valid {
        IResult::Done(i, (block_byte, sample_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, u8, u8)> {
  match be_u8(input) {
    IResult::Done(i, byte)    => {
      let mut channels       = 2;
      let channel_byte       = byte >> 4;
      let channel_assignment = match channel_byte {
        0b0000...0b0111 => {
          channels = channel_byte + 1;

          ChannelAssignment::Independent
        }
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let size_byte = (byte >> 1) & 0b0111;

      // Checks the validity of:
      //
      // * (4 bits) channel assignment
      // * (3 bits) sample size
      // * (1 bit) last bit
      //
      // All these checks are whether of not they are reserved and should
      // return an error if so.
      let is_valid = channel_byte < 0b1011 &&
                     (size_byte != 0b0011 && size_byte != 0b0111) &&
                     (byte & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, channels, size_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn number_type(input: &[u8], is_sample: bool,
               (size, value): (usize, u8))
               -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in 0..size {
        let byte = bytes[i] as u64;

        if byte >= 0b10000000 && byte <= 0b10111111 {
          result = (result << 6) + (byte & 0b00111111);
        } else {
          is_error = true;
          break;
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100          => opt!(input, map!(take!(1), to_u32)),
    0b1101 | 0b1110 => opt!(input, map!(take!(2), to_u32)),
    _               => IResult::Done(input, None)
  }
}

pub fn header<'a>(input: &'a [u8], stream_info: &StreamInfo)
                  -> IResult<'a, &'a [u8], Header> {
  let result = chain!(input,
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(number_type, is_variable_block_size, number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)                 = tuple0;
      let (channel_assignment, channels, size_byte) = tuple1;

      let block_size = match block_byte {
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(block_byte as u32 - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(block_byte as u32 - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => stream_info.sample_rate,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        _      => unreachable!(),
      };

      let bits_per_sample = match size_byte {
        0b0000 => stream_info.bits_per_sample as usize,
        0b0001 => 8,
        0b0010 => 12,
        0b0100 => 16,
        0b0101 => 20,
        0b0110 => 24,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channels: channels,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  );

  match result {
    IResult::Done(i, frame_header) => {
      // All header bytes before the crc-8
      let end = (input.len() - i.len()) - 1;

      if crc8(&input[0..end]) == frame_header.crc {
        IResult::Done(i, frame_header)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)          => IResult::Error(error),
    IResult::Incomplete(need)      => IResult::Incomplete(need),
  }
}

named!(pub footer <&[u8], Footer>, map!(be_u16, Footer));

#[cfg(test)]
mod tests {
  use super::*;
  use frame::{
    Header, Footer,
    ChannelAssignment, NumberType,
  };
  use metadata::StreamInfo;
  use nom::IResult;

  #[test]
  fn test_header() {
    let inputs   = [ &b"\xff\xf8\x53\x1c\xf0\x90\x80\x80\x2e"[..]
                   , &b"\xff\xf9\x7c\xa0\xfe\xbf\xbf\xbf\xbf\xbf\xbc\x01\xff\
                        \x01\x88"[..]
                   , &b"\xff\xf8\xc8\x72\x40\x19"[..]
                   ];
    let mut info = StreamInfo::new();
    let results  = [ IResult::Done(&[][..], Header {
                      block_size: 4608,
                      sample_rate: 192000,
                      channel_assignment: ChannelAssignment::Independent,
                      bits_per_sample: 24,
                      number: NumberType::Frame(65536),
                      crc: 0x2e,
                    })
                  , IResult::Done(&[][..], Header {
                      block_size: 512,
                      sample_rate: 1000,
                      channel_assignment: ChannelAssignment::MiddleSide,
                      bits_per_sample: 16,
                      number: NumberType::Sample(68719476732),
                      crc: 0x88,
                    })
                  , IResult::Done(&[][..], Header {
                      block_size: 4096,
                      sample_rate: 32000,
                      channel_assignment: ChannelAssignment::Independent,
                      bits_per_sample: 8,
                      number: NumberType::Frame(64),
                      crc: 0x19,
                    })
                  ];

    info.bits_per_sample = 16;

    assert_eq!(header(inputs[0], &info), results[0]);
    assert_eq!(header(inputs[1], &info), results[1]);
    assert_eq!(header(inputs[2], &info), results[2]);
  }

  #[test]
  fn test_footer() {
    let input  = b"\x03\xe8";
    let result = IResult::Done(&[][..], Footer(0x03e8));

    assert_eq!(footer(input), result);
  }
}
<commit_msg>Modify tests to incorporate the channels value<commit_after>use nom::{
  be_u8, be_u16,
  IResult,
  ErrorCode, Err,
};

use frame::{
  ChannelAssignment, NumberType,
  Frame,
  Header, Footer,
};

use metadata::StreamInfo;
use utility::{crc8, crc16, to_u32};

pub fn frame_parser<'a>(input: &'a [u8], stream_info: &StreamInfo)
                        -> IResult<'a, &'a [u8], Frame> {
  let result = chain!(input,
    frame_header: apply!(header, stream_info) ~
    frame_footer: footer,
    || {
      Frame {
        header: frame_header,
        footer: frame_footer,
      }
    }
  );

  match result {
    IResult::Done(i, frame)   => {
      // All frame bytes before the crc-16
      let end         = (input.len() - i.len()) - 2;
      let Footer(crc) = frame.footer;

      if crc16(&input[0..end]) == crc {
        IResult::Done(i, frame)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn blocking_strategy(input: &[u8]) -> IResult<&[u8], bool> {
  match take!(input, 2) {
    IResult::Done(i, bytes)   => {
      let sync_code = ((bytes[0] as u16) << 6) +
                      ((bytes[1] as u16) >> 2);
      let is_valid  = ((bytes[1] >> 1) & 0b01) == 0;

      if sync_code == 0b11111111111110 && is_valid {
        let is_variable_block_size = (bytes[1] & 0b01) == 1;

        IResult::Done(i, is_variable_block_size)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn block_sample(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
  match be_u8(input) {
    IResult::Done(i, byte)    => {
      let block_byte  = byte >> 4;
      let sample_byte = byte & 0x0f;
      let is_valid    = block_byte != 0b0000 && sample_byte != 0b1111;

      if is_valid {
        IResult::Done(i, (block_byte, sample_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn channel_bits(input: &[u8]) -> IResult<&[u8], (ChannelAssignment, u8, u8)> {
  match be_u8(input) {
    IResult::Done(i, byte)    => {
      let mut channels       = 2;
      let channel_byte       = byte >> 4;
      let channel_assignment = match channel_byte {
        0b0000...0b0111 => {
          channels = channel_byte + 1;

          ChannelAssignment::Independent
        }
        0b1000          => ChannelAssignment::LeftSide,
        0b1001          => ChannelAssignment::RightSide,
        0b1010          => ChannelAssignment::MiddleSide,
        _               => ChannelAssignment::Independent,
      };
      let size_byte = (byte >> 1) & 0b0111;

      // Checks the validity of:
      //
      // * (4 bits) channel assignment
      // * (3 bits) sample size
      // * (1 bit) last bit
      //
      // All these checks are whether of not they are reserved and should
      // return an error if so.
      let is_valid = channel_byte < 0b1011 &&
                     (size_byte != 0b0011 && size_byte != 0b0111) &&
                     (byte & 0b01) == 0;

      if is_valid {
        IResult::Done(i, (channel_assignment, channels, size_byte))
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn utf8_size(input: &[u8], is_u64: bool)
             -> IResult<&[u8], Option<(usize, u8)>> {
  map!(input, be_u8, |utf8_header| {
    match utf8_header {
      0b00000000...0b01111111 => Some((0, utf8_header)),
      0b11000000...0b11011111 => Some((1, utf8_header & 0b00011111)),
      0b11100000...0b11101111 => Some((2, utf8_header & 0b00001111)),
      0b11110000...0b11110111 => Some((3, utf8_header & 0b00000111)),
      0b11111000...0b11111011 => Some((4, utf8_header & 0b00000011)),
      0b11111100...0b11111101 => Some((5, utf8_header & 0b00000001)),
      0b11111110              => if is_u64 { Some((6, 0)) } else { None },
      _                       => None,
    }
  })
}

fn number_type(input: &[u8], is_sample: bool,
               (size, value): (usize, u8))
               -> IResult<&[u8], NumberType> {
  let mut result   = value as u64;
  let mut is_error = false;

  match take!(input, size) {
    IResult::Done(i, bytes)   => {
      for i in 0..size {
        let byte = bytes[i] as u64;

        if byte >= 0b10000000 && byte <= 0b10111111 {
          result = (result << 6) + (byte & 0b00111111);
        } else {
          is_error = true;
          break;
        }
      }

      if is_error {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      } else if is_sample {
        IResult::Done(i, NumberType::Sample(result))
      } else {
        IResult::Done(i, NumberType::Frame(result as u32))
      }
    }
    IResult::Error(error)     => IResult::Error(error),
    IResult::Incomplete(need) => IResult::Incomplete(need),
  }
}

fn secondary_block_size(input: &[u8], block_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match block_byte {
    0b0110 => opt!(input, map!(take!(1), to_u32)),
    0b0111 => opt!(input, map!(take!(2), to_u32)),
    _      => IResult::Done(input, None)
  }
}

fn secondary_sample_rate(input: &[u8], sample_byte: u8)
                        -> IResult<&[u8], Option<u32>> {
  match sample_byte {
    0b1100          => opt!(input, map!(take!(1), to_u32)),
    0b1101 | 0b1110 => opt!(input, map!(take!(2), to_u32)),
    _               => IResult::Done(input, None)
  }
}

pub fn header<'a>(input: &'a [u8], stream_info: &StreamInfo)
                  -> IResult<'a, &'a [u8], Header> {
  let result = chain!(input,
    is_variable_block_size: blocking_strategy ~
    tuple0: block_sample ~
    tuple1: channel_bits ~
    number_opt: apply!(utf8_size, is_variable_block_size) ~
    number_length: expr_opt!(number_opt) ~
    number: apply!(number_type, is_variable_block_size, number_length) ~
    alt_block_size: apply!(secondary_block_size, tuple0.0) ~
    alt_sample_rate: apply!(secondary_sample_rate, tuple0.1) ~
    crc: be_u8,
    || {
      let (block_byte, sample_byte)                 = tuple0;
      let (channel_assignment, channels, size_byte) = tuple1;

      let block_size = match block_byte {
        0b0001          => 192,
        0b0010...0b0101 => 576 * 2_u32.pow(block_byte as u32 - 2),
        0b0110 | 0b0111 => alt_block_size.unwrap() + 1,
        0b1000...0b1111 => 256 * 2_u32.pow(block_byte as u32 - 8),
        _               => unreachable!(),
      };

      let sample_rate = match sample_byte {
        0b0000 => stream_info.sample_rate,
        0b0001 => 88200,
        0b0010 => 176400,
        0b0011 => 192000,
        0b0100 => 8000,
        0b0101 => 16000,
        0b0110 => 22050,
        0b0111 => 24000,
        0b1000 => 32000,
        0b1001 => 44100,
        0b1010 => 48000,
        0b1011 => 96000,
        0b1100 => alt_sample_rate.unwrap() * 1000,
        0b1101 => alt_sample_rate.unwrap(),
        0b1110 => alt_sample_rate.unwrap() * 10,
        _      => unreachable!(),
      };

      let bits_per_sample = match size_byte {
        0b0000 => stream_info.bits_per_sample as usize,
        0b0001 => 8,
        0b0010 => 12,
        0b0100 => 16,
        0b0101 => 20,
        0b0110 => 24,
        _      => unreachable!(),
      };

      Header {
        block_size: block_size,
        sample_rate: sample_rate,
        channels: channels,
        channel_assignment: channel_assignment,
        bits_per_sample: bits_per_sample,
        number: number,
        crc: crc,
      }
    }
  );

  match result {
    IResult::Done(i, frame_header) => {
      // All header bytes before the crc-8
      let end = (input.len() - i.len()) - 1;

      if crc8(&input[0..end]) == frame_header.crc {
        IResult::Done(i, frame_header)
      } else {
        IResult::Error(Err::Position(ErrorCode::Digit as u32, input))
      }
    }
    IResult::Error(error)          => IResult::Error(error),
    IResult::Incomplete(need)      => IResult::Incomplete(need),
  }
}

named!(pub footer <&[u8], Footer>, map!(be_u16, Footer));

#[cfg(test)]
mod tests {
  use super::*;
  use frame::{
    Header, Footer,
    ChannelAssignment, NumberType,
  };
  use metadata::StreamInfo;
  use nom::IResult;

  #[test]
  fn test_header() {
    let inputs   = [ &b"\xff\xf8\x53\x1c\xf0\x90\x80\x80\x2e"[..]
                   , &b"\xff\xf9\x7c\xa0\xfe\xbf\xbf\xbf\xbf\xbf\xbc\x01\xff\
                        \x01\x88"[..]
                   , &b"\xff\xf8\xc8\x72\x40\x19"[..]
                   ];
    let mut info = StreamInfo::new();
    let results  = [ IResult::Done(&[][..], Header {
                      block_size: 4608,
                      sample_rate: 192000,
                      channels: 2,
                      channel_assignment: ChannelAssignment::Independent,
                      bits_per_sample: 24,
                      number: NumberType::Frame(65536),
                      crc: 0x2e,
                    })
                  , IResult::Done(&[][..], Header {
                      block_size: 512,
                      sample_rate: 1000,
                      channels: 2,
                      channel_assignment: ChannelAssignment::MiddleSide,
                      bits_per_sample: 16,
                      number: NumberType::Sample(68719476732),
                      crc: 0x88,
                    })
                  , IResult::Done(&[][..], Header {
                      block_size: 4096,
                      sample_rate: 32000,
                      channels: 8,
                      channel_assignment: ChannelAssignment::Independent,
                      bits_per_sample: 8,
                      number: NumberType::Frame(64),
                      crc: 0x19,
                    })
                  ];

    info.bits_per_sample = 16;

    assert_eq!(header(inputs[0], &info), results[0]);
    assert_eq!(header(inputs[1], &info), results[1]);
    assert_eq!(header(inputs[2], &info), results[2]);
  }

  #[test]
  fn test_footer() {
    let input  = b"\x03\xe8";
    let result = IResult::Done(&[][..], Footer(0x03e8));

    assert_eq!(footer(input), result);
  }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;

use std::sync::Arc;
use std::sync::Mutex;
use std::iter;

use futures::*;
use futures::stream::Stream;
use futures::stream::BoxStream;
use futures::task::TaskData;

pub struct FutureToStream<F> {
    future: Option<F>,
}

pub fn future_to_stream<F : Future>(f: F) -> FutureToStream<F> {
    FutureToStream {
        future: Some(f)
    }
}

impl<F : Future> Stream for FutureToStream<F> {
    type Item = F::Item;
    type Error = F::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let r = match &mut self.future {
            &mut None => return Poll::Ok(None),
            &mut Some(ref mut future) => match future.poll() {
                Poll::NotReady => return Poll::NotReady,
                Poll::Err(e) => Poll::Err(e),
                Poll::Ok(r) => Poll::Ok(Some(r)),
            }
        };

        self.future.take();

        r
    }
}

#[allow(dead_code)]
pub fn future_success<T : Send + 'static, E : Send + 'static>(t: T) -> BoxFuture<T, E> {
    done(Ok(t))
        .boxed()
}

#[allow(dead_code)]
pub fn stream_repeat<T : Clone + Send + 'static, E>(t: T) -> BoxStream<T, E> {
    let ts = iter::repeat(t).map(|t| Ok(t));
    stream::iter(ts)
        .boxed()
}

//#[derive(Clone)]
#[allow(dead_code)]
pub struct TaskDataMut<A>(TaskData<RefCell<A>>);

impl<A> Clone for TaskDataMut<A> {
    fn clone(&self) -> Self {
        TaskDataMut(self.0.clone())
    }
}

#[allow(dead_code)]
impl<A> TaskDataMut<A> {

    pub fn new(a: A) -> TaskDataMut<A> {
        TaskDataMut(TaskData::new(RefCell::new(a)))
    }

    pub fn with<F, R>(&self, f: F) -> R
        where F: FnOnce(&mut A) -> R
    {
        self.0.with(|d| f(&mut *d.borrow_mut()))
    }

}

pub struct TaskDataMutex<A>(TaskData<Arc<Mutex<A>>>);

impl<A> Clone for TaskDataMutex<A> {
    fn clone(&self) -> Self {
        TaskDataMutex(self.0.clone())
    }
}

impl<A> TaskDataMutex<A> {

    pub fn new(a: A) -> TaskDataMutex<A> {
        TaskDataMutex(TaskData::new(Arc::new(Mutex::new(a))))
    }

    pub fn with<F, R>(&self, f: F) -> R
        where F: FnOnce(&mut A) -> R
    {
        self.0.with(|d| f(&mut *d.lock().unwrap()))
    }

}
<commit_msg>safer future_to_stream<commit_after>use std::cell::RefCell;

use std::sync::Arc;
use std::sync::Mutex;
use std::iter;

use futures::*;
use futures::stream::Stream;
use futures::stream::BoxStream;
use futures::task::TaskData;

enum FutureToStreamState<F> {
    Future(F),
    Eof,
    Done,
}

pub struct FutureToStream<F> {
    future: FutureToStreamState<F>,
}

pub fn future_to_stream<F : Future>(f: F) -> FutureToStream<F> {
    FutureToStream {
        future: FutureToStreamState::Future(f)
    }
}

impl<F : Future> Stream for FutureToStream<F> {
    type Item = F::Item;
    type Error = F::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let r = match &mut self.future {
            r @ &mut FutureToStreamState::Eof => {
                *r = FutureToStreamState::Done;
                return Poll::Ok(None)
            },
            &mut FutureToStreamState::Done => {
                panic!("cannot poll after eof");
            },
            &mut FutureToStreamState::Future(ref mut future) => match future.poll() {
                Poll::NotReady => return Poll::NotReady,
                Poll::Err(e) => return Poll::Err(e),
                Poll::Ok(r) => r,
            }
        };

        self.future = FutureToStreamState::Eof;

        Poll::Ok(Some(r))
    }
}

#[allow(dead_code)]
pub fn future_success<T : Send + 'static, E : Send + 'static>(t: T) -> BoxFuture<T, E> {
    done(Ok(t))
        .boxed()
}

#[allow(dead_code)]
pub fn stream_repeat<T : Clone + Send + 'static, E>(t: T) -> BoxStream<T, E> {
    let ts = iter::repeat(t).map(|t| Ok(t));
    stream::iter(ts)
        .boxed()
}

//#[derive(Clone)]
#[allow(dead_code)]
pub struct TaskDataMut<A>(TaskData<RefCell<A>>);

impl<A> Clone for TaskDataMut<A> {
    fn clone(&self) -> Self {
        TaskDataMut(self.0.clone())
    }
}

#[allow(dead_code)]
impl<A> TaskDataMut<A> {

    pub fn new(a: A) -> TaskDataMut<A> {
        TaskDataMut(TaskData::new(RefCell::new(a)))
    }

    pub fn with<F, R>(&self, f: F) -> R
        where F: FnOnce(&mut A) -> R
    {
        self.0.with(|d| f(&mut *d.borrow_mut()))
    }

}

pub struct TaskDataMutex<A>(TaskData<Arc<Mutex<A>>>);

impl<A> Clone for TaskDataMutex<A> {
    fn clone(&self) -> Self {
        TaskDataMutex(self.0.clone())
    }
}

impl<A> TaskDataMutex<A> {

    pub fn new(a: A) -> TaskDataMutex<A> {
        TaskDataMutex(TaskData::new(Arc::new(Mutex::new(a))))
    }

    pub fn with<F, R>(&self, f: F) -> R
        where F: FnOnce(&mut A) -> R
    {
        self.0.with(|d| f(&mut *d.lock().unwrap()))
    }

}
<|endoftext|>