<commit_before>//! Operations on manifest files.

use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, BufRead};
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};
use std::string::FromUtf8Error;
use std::usize;

/// Manifest file info.
pub struct Manifest {
    hostname: String,
    local_dir: PathBuf,
    volumes: Vec<Option<Volume>>,
}

/// Volume info.
pub struct Volume {
    start_path: PathBuf,
    end_path: PathBuf,
    start_block: Option<usize>,
    end_block: Option<usize>,
    hash_type: String,
    hash: Vec<u8>,
}

/// wip
#[derive(Debug)]
pub enum ParseError {
    /// wip
    Io(io::Error),
    /// wip
    MissingKeyword(String),
    /// wip
    Utf8Error(FromUtf8Error),
}

struct ManifestParser<R> {
    input: R,
    buf: Vec<u8>,
    hostname: String,
    local_dir: Vec<u8>,
    volumes: Vec<Option<Volume>>,
}

impl Manifest {
    /// Parses a stream to get a manifest.
    pub fn parse<R: BufRead>(m: &mut R) -> Result<Self, ParseError> {
        let parser = ManifestParser::new(m);
        parser.parse()
    }

    /// wip
    pub fn hostname(&self) -> Option<&str> {
        Some(&self.hostname)
    }

    /// wip
    pub fn local_dir(&self) -> Option<&Path> {
        Some(&self.local_dir)
    }

    /// wip
    pub fn max_vol_num(&self) -> usize {
        self.volumes.len()
    }

    /// wip
    pub fn volume(&self, num: usize) -> Option<&Volume> {
        self.volumes.get(num).and_then(|v| v.as_ref())
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::Io(ref err) => err.description(),
            ParseError::MissingKeyword(_) => "missing keyword in manifest",
            ParseError::Utf8Error(ref err) => err.description(),
        }
    }
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::Io(ref e) => write!(fmt, "{}", e),
            ParseError::MissingKeyword(ref e) => write!(fmt, "missing keyword '{}' in manifest", e),
            ParseError::Utf8Error(ref e) => write!(fmt, "{}", e),
        }
    }
}

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

impl From<FromUtf8Error> for ParseError {
    fn from(err: FromUtf8Error) -> ParseError {
        ParseError::Utf8Error(err)
    }
}

impl<R: BufRead> ManifestParser<R> {
    pub fn new(input: R) -> Self {
        ManifestParser {
            input: input,
            buf: vec![],
            hostname: String::new(),
            local_dir: vec![],
            volumes: vec![],
        }
    }

    pub fn parse(mut self) -> Result<Manifest, ParseError> {
        self.hostname = try!(self.read_param_str("Hostname"));
        self.local_dir = try!(self.read_param_bytes("Localdir"));

        while let Some((vol, i)) = try!(self.read_volume()) {
            // resize volumes if necessary
            if i >= self.volumes.len() {
                self.volumes.reserve(i + 1);
                for _ in self.volumes.len()..i + 1 {
                    self.volumes.push(None);
                }
            }
            self.volumes[i] = Some(vol);
        }

        // make result
        unimplemented!()
    }

    fn read_volume(&mut self) -> Result<Option<(Volume, usize)>, ParseError> {
        // volume number
        let mut param = try!(self.read_param_str("Volume"));
        if param.ends_with(":") {
            param.pop();
        }
        let num = usize::from_str(&param);

        unimplemented!()
    }

    fn read_param_bytes(&mut self, key: &str) -> Result<Vec<u8>, ParseError> {
        try!(self.consume_whitespace());
        if !try!(self.consume_keyword(key)) {
            return Err(ParseError::MissingKeyword(key.to_owned()));
        }
        try!(self.consume_whitespace());
        match self.read_param_value() {
            Ok(res) => {
                try!(self.consume_newline());
                Ok(res)
            }
            Err(e) => Err(From::from(e)),
        }
    }

    fn read_param_str(&mut self, key: &str) -> Result<String, ParseError> {
        let bytes = try!(self.read_param_bytes(key));
        String::from_utf8(bytes).map_err(From::from)
    }

    fn consume_keyword(&mut self, key: &str) -> io::Result<bool> {
        try!(self.input.read_until(b' ', &mut self.buf));
        Ok(match_keyword(&self.buf, key))
    }

    fn consume_newline(&mut self) -> io::Result<()> {
        self.consume_until(|b| {
            match b {
                b' ' | b'\t' | b'\r' | b'\n' => true,
                _ => false,
            }
        })
    }

    fn consume_whitespace(&mut self) -> io::Result<()> {
        self.consume_until(|b| {
            match b {
                b' ' | b'\t' => true,
                _ => false,
            }
        })
    }

    fn consume_until<F>(&mut self, mut f: F) -> io::Result<()>
        where F: FnMut(u8) -> bool
    {
        loop {
            let (pos, end) = {
                let buf = try!(self.input.fill_buf());
                match buf.iter().cloned().position(&mut f) {
                    Some(p) => (p, true),
                    None => (buf.len(), buf.is_empty()),
                }
            };
            self.input.consume(pos);
            if end {
                return Ok(());
            }
        }
    }

    fn read_param_value(&mut self) -> io::Result<Vec<u8>> {
        if try!(self.consume_byte(b'"')) {
            try!(self.input.read_until(b'"', &mut self.buf));
        } else {
            try!(self.input.read_until(b'\n', &mut self.buf));
        }
        let mut result = Vec::with_capacity(self.buf.len());
        // unescape
        for (i, b) in self.buf.iter().cloned().enumerate() {
            if b != b'\\' {
                result.push(b);
            } else {
                // expects a \xNN where NN is a number string representing the escaped char in hex
                // e.g. \x20 is the space ' '
                if self.buf.len() - i >= 4 && self.buf[i + 1] == b'x' {
                    let num = (self.buf[i + 2] - b'0') << 4 + self.buf[i + 3] - b'0';
                    result.push(num);
                }
            }
        }
        Ok(result)
    }

    fn consume_byte(&mut self, expected: u8) -> io::Result<bool> {
        let found = {
            let buf = try!(self.input.fill_buf());
            buf.first().map_or(false, |b| *b == expected)
        };
        if found {
            self.input.consume(1);
        }
        Ok(found)
    }
}

#[inline]
fn match_keyword(buf: &[u8], key: &str) -> bool {
    str::from_utf8(&buf).ok().map_or(false, |s| s == key)
}
<commit_msg>Working on LineReader<commit_after>//! Operations on manifest files.

use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::io::{self, BufRead, Read};
use std::path::{Path, PathBuf};
use std::str::{self, FromStr};
use std::string::FromUtf8Error;
use std::usize;

/// Manifest file info.
pub struct Manifest {
    hostname: String,
    local_dir: PathBuf,
    volumes: Vec<Option<Volume>>,
}

/// Volume info.
pub struct Volume {
    start_path: PathBuf,
    end_path: PathBuf,
    start_block: Option<usize>,
    end_block: Option<usize>,
    hash_type: String,
    hash: Vec<u8>,
}

/// wip
#[derive(Debug)]
pub enum ParseError {
    /// wip
    Io(io::Error),
    /// wip
    MissingKeyword(String),
    /// wip
    Utf8Error(FromUtf8Error),
}

struct ManifestParser<R> {
    input: R,
    buf: Vec<u8>,
    hostname: String,
    local_dir: Vec<u8>,
    volumes: Vec<Option<Volume>>,
}

struct LineReader<'a, R: 'a>(&'a mut R);

impl Manifest {
    /// Parses a stream to get a manifest.
    pub fn parse<R: BufRead>(m: &mut R) -> Result<Self, ParseError> {
        let parser = ManifestParser::new(m);
        parser.parse()
    }

    /// wip
    pub fn hostname(&self) -> Option<&str> {
        Some(&self.hostname)
    }

    /// wip
    pub fn local_dir(&self) -> Option<&Path> {
        Some(&self.local_dir)
    }

    /// wip
    pub fn max_vol_num(&self) -> usize {
        self.volumes.len()
    }

    /// wip
    pub fn volume(&self, num: usize) -> Option<&Volume> {
        self.volumes.get(num).and_then(|v| v.as_ref())
    }
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::Io(ref err) => err.description(),
            ParseError::MissingKeyword(_) => "missing keyword in manifest",
            ParseError::Utf8Error(ref err) => err.description(),
        }
    }
}

impl Display for ParseError {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        match *self {
            ParseError::Io(ref e) => write!(fmt, "{}", e),
            ParseError::MissingKeyword(ref e) => write!(fmt, "missing keyword '{}' in manifest", e),
            ParseError::Utf8Error(ref e) => write!(fmt, "{}", e),
        }
    }
}

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

impl From<FromUtf8Error> for ParseError {
    fn from(err: FromUtf8Error) -> ParseError {
        ParseError::Utf8Error(err)
    }
}

impl<R: BufRead> ManifestParser<R> {
    pub fn new(input: R) -> Self {
        ManifestParser {
            input: input,
            buf: vec![],
            hostname: String::new(),
            local_dir: vec![],
            volumes: vec![],
        }
    }

    pub fn parse(mut self) -> Result<Manifest, ParseError> {
        self.hostname = try!(self.read_param_str("Hostname"));
        self.local_dir = try!(self.read_param_bytes("Localdir"));

        while let Some((vol, i)) = try!(self.read_volume()) {
            // resize volumes if necessary
            if i >= self.volumes.len() {
                self.volumes.reserve(i + 1);
                for _ in self.volumes.len()..i + 1 {
                    self.volumes.push(None);
                }
            }
            self.volumes[i] = Some(vol);
        }

        // make result
        unimplemented!()
    }

    fn read_volume(&mut self) -> Result<Option<(Volume, usize)>, ParseError> {
        // volume number
        let mut param = try!(self.read_param_str("Volume"));
        if param.ends_with(":") {
            param.pop();
        }
        let num = usize::from_str(&param);

        unimplemented!()
    }

    fn read_param_bytes(&mut self, key: &str) -> Result<Vec<u8>, ParseError> {
        try!(self.consume_whitespace());
        if !try!(self.consume_keyword(key)) {
            return Err(ParseError::MissingKeyword(key.to_owned()));
        }
        try!(self.consume_whitespace());
        match self.read_param_value() {
            Ok(res) => {
                try!(self.consume_newline());
                Ok(res)
            }
            Err(e) => Err(From::from(e)),
        }
    }

    fn read_param_str(&mut self, key: &str) -> Result<String, ParseError> {
        let bytes = try!(self.read_param_bytes(key));
        String::from_utf8(bytes).map_err(From::from)
    }

    fn consume_keyword(&mut self, key: &str) -> io::Result<bool> {
        try!(self.input.read_until(b' ', &mut self.buf));
        Ok(match_keyword(&self.buf, key))
    }

    fn consume_newline(&mut self) -> io::Result<()> {
        self.consume_until(|b| {
            match b {
                b' ' | b'\t' | b'\r' | b'\n' => true,
                _ => false,
            }
        })
    }

    fn consume_whitespace(&mut self) -> io::Result<()> {
        self.consume_until(|b| {
            match b {
                b' ' | b'\t' => true,
                _ => false,
            }
        })
    }

    fn consume_until<F>(&mut self, mut f: F) -> io::Result<()>
        where F: FnMut(u8) -> bool
    {
        loop {
            let (pos, end) = {
                let buf = try!(self.input.fill_buf());
                match buf.iter().cloned().position(&mut f) {
                    Some(p) => (p, true),
                    None => (buf.len(), buf.is_empty()),
                }
            };
            self.input.consume(pos);
            if end {
                return Ok(());
            }
        }
    }

    fn read_param_value(&mut self) -> io::Result<Vec<u8>> {
        if try!(self.consume_byte(b'"')) {
            try!(self.input.read_until(b'"', &mut self.buf));
        } else {
            try!(self.input.read_until(b'\n', &mut self.buf));
        }
        let mut result = Vec::with_capacity(self.buf.len());
        // unescape
        for (i, b) in self.buf.iter().cloned().enumerate() {
            if b != b'\\' {
                result.push(b);
            } else {
                // expects a \xNN where NN is a number string representing the escaped char in hex
                // e.g. \x20 is the space ' '
                if self.buf.len() - i >= 4 && self.buf[i + 1] == b'x' {
                    let num = (self.buf[i + 2] - b'0') << 4 + self.buf[i + 3] - b'0';
                    result.push(num);
                }
            }
        }
        Ok(result)
    }

    fn consume_byte(&mut self, expected: u8) -> io::Result<bool> {
        let found = {
            let buf = try!(self.input.fill_buf());
            buf.first().map_or(false, |b| *b == expected)
        };
        if found {
            self.input.consume(1);
        }
        Ok(found)
    }
}

impl<'a, R: BufRead + 'a> BufRead for LineReader<'a, R> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        let buf = try!(self.0.fill_buf());
        Ok(filter_newline(buf))
    }

    fn consume(&mut self, amt: usize) {
        self.0.consume(amt);
    }
}

impl<'a, R: Read + 'a> Read for LineReader<'a, R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        let size = try!(self.0.read(buf));
        Ok(filter_newline(&buf[0..size]).len())
    }
}

#[inline]
fn match_keyword(buf: &[u8], key: &str) -> bool {
    str::from_utf8(&buf).ok().map_or(false, |s| s == key)
}

fn filter_newline<'b>(buf: &[u8]) -> &[u8] {
    match buf.iter().cloned().position(|b| b == b'\n') {
        Some(pos) => buf.split_at(pos).0,
        None => buf,
    }
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

//! The `metadata` module deals with metadata at the beginning of a FLAC stream.

use error::{Result, fmt_err};
use input::ReadBytes;

#[derive(Clone, Copy)]
struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32,
}

/// The streaminfo metadata block, with important information about the stream.
#[derive(Clone, Copy)]
pub struct StreamInfo {
    // TODO: "size" would better be called "duration" for clarity.

    /// The minimum block size (in samples) used in the stream.
    pub min_block_size: u16,
    /// The maximum block size (in samples) used in the stream.
    pub max_block_size: u16,
    /// The minimum frame size (in bytes) used in the stream.
    pub min_frame_size: Option<u32>,
    /// The maximum frame size (in bytes) used in the stream.
    pub max_frame_size: Option<u32>,
    /// The sample rate in Hz.
    pub sample_rate: u32,
    /// The number of channels.
    pub channels: u32,
    /// The number of bits per sample.
    pub bits_per_sample: u32,
    /// The total number of inter-channel samples in the stream.
    pub samples: Option<u64>,
    /// MD5 signature of the unencoded audio data.
    pub md5sum: [u8; 16],
}

/// A seek point in the seek table.
#[derive(Clone, Copy)]
pub struct SeekPoint {
    /// Sample number of the first sample in the target frame, or 2^64 - 1 for a placeholder.
    pub sample: u64,
    /// Offset in bytes from the first byte of the first frame header to the first byte of the
    /// target frame's header.
    pub offset: u64,
    /// Number of samples in the target frame.
    pub samples: u16,
}

/// A seek table to aid seeking in the stream.
pub struct SeekTable {
    /// The seek points, sorted in ascending order by sample number.
    #[allow(dead_code)] // TODO: Implement seeking.
    seekpoints: Vec<SeekPoint>,
}

/// A metadata about the flac stream.
pub enum MetadataBlock {
    /// A stream info block.
    StreamInfo(StreamInfo),
    /// A padding block (with no meaningful data).
    Padding {
        /// The number of padding bytes.
        length: u32,
    },
    /// An application block with application-specific data.
    Application {
        /// The registered application ID.
        id: u32,
        /// The contents of the application block.
        data: Vec<u8>,
    },
    /// A seek table block.
    SeekTable(SeekTable),
    /// A Vorbis comment block, also known as FLAC tags.
    VorbisComment, // TODO
    /// A CUE sheet block.
    CueSheet, // TODO
    /// A picture block.
    Picture, // TODO
    /// A block with a reserved block type, not supported by this library.
    Reserved,
}

fn read_metadata_block_header<R: ReadBytes>(input: &mut R) -> Result<MetadataBlockHeader> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte >> 7) == 1;
    let block_type = byte & 0b0111_1111;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_u24());

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length,
    };
    Ok(header)
}

fn read_metadata_block<R: ReadBytes>(input: &mut R,
                                     block_type: u8,
                                     length: u32)
                                     -> Result<MetadataBlock> {
    match block_type {
        0 => {
            // The streaminfo block has a fixed size of 34 bytes.
            if length == 34 {
                let streaminfo = try!(read_streaminfo_block(input));
                Ok(MetadataBlock::StreamInfo(streaminfo))
            } else {
                fmt_err("invalid streaminfo metadata block length")
            }
        }
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        }
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application {
                id: id,
                data: data,
            })
        }
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        127 => {
            // This code is invalid to avoid confusion with a frame sync code.
            fmt_err("invalid metadata block type")
        }
        _ => {
            // Any other block type is 'reserved' at the moment of writing. The
            // reference implementation reads it as an 'unknown' block. That is
            // one way of handling it, but maybe there should be some kind of
            // 'strict' mode (configurable at compile time?) so that this can
            // be an error if desired.
            try!(input.skip(length));
            Ok(MetadataBlock::Reserved)
        }
    }
}

fn read_streaminfo_block<R: ReadBytes>(input: &mut R) -> Result<StreamInfo> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_u24());
    let max_frame_size = try!(input.read_be_u24());

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_u8());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = (sample_rate_msb as u32) << 4 | (sample_rate_lsb as u32) >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0b0000_0111) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_u8());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0b0000_1111;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = (n_samples_msb as u64) << 32 | n_samples_lsb as u64;

    // Next are 128 bits (16 bytes) of MD5 signature.
    let mut md5sum = [0u8; 16];
    try!(input.read_into(&mut md5sum));

    // Lower bounds can never be larger than upper bounds. Note that 0 indicates
    // unknown for the frame size. Also, the block size must be at least 16.
    if min_block_size > max_block_size {
        return fmt_err("inconsistent bounds, min block size > max block size");
    }
    if min_block_size < 16 {
        return fmt_err("invalid block size, must be at least 16");
    }
    if min_frame_size > max_frame_size && max_frame_size != 0 {
        return fmt_err("inconsistent bounds, min frame size > max frame size");
    }

    // A sample rate of 0 is invalid, and the maximum sample rate is limited by
    // the structure of the frame headers to 655350 Hz.
    if sample_rate == 0 || sample_rate > 655350 {
        return fmt_err("invalid sample rate");
    }

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 {
            None
        } else {
            Some(min_frame_size)
        },
        max_frame_size: if max_frame_size == 0 {
            None
        } else {
            Some(max_frame_size)
        },
        sample_rate: sample_rate,
        channels: n_channels as u32,
        bits_per_sample: bits_per_sample as u32,
        samples: if n_samples == 0 {
            None
        } else {
            Some(n_samples)
        },
        md5sum: md5sum,
    };
    Ok(stream_info)
}

fn read_padding_block<R: ReadBytes>(input: &mut R, length: u32) -> Result<()> {
    // The specification dictates that all bits of the padding block must be 0.
    // However, the reference implementation does not issue an error when this
    // is not the case, and frankly, when you are going to skip over these
    // bytes and do nothing with them whatsoever, why waste all those CPU
    // cycles checking that the padding is valid?
    Ok(try!(input.skip(length)))
}

fn read_application_block<R: ReadBytes>(input: &mut R, length: u32) -> Result<(u32, Vec<u8>)> {
    if length < 4 {
        return fmt_err("application block length must be at least 4 bytes.")
    }

    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    // Create a vector of uninitialized memory, and read the block into it. The
    // uninitialized memory is never exposed: read_into will either fill the
    // buffer completely, or return an err, in which case the memory is not
    // exposed.
    let mut data = Vec::with_capacity(length as usize - 4);
    unsafe { data.set_len(length as usize - 4); }
    try!(input.read_into(&mut data));

    Ok((id, data))
}

/// Reads metadata blocks from a stream and exposes them as an iterator.
///
/// It is assumed that the next byte that the reader will read, is the first
/// byte of a metadata block header. This means that the iterator will yield at
/// least a single value. If the iterator ever yields an error, then no more
/// data will be read thereafter, and the next value will be `None`.
pub struct MetadataBlockReader<R: ReadBytes> {
    input: R,
    done: bool,
}

/// Either a `MetadataBlock` or an `Error`.
pub type MetadataBlockResult = Result<MetadataBlock>;

impl<R: ReadBytes> MetadataBlockReader<R> {
    /// Creates a metadata block reader that will yield at least one element.
    pub fn new(input: R) -> MetadataBlockReader<R> {
        MetadataBlockReader {
            input: input,
            done: false,
        }
    }

    fn read_next(&mut self) -> MetadataBlockResult {
        let header = try!(read_metadata_block_header(&mut self.input));
        let block = try!(read_metadata_block(&mut self.input, header.block_type, header.length));
        self.done = header.is_last;
        Ok(block)
    }
}

impl<R: ReadBytes> Iterator for MetadataBlockReader<R> {
    type Item = MetadataBlockResult;

    fn next(&mut self) -> Option<MetadataBlockResult> {
        if self.done {
            None
        } else {
            let block = self.read_next();

            // After a failure, no more attempts to read will be made,
            // because we don't know where we are in the stream.
            if !block.is_ok() {
                self.done = true;
            }

            Some(block)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        // When done, there will be no more blocks,
        // when not done, there will be at least one more.
        if self.done { (0, Some(0)) } else { (1, None) }
    }
}
<commit_msg>Derive Debug for StreamInfo<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

//! The `metadata` module deals with metadata at the beginning of a FLAC stream.

use error::{Result, fmt_err};
use input::ReadBytes;

#[derive(Clone, Copy)]
struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32,
}

/// The streaminfo metadata block, with important information about the stream.
#[derive(Clone, Copy, Debug)]
pub struct StreamInfo {
    // TODO: "size" would better be called "duration" for clarity.

    /// The minimum block size (in samples) used in the stream.
    pub min_block_size: u16,
    /// The maximum block size (in samples) used in the stream.
    pub max_block_size: u16,
    /// The minimum frame size (in bytes) used in the stream.
    pub min_frame_size: Option<u32>,
    /// The maximum frame size (in bytes) used in the stream.
    pub max_frame_size: Option<u32>,
    /// The sample rate in Hz.
    pub sample_rate: u32,
    /// The number of channels.
    pub channels: u32,
    /// The number of bits per sample.
    pub bits_per_sample: u32,
    /// The total number of inter-channel samples in the stream.
    pub samples: Option<u64>,
    /// MD5 signature of the unencoded audio data.
    pub md5sum: [u8; 16],
}

/// A seek point in the seek table.
#[derive(Clone, Copy)]
pub struct SeekPoint {
    /// Sample number of the first sample in the target frame, or 2^64 - 1 for a placeholder.
    pub sample: u64,
    /// Offset in bytes from the first byte of the first frame header to the first byte of the
    /// target frame's header.
    pub offset: u64,
    /// Number of samples in the target frame.
    pub samples: u16,
}

/// A seek table to aid seeking in the stream.
pub struct SeekTable {
    /// The seek points, sorted in ascending order by sample number.
    #[allow(dead_code)] // TODO: Implement seeking.
    seekpoints: Vec<SeekPoint>,
}

/// A metadata about the flac stream.
pub enum MetadataBlock {
    /// A stream info block.
    StreamInfo(StreamInfo),
    /// A padding block (with no meaningful data).
    Padding {
        /// The number of padding bytes.
        length: u32,
    },
    /// An application block with application-specific data.
    Application {
        /// The registered application ID.
        id: u32,
        /// The contents of the application block.
        data: Vec<u8>,
    },
    /// A seek table block.
    SeekTable(SeekTable),
    /// A Vorbis comment block, also known as FLAC tags.
    VorbisComment, // TODO
    /// A CUE sheet block.
    CueSheet, // TODO
    /// A picture block.
    Picture, // TODO
    /// A block with a reserved block type, not supported by this library.
    Reserved,
}

fn read_metadata_block_header<R: ReadBytes>(input: &mut R) -> Result<MetadataBlockHeader> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte >> 7) == 1;
    let block_type = byte & 0b0111_1111;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_u24());

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length,
    };
    Ok(header)
}

fn read_metadata_block<R: ReadBytes>(input: &mut R,
                                     block_type: u8,
                                     length: u32)
                                     -> Result<MetadataBlock> {
    match block_type {
        0 => {
            // The streaminfo block has a fixed size of 34 bytes.
            if length == 34 {
                let streaminfo = try!(read_streaminfo_block(input));
                Ok(MetadataBlock::StreamInfo(streaminfo))
            } else {
                fmt_err("invalid streaminfo metadata block length")
            }
        }
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        }
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application {
                id: id,
                data: data,
            })
        }
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(input.skip(length));
            Ok(MetadataBlock::Padding { length: length })
        }
        127 => {
            // This code is invalid to avoid confusion with a frame sync code.
            fmt_err("invalid metadata block type")
        }
        _ => {
            // Any other block type is 'reserved' at the moment of writing. The
            // reference implementation reads it as an 'unknown' block. That is
            // one way of handling it, but maybe there should be some kind of
            // 'strict' mode (configurable at compile time?) so that this can
            // be an error if desired.
            try!(input.skip(length));
            Ok(MetadataBlock::Reserved)
        }
    }
}

fn read_streaminfo_block<R: ReadBytes>(input: &mut R) -> Result<StreamInfo> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_u24());
    let max_frame_size = try!(input.read_be_u24());

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_u8());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = (sample_rate_msb as u32) << 4 | (sample_rate_lsb as u32) >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0b0000_0111) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_u8());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0b0000_1111;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = (n_samples_msb as u64) << 32 | n_samples_lsb as u64;

    // Next are 128 bits (16 bytes) of MD5 signature.
    let mut md5sum = [0u8; 16];
    try!(input.read_into(&mut md5sum));

    // Lower bounds can never be larger than upper bounds. Note that 0 indicates
    // unknown for the frame size. Also, the block size must be at least 16.
    if min_block_size > max_block_size {
        return fmt_err("inconsistent bounds, min block size > max block size");
    }
    if min_block_size < 16 {
        return fmt_err("invalid block size, must be at least 16");
    }
    if min_frame_size > max_frame_size && max_frame_size != 0 {
        return fmt_err("inconsistent bounds, min frame size > max frame size");
    }

    // A sample rate of 0 is invalid, and the maximum sample rate is limited by
    // the structure of the frame headers to 655350 Hz.
    if sample_rate == 0 || sample_rate > 655350 {
        return fmt_err("invalid sample rate");
    }

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 {
            None
        } else {
            Some(min_frame_size)
        },
        max_frame_size: if max_frame_size == 0 {
            None
        } else {
            Some(max_frame_size)
        },
        sample_rate: sample_rate,
        channels: n_channels as u32,
        bits_per_sample: bits_per_sample as u32,
        samples: if n_samples == 0 {
            None
        } else {
            Some(n_samples)
        },
        md5sum: md5sum,
    };
    Ok(stream_info)
}

fn read_padding_block<R: ReadBytes>(input: &mut R, length: u32) -> Result<()> {
    // The specification dictates that all bits of the padding block must be 0.
    // However, the reference implementation does not issue an error when this
    // is not the case, and frankly, when you are going to skip over these
    // bytes and do nothing with them whatsoever, why waste all those CPU
    // cycles checking that the padding is valid?
    Ok(try!(input.skip(length)))
}

fn read_application_block<R: ReadBytes>(input: &mut R, length: u32) -> Result<(u32, Vec<u8>)> {
    if length < 4 {
        return fmt_err("application block length must be at least 4 bytes.")
    }

    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    // Create a vector of uninitialized memory, and read the block into it. The
    // uninitialized memory is never exposed: read_into will either fill the
    // buffer completely, or return an err, in which case the memory is not
    // exposed.
    let mut data = Vec::with_capacity(length as usize - 4);
    unsafe { data.set_len(length as usize - 4); }
    try!(input.read_into(&mut data));

    Ok((id, data))
}

/// Reads metadata blocks from a stream and exposes them as an iterator.
///
/// It is assumed that the next byte that the reader will read, is the first
/// byte of a metadata block header. This means that the iterator will yield at
/// least a single value. If the iterator ever yields an error, then no more
/// data will be read thereafter, and the next value will be `None`.
pub struct MetadataBlockReader<R: ReadBytes> {
    input: R,
    done: bool,
}

/// Either a `MetadataBlock` or an `Error`.
pub type MetadataBlockResult = Result<MetadataBlock>;

impl<R: ReadBytes> MetadataBlockReader<R> {
    /// Creates a metadata block reader that will yield at least one element.
    pub fn new(input: R) -> MetadataBlockReader<R> {
        MetadataBlockReader {
            input: input,
            done: false,
        }
    }

    fn read_next(&mut self) -> MetadataBlockResult {
        let header = try!(read_metadata_block_header(&mut self.input));
        let block = try!(read_metadata_block(&mut self.input, header.block_type, header.length));
        self.done = header.is_last;
        Ok(block)
    }
}

impl<R: ReadBytes> Iterator for MetadataBlockReader<R> {
    type Item = MetadataBlockResult;

    fn next(&mut self) -> Option<MetadataBlockResult> {
        if self.done {
            None
        } else {
            let block = self.read_next();

            // After a failure, no more attempts to read will be made,
            // because we don't know where we are in the stream.
            if !block.is_ok() {
                self.done = true;
            }

            Some(block)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        // When done, there will be no more blocks,
        // when not done, there will be at least one more.
        if self.done { (0, Some(0)) } else { (1, None) }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Vincent Vigneron. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at.your option.
// This file may not be copied, modified, or distributed
// except according to those terms.

extern crate itertools;

use std::collections::{HashSet,HashMap};
use std::fmt;                          // Formatter, format!, Display, Debug, write!
use std::error;
use std::result;

/// The `NFAError` type.
#[derive(Debug)]
pub enum NFAError {
    /// The transition from state `usize` with symbol `char` is defined twice.
    DuplicatedTransition(char,usize),
    /// No final state is specified.
    MissingFinalStates,
    /// No starting state is specified.
    MissingStartingState,
}

impl fmt::Display for NFAError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            NFAError::DuplicatedTransition(symb,state) => write!(f, "Duplicated transition ('{}',{}).", symb, state),
            NFAError::MissingFinalStates => write!(f, "Missing final states."),
            NFAError::MissingStartingState => write!(f, "Missing starting state."),
        }
    }
}

impl error::Error for NFAError {
    fn description(&self) -> &str {
        match *self {
            NFAError::DuplicatedTransition(_,_) => "Duplicated transition.",
            NFAError::MissingFinalStates => "Missing final states.",
            NFAError::MissingStartingState => "Missing starting state.",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

/// The type `NFA` represents a NonDeterministic Finite Automaton. The transitions
/// of the automatan are stored in a hashtable.
#[derive(Debug)]
pub struct NFA {
    transitions : HashMap<(char,usize),HashSet<usize>>,
    start       : usize,
    finals      : HashSet<usize>,
}

/// The `NFABuilder` follows the builder pattern and allows to create a Deterministic
/// Finite Automaton. The builder is moved at each call so it is necessary to bind
/// to a new variable the return value for each function of the builder.
///
/// # Errors
///
/// Return an error if the starting state is not specified.
///
/// Return an error if the final states are not specified.
///
/// # Examples
///
/// ```
/// extern crate automata;
///
/// use automata::nfa::core::*;
/// use std::error::Error;
///
/// fn main() {
///     // (abc)*
///     let nfa = NFABuilder::new()
///         .add_start(0)
///         .add_final(3)
///         .add_final(0)
///         .add_transition('a', 0, 1)
///         .add_transition('b', 1, 2)
///         .add_transition('c', 2, 3)
///         .add_transition('a', 3, 1)
///         .finalize();
/// }
/// ```
///
/// ```
/// extern crate automata;
///
/// use automata::nfa::core::*;
/// use std::error::Error;
///
/// fn main() {
///     let nfa = NFABuilder::new()
///         .add_start(4)
///         .add_transition('t', 0, 1)
///         .finalize();
///     match nfa {
///         Err(NFAError::MissingFinalStates) => assert!(true),
///         _ => assert!(false),
///     }
/// }
/// ```
///
/// ```
/// extern crate automata;
///
/// use automata::nfa::core::*;
/// use std::error::Error;
///
/// fn main() {
///     let nfa = NFABuilder::new()
///         .add_start(4)
///         .add_transition('t', 0, 1)
///         .add_transition('t', 0, 2)
///         .finalize();
///     match nfa {
///         Err(NFAError::DuplicatedTransition(symb,src)) => assert!((symb,src)==('t',0)),
///         _ => assert!(false),
///     }
/// }
/// ```
///
/// ```
/// extern crate automata;
///
/// use automata::nfa::core::*;
/// use std::error::Error;
///
/// fn main() {
///     let nfa = NFABuilder::new()
///         .add_final(4)
///         .add_transition('t', 0, 1)
///         .finalize();
///     match nfa {
///         Err(NFAError::MissingStartingState) => assert!(true),
///         _ => assert!(false),
///     }
/// }
/// ```
///
#[derive(Debug)]
pub struct NFABuilder {
    transitions : HashMap<(char,usize),HashSet<usize>>,
    start       : Option<usize>,
    finals      : HashSet<usize>,
}

/// Alias for result::Result<T,NFAError>.
pub type Result<T> = result::Result<T,NFAError>;

/// NFABuilding is the trait assiociated to the NFABuilder type. Each NFABuilder
/// should implement NFABuilding trait.
///
/// NFABuilder can generate some errors during the building stage. For instance,
/// one could try to insert a transition with two different destination states.
///
/// #Errors
///
/// If self contains a NFAerror then each function should transfer this error.
pub trait NFABuilding {
    /// Add a starting state to the NFA.
    ///
    /// # Errors
    ///
    /// In the futur will return a NFAError::DuplicatedStartingState if
    /// two starting states are added.
    fn add_start(mut self, state: usize) -> Result<NFABuilder>;

    /// Add a final state to the NFA.
    fn add_final(mut self, state: usize) -> Result<NFABuilder>;

    /// Add a transition to the NFA.
    ///
    /// # Errors
    ///
    /// Return a NFAError::DuplicatedTransition(symb,src) if a transtion
    /// with the same symb and src has already been inserted, even if
    /// the destination state is the same.
    fn add_transition(mut self, symb: char, src: usize, dest: usize) -> Result<NFABuilder>;

    /// Finalize the building of the NFA.
    ///
    /// # Errors
    ///
    /// Return a NFAError::MissingStartingState if no starting state is specified.
    ///
    /// Return a NFAError::MissingFinalStates if no final state is specified.
    fn finalize(self) -> Result<NFA>;
}

impl NFABuilder {
    /// Creates a new NFABuilder.
    pub fn new() -> Result<NFABuilder> {
        Ok(NFABuilder{transitions: HashMap::new(), start: None, finals: HashSet::new()})
    }
}

impl NFABuilding for NFABuilder {
    fn add_start(self, state: usize) -> Result<NFABuilder> {
        Ok(self).add_start(state)
    }

    fn add_final(self, state: usize) -> Result<NFABuilder> {
        Ok(self).add_final(state)
    }

    fn add_transition(self, symb: char, src: usize, dest: usize) -> Result<NFABuilder> {
        Ok(self).add_transition(symb,src,dest)
    }

    fn finalize(self) -> Result<NFA> {
        Ok(self).finalize()
    }
}

/// Implementing NFABuilding trait for Result<NFABuilder> allows
/// to chain the return value of the NFABuilder instead of unwrapping them
/// at each stage of the building process.
impl NFABuilding for Result<NFABuilder> {
    fn add_start(self, state: usize) -> Result<NFABuilder> {
        self.and_then(|mut nfa| {
            nfa.start = Some(state);
            Ok(nfa)
        })
    }

    fn add_final(self, state: usize) -> Result<NFABuilder> {
        self.and_then(|mut nfa| {
            nfa.finals.insert(state);
            Ok(nfa)
        })
    }

    fn add_transition(self, symb: char, src: usize, dest: usize) -> Result<NFABuilder> {
        self.and_then(|mut nfa| {
            {
                // A block is mandatory here because states borrow a value inside nfa.
                // Ok(nfa) moves nfa but if states is in the same block it will has the
                // same lifetime and it's not possible to move a borrowed value.
                let states = nfa.transitions.entry((symb,src)).or_insert(HashSet::new());
                (*states).insert(dest);
            }
            Ok(nfa)
        })
    }

    fn finalize(self) -> Result<NFA> {
        self.and_then(|nfa| {
            if nfa.start.is_none() {
                Err(NFAError::MissingStartingState)
            } else if nfa.finals.is_empty() {
                Err(NFAError::MissingFinalStates)
            } else {
                Ok(NFA{transitions: nfa.transitions, start: nfa.start.unwrap(), finals: nfa.finals})
            }
        })
    }
}

impl NFA {
    /// Test if an input string is a word of the language defined by the NFA.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate automata;
    ///
    /// use automata::nfa::core::*;
    /// use std::error::Error;
    ///
    /// fn main() {
    ///     // (abc)*
    ///     let nfa = NFABuilder::new()
    ///         .add_start(0)
    ///         .add_final(3)
    ///         .add_final(0)
    ///         .add_transition('a', 0, 1)
    ///         .add_transition('b', 1, 2)
    ///         .add_transition('c', 2, 3)
    ///         .add_transition('a', 3, 1)
    ///         .finalize();
    ///     match nfa {
    ///         Ok(nfa) => {
    ///            assert!(nfa.test("abc"));
    ///            assert!(nfa.test(""));
    ///            assert!(!nfa.test("a"));
    ///            assert!(!nfa.test("ab"));
    ///            assert!(!nfa.test("abca"));
    ///            assert!(!nfa.test("abcab"));
    ///            assert!(nfa.test("abcabcabc"));
    ///         },
    ///         Err(e) => println!("{}", e),
    ///     }
    /// }
    /// ```
    pub fn test(&self, input: &str) -> bool {
        let start : HashSet<_> = [self.start].iter().cloned().collect();
        let f = input
            .chars()
            .fold(Some(start), |states,c| {
                match states {
                    Some(n) => {
                        n.iter().fold(Some(HashSet::new()), |acc, state| {
                            match acc {
                                Some(acc) => {
                                    if let Some(trans) = self.transitions.get(&(c,*state)) {
                                        Some(acc.union(trans).cloned().collect())
                                    } else {
                                        None
                                    }
                                },
                                None => None,
                            }
                        })
                    },
                    None => None,
                }
            });
        match f {
            Some(states) => states.intersection(&self.finals).next().is_some(),
            None => false,
        }
    }
}

impl fmt::Display for NFA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "START: {}", self.start));
        try!(writeln!(f, "FINALS:"));
        for fi in self.finals.iter() {
            try!(writeln!(f,"  {}", fi));
        }
        try!(writeln!(f, "TRANSITIONS:"));
        for (tr,d) in self.transitions.iter() {
            let (c,s) = *tr;
            try!(writeln!(f, "  ({},{}) => {:?}", c, s, d));
        }
        write!(f, "")
    }
}

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

    #[test]
    fn test_nfa() {
        let nfa = NFABuilder::new()
            .add_start(0)
            .add_final(3)
            .add_transition('a', 0, 1)
            .add_transition('c', 0, 3)
            .add_transition('b', 1, 2)
            .add_transition('a', 2, 1)
            .add_transition('c', 2, 3)
            .finalize()
            .unwrap();
        let samples =
            vec![("ababac", false),
                 ("ababc", true),
                 ("", false),
                 ("abc", true),
                 ("c", true),
                 ("ac", false),
                 ("ababababababababababababababababababababc", true),];

        for (input,expected_result) in samples {
            assert!(nfa.test(input) == expected_result, "input false for: \"{}\"", input);
        }
    }

    #[test]
    fn test_nfa_builder() {
        let _nfa = NFABuilder::new()
            .add_start(0)
            .add_final(3)
            .add_transition('a', 0, 1)
            .add_transition('c', 0, 3)
            .add_transition('b', 1, 2)
            .add_transition('a', 2, 1)
            .add_transition('c', 2, 3)
            .finalize()
            .unwrap();
    }

    #[test]
    fn test_nfa_builder_duplicated_transition() {
        let nfa = NFABuilder::new()
            .add_start(0)
            .add_final(3)
            .add_transition('a', 0, 1)
            .add_transition('c', 0, 3)
            .add_transition('b', 1, 2)
            .add_transition('a', 2, 1)
            .add_transition('c', 2, 3)
            .add_transition('a', 0, 2)
            .finalize();
        match nfa {
            Err(NFAError::DuplicatedTransition(sy,sr)) => assert!((sy,sr) == ('a',0)),
            _ => assert!(false, "DuplicatedTransition expected."),
        }
    }

    #[test]
    fn test_nfa_builder_missing_start() {
        let nfa = NFABuilder::new()
            .add_final(3)
            .add_transition('a', 0, 1)
            .finalize();
        match nfa {
            Err(NFAError::MissingStartingState) => assert!(true),
            _ => assert!(false, "MissingStartingState expected."),
        }
    }

    #[test]
    fn test_nfa_builder_missing_finals() {
        let nfa = NFABuilder::new()
            .add_start(0)
            .add_transition('a', 0, 1)
            .finalize();
        match nfa {
            Err(NFAError::MissingFinalStates) => assert!(true),
            _ => assert!(false, "MissingFinalStates expected."),
        }
    }
}
<commit_msg>nfa::test<commit_after>// Copyright 2016 Vincent Vigneron. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at.your option.
// This file may not be copied, modified, or distributed
// except according to those terms.

extern crate itertools;

use std::collections::{HashSet,HashMap};
use std::fmt;                          // Formatter, format!, Display, Debug, write!
use std::error;
use std::result;

/// The `NFAError` type.
#[derive(Debug)]
pub enum NFAError {
    /// The transition from state `usize` with symbol `char` is defined twice.
    DuplicatedTransition(char,usize),
    /// No final state is specified.
    MissingFinalStates,
    /// No starting state is specified.
    MissingStartingState,
}

impl fmt::Display for NFAError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            NFAError::DuplicatedTransition(symb,state) => write!(f, "Duplicated transition ('{}',{}).", symb, state),
            NFAError::MissingFinalStates => write!(f, "Missing final states."),
            NFAError::MissingStartingState => write!(f, "Missing starting state."),
        }
    }
}

impl error::Error for NFAError {
    fn description(&self) -> &str {
        match *self {
            NFAError::DuplicatedTransition(_,_) => "Duplicated transition.",
            NFAError::MissingFinalStates => "Missing final states.",
            NFAError::MissingStartingState => "Missing starting state.",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        None
    }
}

/// The type `NFA` represents a NonDeterministic Finite Automaton. The transitions
/// of the automatan are stored in a hashtable.
#[derive(Debug)]
pub struct NFA {
    transitions : HashMap<(char,usize),HashSet<usize>>,
    start       : usize,
    finals      : HashSet<usize>,
}

/// The `NFABuilder` follows the builder pattern and allows to create a Deterministic
/// Finite Automaton. The builder is moved at each call so it is necessary to bind
/// to a new variable the return value for each function of the builder.
///
/// # Errors
///
/// Return an error if the starting state is not specified.
///
/// Return an error if the final states are not specified.
///
/// # Examples
///
/// ```
/// extern crate automata;
///
/// use automata::nfa::core::*;
/// use std::error::Error;
///
/// fn main() {
///     // (abc)*
///     let nfa = NFABuilder::new()
///         .add_start(0)
///         .add_final(3)
///         .add_final(0)
///         .add_transition('a', 0, 1)
///         .add_transition('b', 1, 2)
///         .add_transition('c', 2, 3)
///         .add_transition('a', 3, 1)
///         .finalize();
/// }
/// ```
///
/// ```
/// extern crate automata;
///
/// use automata::nfa::core::*;
/// use std::error::Error;
///
/// fn main() {
///     let nfa = NFABuilder::new()
///         .add_start(4)
///         .add_transition('t', 0, 1)
///         .finalize();
///     match nfa {
///         Err(NFAError::MissingFinalStates) => assert!(true),
///         _ => assert!(false),
///     }
/// }
/// ```
///
/// ```
/// extern crate automata;
///
/// use automata::nfa::core::*;
/// use std::error::Error;
///
/// fn main() {
///     let nfa = NFABuilder::new()
///         .add_start(4)
///         .add_transition('t', 0, 1)
///         .add_transition('t', 0, 2)
///         .finalize();
///     match nfa {
///         Err(NFAError::DuplicatedTransition(symb,src)) => assert!((symb,src)==('t',0)),
///         _ => assert!(false),
///     }
/// }
/// ```
///
/// ```
/// extern crate automata;
///
/// use automata::nfa::core::*;
/// use std::error::Error;
///
/// fn main() {
///     let nfa = NFABuilder::new()
///         .add_final(4)
///         .add_transition('t', 0, 1)
///         .finalize();
///     match nfa {
///         Err(NFAError::MissingStartingState) => assert!(true),
///         _ => assert!(false),
///     }
/// }
/// ```
///
#[derive(Debug)]
pub struct NFABuilder {
    transitions : HashMap<(char,usize),HashSet<usize>>,
    start       : Option<usize>,
    finals      : HashSet<usize>,
}

/// Alias for result::Result<T,NFAError>.
pub type Result<T> = result::Result<T,NFAError>;

/// NFABuilding is the trait assiociated to the NFABuilder type. Each NFABuilder
/// should implement NFABuilding trait.
///
/// NFABuilder can generate some errors during the building stage. For instance,
/// one could try to insert a transition with two different destination states.
///
/// #Errors
///
/// If self contains a NFAerror then each function should transfer this error.
pub trait NFABuilding {
    /// Add a starting state to the NFA.
    ///
    /// # Errors
    ///
    /// In the futur will return a NFAError::DuplicatedStartingState if
    /// two starting states are added.
    fn add_start(mut self, state: usize) -> Result<NFABuilder>;

    /// Add a final state to the NFA.
    fn add_final(mut self, state: usize) -> Result<NFABuilder>;

    /// Add a transition to the NFA.
    ///
    /// # Errors
    ///
    /// Return a NFAError::DuplicatedTransition(symb,src) if a transtion
    /// with the same symb and src has already been inserted, even if
    /// the destination state is the same.
    fn add_transition(mut self, symb: char, src: usize, dest: usize) -> Result<NFABuilder>;

    /// Finalize the building of the NFA.
    ///
    /// # Errors
    ///
    /// Return a NFAError::MissingStartingState if no starting state is specified.
    ///
    /// Return a NFAError::MissingFinalStates if no final state is specified.
    fn finalize(self) -> Result<NFA>;
}

impl NFABuilder {
    /// Creates a new NFABuilder.
    pub fn new() -> Result<NFABuilder> {
        Ok(NFABuilder{transitions: HashMap::new(), start: None, finals: HashSet::new()})
    }
}

impl NFABuilding for NFABuilder {
    fn add_start(self, state: usize) -> Result<NFABuilder> {
        Ok(self).add_start(state)
    }

    fn add_final(self, state: usize) -> Result<NFABuilder> {
        Ok(self).add_final(state)
    }

    fn add_transition(self, symb: char, src: usize, dest: usize) -> Result<NFABuilder> {
        Ok(self).add_transition(symb,src,dest)
    }

    fn finalize(self) -> Result<NFA> {
        Ok(self).finalize()
    }
}

/// Implementing NFABuilding trait for Result<NFABuilder> allows
/// to chain the return value of the NFABuilder instead of unwrapping them
/// at each stage of the building process.
impl NFABuilding for Result<NFABuilder> {
    fn add_start(self, state: usize) -> Result<NFABuilder> {
        self.and_then(|mut nfa| {
            nfa.start = Some(state);
            Ok(nfa)
        })
    }

    fn add_final(self, state: usize) -> Result<NFABuilder> {
        self.and_then(|mut nfa| {
            nfa.finals.insert(state);
            Ok(nfa)
        })
    }

    fn add_transition(self, symb: char, src: usize, dest: usize) -> Result<NFABuilder> {
        self.and_then(|mut nfa| {
            {
                // A block is mandatory here because states borrow a value inside nfa.
                // Ok(nfa) moves nfa but if states is in the same block it will has the
                // same lifetime and it's not possible to move a borrowed value.
                let states = nfa.transitions.entry((symb,src)).or_insert(HashSet::new());
                (*states).insert(dest);
            }
            Ok(nfa)
        })
    }

    fn finalize(self) -> Result<NFA> {
        self.and_then(|nfa| {
            if nfa.start.is_none() {
                Err(NFAError::MissingStartingState)
            } else if nfa.finals.is_empty() {
                Err(NFAError::MissingFinalStates)
            } else {
                Ok(NFA{transitions: nfa.transitions, start: nfa.start.unwrap(), finals: nfa.finals})
            }
        })
    }
}

impl NFA {
    /// Test if an input string is a word of the language defined by the NFA.
    ///
    /// # Examples
    ///
    /// ```
    /// extern crate automata;
    ///
    /// use automata::nfa::core::*;
    /// use std::error::Error;
    ///
    /// fn main() {
    ///     // (abc)*
    ///     let nfa = NFABuilder::new()
    ///         .add_start(0)
    ///         .add_final(3)
    ///         .add_final(0)
    ///         .add_transition('a', 0, 1)
    ///         .add_transition('b', 1, 2)
    ///         .add_transition('c', 2, 3)
    ///         .add_transition('a', 3, 1)
    ///         .finalize();
    ///     match nfa {
    ///         Ok(nfa) => {
    ///            assert!(nfa.test("abc"));
    ///            assert!(nfa.test(""));
    ///            assert!(!nfa.test("a"));
    ///            assert!(!nfa.test("ab"));
    ///            assert!(!nfa.test("abca"));
    ///            assert!(!nfa.test("abcab"));
    ///            assert!(nfa.test("abcabcabc"));
    ///         },
    ///         Err(e) => println!("{}", e),
    ///     }
    /// }
    /// ```
    pub fn test(&self, input: &str) -> bool {
        let start : HashSet<_> = [self.start].iter().cloned().collect();
        let f = input
            .chars()
            .fold(Some(start), |states,c| {
                states.and_then(|n| {
                    n.iter().fold(Some(HashSet::new()), |acc, state| {
                        acc.and_then(|acc| {
                            if let Some(trans) = self.transitions.get(&(c,*state)) {
                                Some(acc.union(trans).cloned().collect())
                            } else {
                                None
                            }
                        })
                    })
                })
            });
        match f {
            Some(states) => states.intersection(&self.finals).next().is_some(),
            None => false,
        }
    }
}

impl fmt::Display for NFA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "START: {}", self.start));
        try!(writeln!(f, "FINALS:"));
        for fi in self.finals.iter() {
            try!(writeln!(f,"  {}", fi));
        }
        try!(writeln!(f, "TRANSITIONS:"));
        for (tr,d) in self.transitions.iter() {
            let (c,s) = *tr;
            try!(writeln!(f, "  ({},{}) => {:?}", c, s, d));
        }
        write!(f, "")
    }
}

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

    #[test]
    fn test_nfa() {
        let nfa = NFABuilder::new()
            .add_start(0)
            .add_final(3)
            .add_transition('a', 0, 1)
            .add_transition('c', 0, 3)
            .add_transition('b', 1, 2)
            .add_transition('a', 2, 1)
            .add_transition('c', 2, 3)
            .finalize()
            .unwrap();
        let samples =
            vec![("ababac", false),
                 ("ababc", true),
                 ("", false),
                 ("abc", true),
                 ("c", true),
                 ("ac", false),
                 ("ababababababababababababababababababababc", true),];

        for (input,expected_result) in samples {
            assert!(nfa.test(input) == expected_result, "input false for: \"{}\"", input);
        }
    }

    #[test]
    fn test_nfa_builder() {
        let _nfa = NFABuilder::new()
            .add_start(0)
            .add_final(3)
            .add_transition('a', 0, 1)
            .add_transition('c', 0, 3)
            .add_transition('b', 1, 2)
            .add_transition('a', 2, 1)
            .add_transition('c', 2, 3)
            .finalize()
            .unwrap();
    }

    #[test]
    fn test_nfa_builder_duplicated_transition() {
        let nfa = NFABuilder::new()
            .add_start(0)
            .add_final(3)
            .add_transition('a', 0, 1)
            .add_transition('c', 0, 3)
            .add_transition('b', 1, 2)
            .add_transition('a', 2, 1)
            .add_transition('c', 2, 3)
            .add_transition('a', 0, 2)
            .finalize();
        match nfa {
            Err(NFAError::DuplicatedTransition(sy,sr)) => assert!((sy,sr) == ('a',0)),
            _ => assert!(false, "DuplicatedTransition expected."),
        }
    }

    #[test]
    fn test_nfa_builder_missing_start() {
        let nfa = NFABuilder::new()
            .add_final(3)
            .add_transition('a', 0, 1)
            .finalize();
        match nfa {
            Err(NFAError::MissingStartingState) => assert!(true),
            _ => assert!(false, "MissingStartingState expected."),
        }
    }

    #[test]
    fn test_nfa_builder_missing_finals() {
        let nfa = NFABuilder::new()
            .add_start(0)
            .add_transition('a', 0, 1)
            .finalize();
        match nfa {
            Err(NFAError::MissingFinalStates) => assert!(true),
            _ => assert!(false, "MissingFinalStates expected."),
        }
    }
}
<|endoftext|>


<commit_before>use routing;
use rpc;

use hash::Hash;
use bincode::serde;
use std::{net, io, thread, time};
use std::sync;
use std::sync::{Weak, Arc};

pub const SOCKET_BUFFER_SIZE_BYTES : usize = 65536;
pub const SOCKET_TIMEOUT_S         : u64   = 5;

/// Subotai node.
///
/// On construction, a detached thread for packet reception is
/// launched.
pub struct Node {
   resources: Arc<Resources>,
}

struct Resources {
   pub id   : Hash,
   table    : routing::Table,
   outbound : net::UdpSocket,
   inbound  : net::UdpSocket,
   state    : sync::Mutex<State>,
}

#[derive(Eq, PartialEq)]
enum State {
   Alive,
   Error,
   ShuttingDown,
}

impl Node {
   pub fn new(inbound_port: u16, outbound_port: u16) -> io::Result<Node> {
      let id = Hash::random();

      let resources = Arc::new(Resources {
         id         : id.clone(),
         table      : routing::Table::new(id),
         inbound    : try!(net::UdpSocket::bind(("0.0.0.0", inbound_port))),
         outbound   : try!(net::UdpSocket::bind(("0.0.0.0", outbound_port))),
         state      : sync::Mutex::new(State::Alive),
      });

      try!(resources.inbound.set_read_timeout(Some(time::Duration::new(SOCKET_TIMEOUT_S,0))));

      let weak_resources = Arc::downgrade(&resources);
      thread::spawn(move || { Node::reception_loop(weak_resources) });

      Ok( Node{ resources: resources } )
   }

   pub fn ping(&self, destination: routing::NodeInfo) {
      let resources = self.resources.clone();
      thread::spawn(move || {
         if let Some(address) = destination.address {
            let ping = rpc::Rpc::ping(resources.id.clone(), resources.inbound.local_addr().unwrap().port());
            let payload = ping.serialize();
            resources.outbound.send_to(&payload, address);
         }
      });
   }

   /// Receives and processes data as long as the table is alive.
   fn reception_loop(weak: Weak<Resources>) {
      let mut buffer = [0u8; SOCKET_BUFFER_SIZE_BYTES];

      while let Some(strong) = weak.upgrade() {
         if let State::ShuttingDown = *strong.state.lock().unwrap() {
            break;
         }

         if let Ok((_, source)) = strong.inbound.recv_from(&mut buffer) {
            strong.process_incoming_rpc(&buffer, source);
         }
      }
   }
}

impl Drop for Node {
   fn drop(&mut self) {
      *self.resources.state.lock().unwrap() = State::ShuttingDown;
   }
}

impl Resources {
   fn process_incoming_rpc(&self, buffer: &[u8], mut source: net::SocketAddr) -> serde::DeserializeResult<()> {
      let rpc = try!(rpc::Rpc::deserialize(buffer));

      source.set_port(rpc.reply_port);
      let sender = routing::NodeInfo {
         node_id : rpc.sender_id.clone(),
         address : Some(source),
      };

      match rpc.kind {
         rpc::Kind::Ping => self.handle_ping(rpc, sender),
         _ => (),
      }
      Ok(())
   }

   fn handle_ping(&self, ping: rpc::Rpc, sender: routing::NodeInfo){
      self.table.insert_node(sender);
      // TODO send ping response
   }
}

#[cfg(test)]
mod tests {
   use node;
   use rpc;
   use std::thread;
   use std::time;
   use routing;
   use std::net;
   use std::str::FromStr;
   pub const POLL_FREQUENCY_MS: u64 = 50;
   pub const TRIES: u8 = 5;

   #[test]
   fn node_ping() {
      let alpha = node::Node::new(50000, 50001).unwrap();
      let beta  = node::Node::new(50002, 50003).unwrap();

      let ip = net::IpAddr::from_str("127.0.0.1").unwrap();
      let address_beta = net::SocketAddr::new(ip, 50002);

      let info_beta = routing::NodeInfo {
         node_id : beta.resources.id.clone(),
         address : Some(address_beta),
      };

      // Before sending the ping, beta does not know about alpha.
      assert!(beta.resources.table.specific_node(&alpha.resources.id).is_none());

      // Alpha pings beta.
      alpha.ping(info_beta);

      // Eventually, beta knows of alpha.
      let mut found = beta.resources.table.specific_node(&alpha.resources.id);
      for _ in 0..TRIES {
         if found.is_some() {
            break;
         }
         found = beta.resources.table.specific_node(&alpha.resources.id);
         thread::sleep(time::Duration::from_millis(POLL_FREQUENCY_MS));
      }

      assert!(found.is_some());
   }
}
<commit_msg>In place deserialization<commit_after>use routing;
use rpc;

use hash::Hash;
use bincode::serde;
use std::{net, io, thread, time};
use std::sync;
use std::sync::{Weak, Arc};

pub const SOCKET_BUFFER_SIZE_BYTES : usize = 65536;
pub const SOCKET_TIMEOUT_S         : u64   = 5;

/// Subotai node.
///
/// On construction, a detached thread for packet reception is
/// launched.
pub struct Node {
   resources: Arc<Resources>,
}

struct Resources {
   pub id   : Hash,
   table    : routing::Table,
   outbound : net::UdpSocket,
   inbound  : net::UdpSocket,
   state    : sync::Mutex<State>,
}

#[derive(Eq, PartialEq)]
enum State {
   Alive,
   Error,
   ShuttingDown,
}

impl Node {
   pub fn new(inbound_port: u16, outbound_port: u16) -> io::Result<Node> {
      let id = Hash::random();

      let resources = Arc::new(Resources {
         id         : id.clone(),
         table      : routing::Table::new(id),
         inbound    : try!(net::UdpSocket::bind(("0.0.0.0", inbound_port))),
         outbound   : try!(net::UdpSocket::bind(("0.0.0.0", outbound_port))),
         state      : sync::Mutex::new(State::Alive),
      });

      try!(resources.inbound.set_read_timeout(Some(time::Duration::new(SOCKET_TIMEOUT_S,0))));

      let weak_resources = Arc::downgrade(&resources);
      thread::spawn(move || { Node::reception_loop(weak_resources) });

      Ok( Node{ resources: resources } )
   }

   pub fn ping(&self, destination: routing::NodeInfo) {
      let resources = self.resources.clone();
      thread::spawn(move || { resources.ping(destination) });
   }

   /// Receives and processes data as long as the table is alive.
   fn reception_loop(weak: Weak<Resources>) {
      let mut buffer = [0u8; SOCKET_BUFFER_SIZE_BYTES];

      while let Some(strong) = weak.upgrade() {
         if let State::ShuttingDown = *strong.state.lock().unwrap() {
            break;
         }

         if let Ok((_, source)) = strong.inbound.recv_from(&mut buffer) {
            if let Ok(rpc) = rpc::Rpc::deserialize(&buffer) {
               thread::spawn(move || { strong.process_incoming_rpc(rpc, source) } );
            }
         }
      }
   }
}

impl Drop for Node {
   fn drop(&mut self) {
      *self.resources.state.lock().unwrap() = State::ShuttingDown;
   }
}

impl Resources {
   pub fn ping(&self, destination: routing::NodeInfo) {
      if let Some(address) = destination.address {
         let ping = rpc::Rpc::ping(self.id.clone(), self.inbound.local_addr().unwrap().port());
         let payload = ping.serialize();
         self.outbound.send_to(&payload, address);
      }
   }

   fn process_incoming_rpc(&self, rpc: rpc::Rpc, mut source: net::SocketAddr) -> serde::DeserializeResult<()> {
      source.set_port(rpc.reply_port);
      let sender = routing::NodeInfo {
         node_id : rpc.sender_id.clone(),
         address : Some(source),
      };

      match rpc.kind {
         rpc::Kind::Ping => self.handle_ping(rpc, sender),
         _ => (),
      }
      Ok(())
   }

   fn handle_ping(&self, ping: rpc::Rpc, sender: routing::NodeInfo){
      self.table.insert_node(sender);
      // TODO send ping response
   }
}

#[cfg(test)]
mod tests {
   use node;
   use rpc;
   use std::thread;
   use std::time;
   use routing;
   use std::net;
   use std::str::FromStr;
   pub const POLL_FREQUENCY_MS: u64 = 50;
   pub const TRIES: u8 = 5;

   #[test]
   fn node_ping() {
      let alpha = node::Node::new(50000, 50001).unwrap();
      let beta  = node::Node::new(50002, 50003).unwrap();

      let ip = net::IpAddr::from_str("127.0.0.1").unwrap();
      let address_beta = net::SocketAddr::new(ip, 50002);

      let info_beta = routing::NodeInfo {
         node_id : beta.resources.id.clone(),
         address : Some(address_beta),
      };

      // Before sending the ping, beta does not know about alpha.
      assert!(beta.resources.table.specific_node(&alpha.resources.id).is_none());

      // Alpha pings beta.
      alpha.ping(info_beta);

      // Eventually, beta knows of alpha.
      let mut found = beta.resources.table.specific_node(&alpha.resources.id);
      for _ in 0..TRIES {
         if found.is_some() {
            break;
         }
         found = beta.resources.table.specific_node(&alpha.resources.id);
         thread::sleep(time::Duration::from_millis(POLL_FREQUENCY_MS));
      }

      assert!(found.is_some());
   }
}
<|endoftext|>


<commit_before>use routing;
use rpc;

use hash::Hash;
use bincode::serde;
use std::{net, io, thread, time};
use std::sync::{ Weak, Arc};

pub const SOCKET_BUFFER_SIZE_BYTES : usize = 65536;
pub const SOCKET_TIMEOUT_S         : u64   = 5;

/// Subotai node.
///
/// On construction, a detached thread for packet reception is
/// launched.
pub struct Node {
   resources: Arc<Resources>,
}

struct Resources {
   pub id   : Hash,
   table    : routing::Table,
   outbound : net::UdpSocket,
   inbound  : net::UdpSocket,
   state    : State,
}

enum State {
   Alive,
   Error,
   ShuttingDown,
}

impl Node {
   pub fn new(inbound_port: u16, outbound_port: u16) -> io::Result<Node> {
      let id = Hash::random();

      let resources = Arc::new(Resources {
         id         : id.clone(),
         table      : routing::Table::new(id),
         inbound    : try!(net::UdpSocket::bind(("0.0.0.0", inbound_port))),
         outbound   : try!(net::UdpSocket::bind(("0.0.0.0", outbound_port))),
         state      : State::Alive,
      });

      try!(resources.inbound.set_read_timeout(Some(time::Duration::new(SOCKET_TIMEOUT_S,0))));

      let weak_resources = Arc::downgrade(&resources);
      thread::spawn(move || { Node::reception_loop(weak_resources) });

      Ok( Node{ resources: resources } )
   }

   /// Sends an RPC to a destination node. If the node address is known, the RPC will
   /// be sent directly. Otherwise, a node lookup will be performed first.
   pub fn send_rpc(&self, rpc: &rpc::Rpc, destination: &routing::NodeInfo)-> io::Result<()> {
      if let Some(address) = destination.address {
         let payload = rpc.serialize();
         try!(self.resources.outbound.send_to(&payload, address));
      }
      else {
         // Perform lookup.
         unimplemented!();
      }
      Ok(())
   }

   /// Receives and processes data as long as the table is alive. Will gracefully exit, at most,
   /// `SOCKET_TIMEOUT_S` seconds after the table is dropped.
   fn reception_loop(weak: Weak<Resources>) {
      let mut buffer = [0u8; SOCKET_BUFFER_SIZE_BYTES];

      while let Some(strong) = weak.upgrade() {
         if let State::ShuttingDown = strong.state {
            break;
         }

         if let Ok((_, source)) = strong.inbound.recv_from(&mut buffer) {
            strong.process_incoming_rpc(&buffer, source);
         }
      }
   }
}

impl Resources {
   fn process_incoming_rpc(&self, buffer: &[u8], mut source: net::SocketAddr) -> serde::DeserializeResult<()> {
      let rpc = try!(rpc::Rpc::deserialize(buffer));

      source.set_port(rpc.reply_port);
      let sender = routing::NodeInfo {
         node_id : rpc.sender_id.clone(),
         address : Some(source),
      };

      match rpc.kind {
         rpc::Kind::Ping => self.handle_ping(rpc, sender),
         _ => (),
      }
      Ok(())
   }

   fn handle_ping(&self, ping: rpc::Rpc, sender: routing::NodeInfo){
      self.table.insert_node(sender);
      // TODO send ping response
   }
}

#[cfg(test)]
mod tests {
   use node;
   use rpc;
   use std::thread;
   use std::time;
   use routing;
   use std::net;
   use std::str::FromStr;
   pub const POLL_FREQUENCY_MS: u64 = 50;
   pub const TRIES: u8 = 5;

   #[test]
   fn node_ping() {
      let alpha = node::Node::new(50000, 50001).unwrap();
      let beta  = node::Node::new(50002, 50003).unwrap();

      let ip = net::IpAddr::from_str("127.0.0.1").unwrap();
      let address_beta = net::SocketAddr::new(ip, 50002);

      let info_beta = routing::NodeInfo {
         node_id : beta.resources.id.clone(),
         address : Some(address_beta),
      };
      let ping = rpc::Rpc::ping(alpha.resources.id.clone(), 50000);

      // Before sending the ping, beta does not know about alpha.
      assert!(beta.resources.table.specific_node(&alpha.resources.id).is_none());

      // Alpha pings beta.
      alpha.send_rpc(&ping, &info_beta);

      // Eventually, beta knows of alpha.
      let mut found = beta.resources.table.specific_node(&alpha.resources.id);
      for _ in 0..TRIES {
         if found.is_some() {
            break;
         }
         found = beta.resources.table.specific_node(&alpha.resources.id);
         thread::sleep(time::Duration::from_millis(POLL_FREQUENCY_MS));
      }

      assert!(found.is_some());
   }
}
<commit_msg>Ping api<commit_after>use routing;
use rpc;

use hash::Hash;
use bincode::serde;
use std::{net, io, thread, time};
use std::sync;
use std::sync::{Weak, Arc};

pub const SOCKET_BUFFER_SIZE_BYTES : usize = 65536;
pub const SOCKET_TIMEOUT_S         : u64   = 5;

/// Subotai node.
///
/// On construction, a detached thread for packet reception is
/// launched.
pub struct Node {
   resources: Arc<Resources>,
}

struct Resources {
   pub id   : Hash,
   table    : routing::Table,
   outbound : net::UdpSocket,
   inbound  : net::UdpSocket,
   state    : sync::Mutex<State>,
}

#[derive(Eq, PartialEq)]
enum State {
   Alive,
   Error,
   ShuttingDown,
}

impl Node {
   pub fn new(inbound_port: u16, outbound_port: u16) -> io::Result<Node> {
      let id = Hash::random();

      let resources = Arc::new(Resources {
         id         : id.clone(),
         table      : routing::Table::new(id),
         inbound    : try!(net::UdpSocket::bind(("0.0.0.0", inbound_port))),
         outbound   : try!(net::UdpSocket::bind(("0.0.0.0", outbound_port))),
         state      : sync::Mutex::new(State::Alive),
      });

      try!(resources.inbound.set_read_timeout(Some(time::Duration::new(SOCKET_TIMEOUT_S,0))));

      let weak_resources = Arc::downgrade(&resources);
      thread::spawn(move || { Node::reception_loop(weak_resources) });

      Ok( Node{ resources: resources } )
   }

   pub fn ping(&self, destination: routing::NodeInfo) {
      let resources = self.resources.clone();
      thread::spawn(move || {
         if let Some(address) = destination.address {
            let ping = rpc::Rpc::ping(resources.id.clone(), resources.inbound.local_addr().unwrap().port());
            let payload = ping.serialize();
            resources.outbound.send_to(&payload, address);
         }
      });
   }

   /// Receives and processes data as long as the table is alive.
   fn reception_loop(weak: Weak<Resources>) {
      let mut buffer = [0u8; SOCKET_BUFFER_SIZE_BYTES];

      while let Some(strong) = weak.upgrade() {
         if let State::ShuttingDown = *strong.state.lock().unwrap() {
            break;
         }

         if let Ok((_, source)) = strong.inbound.recv_from(&mut buffer) {
            strong.process_incoming_rpc(&buffer, source);
         }
      }
   }
}

impl Drop for Node {
   fn drop(&mut self) {
      *self.resources.state.lock().unwrap() = State::ShuttingDown;
   }
}

impl Resources {
   fn process_incoming_rpc(&self, buffer: &[u8], mut source: net::SocketAddr) -> serde::DeserializeResult<()> {
      let rpc = try!(rpc::Rpc::deserialize(buffer));

      source.set_port(rpc.reply_port);
      let sender = routing::NodeInfo {
         node_id : rpc.sender_id.clone(),
         address : Some(source),
      };

      match rpc.kind {
         rpc::Kind::Ping => self.handle_ping(rpc, sender),
         _ => (),
      }
      Ok(())
   }

   fn handle_ping(&self, ping: rpc::Rpc, sender: routing::NodeInfo){
      self.table.insert_node(sender);
      // TODO send ping response
   }
}

#[cfg(test)]
mod tests {
   use node;
   use rpc;
   use std::thread;
   use std::time;
   use routing;
   use std::net;
   use std::str::FromStr;
   pub const POLL_FREQUENCY_MS: u64 = 50;
   pub const TRIES: u8 = 5;

   #[test]
   fn node_ping() {
      let alpha = node::Node::new(50000, 50001).unwrap();
      let beta  = node::Node::new(50002, 50003).unwrap();

      let ip = net::IpAddr::from_str("127.0.0.1").unwrap();
      let address_beta = net::SocketAddr::new(ip, 50002);

      let info_beta = routing::NodeInfo {
         node_id : beta.resources.id.clone(),
         address : Some(address_beta),
      };

      // Before sending the ping, beta does not know about alpha.
      assert!(beta.resources.table.specific_node(&alpha.resources.id).is_none());

      // Alpha pings beta.
      alpha.ping(info_beta);

      // Eventually, beta knows of alpha.
      let mut found = beta.resources.table.specific_node(&alpha.resources.id);
      for _ in 0..TRIES {
         if found.is_some() {
            break;
         }
         found = beta.resources.table.specific_node(&alpha.resources.id);
         thread::sleep(time::Duration::from_millis(POLL_FREQUENCY_MS));
      }

      assert!(found.is_some());
   }
}
<|endoftext|>


<commit_before>use libc::c_int;

// socket

pub const FIOSETOWN: c_int = 0x00008901;
pub const SIOCSPGRP: c_int = 0x00008902;
pub const FIOGETOWN: c_int = 0x00008903;
pub const SIOCGPGRP: c_int = 0x00008904;
pub const SIOCGSTAMP: c_int = 0x00008906;

// termios

pub const TCGETS: c_int = 0x00005401;
pub const TCSETS: c_int = 0x00005402;
pub const TCSETSW: c_int = 0x00005403;
pub const TCSETSF: c_int = 0x00005404;
pub const TCGETA: c_int = 0x00005405;
pub const TCSETA: c_int = 0x00005406;
pub const TCSETAW: c_int = 0x00005407;
pub const TCSETAF: c_int = 0x00005408;
pub const TCSBRK: c_int = 0x00005409;
pub const TCXONC: c_int = 0x0000540a;
pub const TCFLSH: c_int = 0x0000540b;
pub const TIOCEXCL: c_int = 0x0000540c;
pub const TIOCNXCL: c_int = 0x0000540d;
pub const TIOCSCTTY: c_int = 0x0000540e;
pub const TIOCGPGRP: c_int = 0x0000540f;
pub const TIOCSPGRP: c_int = 0x00005410;
pub const TIOCOUTQ: c_int = 0x00005411;
pub const TIOCSTI: c_int = 0x00005412;
pub const TIOCGWINSZ: c_int = 0x00005413;
pub const TIOCSWINSZ: c_int = 0x00005414;
pub const TIOCMGET: c_int = 0x00005415;
pub const TIOCMBIS: c_int = 0x00005416;
pub const TIOCMBIC: c_int = 0x00005417;
pub const TIOCMSET: c_int = 0x00005418;
pub const TIOCGSOFTCAR: c_int = 0x00005419;
pub const TIOCSSOFTCAR: c_int = 0x0000541a;
pub const FIONREAD: c_int = 0x0000541b;
pub const TIOCINQ: c_int = 0x0000541b;
pub const TIOCLINUX: c_int = 0x0000541c;
pub const TIOCCONS: c_int = 0x0000541d;
pub const TIOCGSERIAL: c_int = 0x0000541e;
pub const TIOCSSERIAL: c_int = 0x0000541f;
pub const TIOCPKT: c_int = 0x00005420;
pub const FIONBIO: c_int = 0x00005421;
pub const TIOCNOTTY: c_int = 0x00005422;
pub const TIOCSETD: c_int = 0x00005423;
pub const TIOCGETD: c_int = 0x00005424;
pub const TCSBRKP: c_int = 0x00005425;
pub const FIONCLEX: c_int = 0x00005450;
pub const FIOCLEX: c_int = 0x00005451;
pub const FIOASYNC: c_int = 0x00005452;
pub const TIOCSERCONFIG: c_int = 0x00005453;
pub const TIOCSERGWILD: c_int = 0x00005454;
pub const TIOCSERSWILD: c_int = 0x00005455;
pub const TIOCGLCKTRMIOS: c_int = 0x00005456;
pub const TIOCSLCKTRMIOS: c_int = 0x00005457;
pub const TIOCSERGSTRUCT: c_int = 0x00005458;
pub const TIOCSERGETLSR: c_int = 0x00005459;
pub const TIOCSERGETMULTI: c_int = 0x0000545a;
pub const TIOCSERSETMULTI: c_int = 0x0000545b;

// sockios

pub const SIOCADDRT: c_int = 0x0000890b;
pub const SIOCDELRT: c_int = 0x0000890c;
pub const SIOCGIFNAME: c_int = 0x00008910;
pub const SIOCSIFLINK: c_int = 0x00008911;
pub const SIOCGIFCONF: c_int = 0x00008912;
pub const SIOCGIFFLAGS: c_int = 0x00008913;
pub const SIOCSIFFLAGS: c_int = 0x00008914;
pub const SIOCGIFADDR: c_int = 0x00008915;
pub const SIOCSIFADDR: c_int = 0x00008916;
pub const SIOCGIFDSTADDR: c_int = 0x00008917;
pub const SIOCSIFDSTADDR: c_int = 0x00008918;
pub const SIOCGIFBRDADDR: c_int = 0x00008919;
pub const SIOCSIFBRDADDR: c_int = 0x0000891a;
pub const SIOCGIFNETMASK: c_int = 0x0000891b;
pub const SIOCSIFNETMASK: c_int = 0x0000891c;
pub const SIOCGIFMETRIC: c_int = 0x0000891d;
pub const SIOCSIFMETRIC: c_int = 0x0000891e;
pub const SIOCGIFMEM: c_int = 0x0000891f;
pub const SIOCSIFMEM: c_int = 0x00008920;
pub const SIOCGIFMTU: c_int = 0x00008921;
pub const SIOCSIFMTU: c_int = 0x00008922;
pub const SIOCSIFHWADDR: c_int = 0x00008924;
pub const SIOCGIFENCAP: c_int = 0x00008925;
pub const SIOCSIFENCAP: c_int = 0x00008926;
pub const SIOCGIFHWADDR: c_int = 0x00008927;
pub const SIOCGIFSLAVE: c_int = 0x00008929;
pub const SIOCSIFSLAVE: c_int = 0x00008930;
pub const SIOCADDMULTI: c_int = 0x00008931;
pub const SIOCDELMULTI: c_int = 0x00008932;
pub const SIOCDARP: c_int = 0x00008953;
pub const SIOCGARP: c_int = 0x00008954;
pub const SIOCSARP: c_int = 0x00008955;
pub const SIOCDRARP: c_int = 0x00008960;
pub const SIOCGRARP: c_int = 0x00008961;
pub const SIOCSRARP: c_int = 0x00008962;
pub const SIOCGIFMAP: c_int = 0x00008970;
pub const SIOCSIFMAP: c_int = 0x00008971;

// modem control lines

pub const TIOCM_LE: c_int = 0x00000001;
pub const TIOCM_DTR: c_int = 0x00000002;
pub const TIOCM_RTS: c_int = 0x00000004;
pub const TIOCM_ST: c_int = 0x00000008;
pub const TIOCM_SR: c_int = 0x00000010;
pub const TIOCM_CTS: c_int = 0x00000020;
pub const TIOCM_CAR: c_int = 0x00000040;
pub const TIOCM_CD: c_int = 0x00000040;
pub const TIOCM_RNG: c_int = 0x00000080;
pub const TIOCM_RI: c_int = 0x00000080;
pub const TIOCM_DSR: c_int = 0x00000100;

extern "C" {
    pub fn ioctl(fd: c_int, request: c_int, ...) -> c_int;
}
<commit_msg>[close #3] fix request type on Linux<commit_after>use libc::{c_int, c_uint};

// socket

pub const FIOSETOWN: c_uint = 0x00008901;
pub const SIOCSPGRP: c_uint = 0x00008902;
pub const FIOGETOWN: c_uint = 0x00008903;
pub const SIOCGPGRP: c_uint = 0x00008904;
pub const SIOCGSTAMP: c_uint = 0x00008906;

// termios

pub const TCGETS: c_uint = 0x00005401;
pub const TCSETS: c_uint = 0x00005402;
pub const TCSETSW: c_uint = 0x00005403;
pub const TCSETSF: c_uint = 0x00005404;
pub const TCGETA: c_uint = 0x00005405;
pub const TCSETA: c_uint = 0x00005406;
pub const TCSETAW: c_uint = 0x00005407;
pub const TCSETAF: c_uint = 0x00005408;
pub const TCSBRK: c_uint = 0x00005409;
pub const TCXONC: c_uint = 0x0000540a;
pub const TCFLSH: c_uint = 0x0000540b;
pub const TIOCEXCL: c_uint = 0x0000540c;
pub const TIOCNXCL: c_uint = 0x0000540d;
pub const TIOCSCTTY: c_uint = 0x0000540e;
pub const TIOCGPGRP: c_uint = 0x0000540f;
pub const TIOCSPGRP: c_uint = 0x00005410;
pub const TIOCOUTQ: c_uint = 0x00005411;
pub const TIOCSTI: c_uint = 0x00005412;
pub const TIOCGWINSZ: c_uint = 0x00005413;
pub const TIOCSWINSZ: c_uint = 0x00005414;
pub const TIOCMGET: c_uint = 0x00005415;
pub const TIOCMBIS: c_uint = 0x00005416;
pub const TIOCMBIC: c_uint = 0x00005417;
pub const TIOCMSET: c_uint = 0x00005418;
pub const TIOCGSOFTCAR: c_uint = 0x00005419;
pub const TIOCSSOFTCAR: c_uint = 0x0000541a;
pub const FIONREAD: c_uint = 0x0000541b;
pub const TIOCINQ: c_uint = 0x0000541b;
pub const TIOCLINUX: c_uint = 0x0000541c;
pub const TIOCCONS: c_uint = 0x0000541d;
pub const TIOCGSERIAL: c_uint = 0x0000541e;
pub const TIOCSSERIAL: c_uint = 0x0000541f;
pub const TIOCPKT: c_uint = 0x00005420;
pub const FIONBIO: c_uint = 0x00005421;
pub const TIOCNOTTY: c_uint = 0x00005422;
pub const TIOCSETD: c_uint = 0x00005423;
pub const TIOCGETD: c_uint = 0x00005424;
pub const TCSBRKP: c_uint = 0x00005425;
pub const FIONCLEX: c_uint = 0x00005450;
pub const FIOCLEX: c_uint = 0x00005451;
pub const FIOASYNC: c_uint = 0x00005452;
pub const TIOCSERCONFIG: c_uint = 0x00005453;
pub const TIOCSERGWILD: c_uint = 0x00005454;
pub const TIOCSERSWILD: c_uint = 0x00005455;
pub const TIOCGLCKTRMIOS: c_uint = 0x00005456;
pub const TIOCSLCKTRMIOS: c_uint = 0x00005457;
pub const TIOCSERGSTRUCT: c_uint = 0x00005458;
pub const TIOCSERGETLSR: c_uint = 0x00005459;
pub const TIOCSERGETMULTI: c_uint = 0x0000545a;
pub const TIOCSERSETMULTI: c_uint = 0x0000545b;

// sockios

pub const SIOCADDRT: c_uint = 0x0000890b;
pub const SIOCDELRT: c_uint = 0x0000890c;
pub const SIOCGIFNAME: c_uint = 0x00008910;
pub const SIOCSIFLINK: c_uint = 0x00008911;
pub const SIOCGIFCONF: c_uint = 0x00008912;
pub const SIOCGIFFLAGS: c_uint = 0x00008913;
pub const SIOCSIFFLAGS: c_uint = 0x00008914;
pub const SIOCGIFADDR: c_uint = 0x00008915;
pub const SIOCSIFADDR: c_uint = 0x00008916;
pub const SIOCGIFDSTADDR: c_uint = 0x00008917;
pub const SIOCSIFDSTADDR: c_uint = 0x00008918;
pub const SIOCGIFBRDADDR: c_uint = 0x00008919;
pub const SIOCSIFBRDADDR: c_uint = 0x0000891a;
pub const SIOCGIFNETMASK: c_uint = 0x0000891b;
pub const SIOCSIFNETMASK: c_uint = 0x0000891c;
pub const SIOCGIFMETRIC: c_uint = 0x0000891d;
pub const SIOCSIFMETRIC: c_uint = 0x0000891e;
pub const SIOCGIFMEM: c_uint = 0x0000891f;
pub const SIOCSIFMEM: c_uint = 0x00008920;
pub const SIOCGIFMTU: c_uint = 0x00008921;
pub const SIOCSIFMTU: c_uint = 0x00008922;
pub const SIOCSIFHWADDR: c_uint = 0x00008924;
pub const SIOCGIFENCAP: c_uint = 0x00008925;
pub const SIOCSIFENCAP: c_uint = 0x00008926;
pub const SIOCGIFHWADDR: c_uint = 0x00008927;
pub const SIOCGIFSLAVE: c_uint = 0x00008929;
pub const SIOCSIFSLAVE: c_uint = 0x00008930;
pub const SIOCADDMULTI: c_uint = 0x00008931;
pub const SIOCDELMULTI: c_uint = 0x00008932;
pub const SIOCDARP: c_uint = 0x00008953;
pub const SIOCGARP: c_uint = 0x00008954;
pub const SIOCSARP: c_uint = 0x00008955;
pub const SIOCDRARP: c_uint = 0x00008960;
pub const SIOCGRARP: c_uint = 0x00008961;
pub const SIOCSRARP: c_uint = 0x00008962;
pub const SIOCGIFMAP: c_uint = 0x00008970;
pub const SIOCSIFMAP: c_uint = 0x00008971;

// modem control lines

pub const TIOCM_LE: c_uint = 0x00000001;
pub const TIOCM_DTR: c_uint = 0x00000002;
pub const TIOCM_RTS: c_uint = 0x00000004;
pub const TIOCM_ST: c_uint = 0x00000008;
pub const TIOCM_SR: c_uint = 0x00000010;
pub const TIOCM_CTS: c_uint = 0x00000020;
pub const TIOCM_CAR: c_uint = 0x00000040;
pub const TIOCM_CD: c_uint = 0x00000040;
pub const TIOCM_RNG: c_uint = 0x00000080;
pub const TIOCM_RI: c_uint = 0x00000080;
pub const TIOCM_DSR: c_uint = 0x00000100;

extern "C" {
    pub fn ioctl(fd: c_int, request: c_uint, ...) -> c_int;
}
<|endoftext|>