<commit_before>use std::convert::From;
use std::fmt;
use std::io;
use std::iter;

/// Error enum for errors that can be encountered while decoding.
#[derive(Debug)]
pub enum DecodeError {
    /// Fewer or more bytes than expected.
    IncompleteData {
        /// the expected size, as specified in the yenc header
        expected_size: usize,
        /// the actual size, as found while reading
        actual_size: usize,
    },
    /// The header or footer line contains unexpected characters or is incomplete.
    InvalidHeader {
        /// the header line
        line: String,
        /// the position in the line where the parsing error occurred
        position: usize,
    },
    /// CRC32 checksum of the part is not the expected checksum.
    InvalidChecksum,
    /// An I/O error occurred.
    IoError(io::Error),
}

/// Error enum for errors that can be encountered when validating the encode options or while encoding.
#[derive(Debug)]
pub enum EncodeError {
    /// Multiple parts (parts > 1), but no part number specified
    PartNumberMissing,
    /// Multiple parts (parts > 1), but no begin offset specified
    PartBeginOffsetMissing,
    /// Multiple parts (parts > 1), but no end offset specified
    PartEndOffsetMissing,
    /// Multiple parts (parts > 1), and begin offset larger than end offset
    PartOffsetsInvalidRange,
    /// I/O Error
    IoError(io::Error),
}

impl From<io::Error> for DecodeError {
    fn from(error: io::Error) -> DecodeError {
        DecodeError::IoError(error)
    }
}

impl From<io::Error> for EncodeError {
    fn from(error: io::Error) -> EncodeError {
        EncodeError::IoError(error)
    }
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            DecodeError::IncompleteData {
                ref expected_size,
                ref actual_size,
            } => write!(
                f,
                "Incomplete data: expected size {}, actual size {}",
                expected_size, actual_size
            ),
            DecodeError::InvalidHeader { ref line, position } => write!(
                f,
                "Invalid header: \n{}\n{}^",
                line,
                iter::repeat(" ").take(position).collect::<String>()
            ),
            DecodeError::InvalidChecksum => write!(f, "Invalid checksum"),
            DecodeError::IoError(ref err) => write!(f, "I/O error {}", err),
        }
    }
}

impl fmt::Display for EncodeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            EncodeError::PartNumberMissing => {
                write!(f, "Multiple parts, but no part number specified.")
            }
            EncodeError::PartBeginOffsetMissing => {
                write!(f, "Multiple parts, but no begin offset specified.")
            }
            EncodeError::PartEndOffsetMissing => {
                write!(f, "Multiple parts, but no end offset specified.")
            }
            EncodeError::PartOffsetsInvalidRange => {
                write!(f, "Multiple parts, begin offset larger than end offset")
            }
            EncodeError::IoError(ref err) => write!(f, "I/O error {}", err),
        }
    }
}
// impl error::Error for DecodeError {}
<commit_msg>Simplify str repeat<commit_after>use std::convert::From;
use std::fmt;
use std::io;

/// Error enum for errors that can be encountered while decoding.
#[derive(Debug)]
pub enum DecodeError {
    /// Fewer or more bytes than expected.
    IncompleteData {
        /// the expected size, as specified in the yenc header
        expected_size: usize,
        /// the actual size, as found while reading
        actual_size: usize,
    },
    /// The header or footer line contains unexpected characters or is incomplete.
    InvalidHeader {
        /// the header line
        line: String,
        /// the position in the line where the parsing error occurred
        position: usize,
    },
    /// CRC32 checksum of the part is not the expected checksum.
    InvalidChecksum,
    /// An I/O error occurred.
    IoError(io::Error),
}

/// Error enum for errors that can be encountered when validating the encode options or while encoding.
#[derive(Debug)]
pub enum EncodeError {
    /// Multiple parts (parts > 1), but no part number specified
    PartNumberMissing,
    /// Multiple parts (parts > 1), but no begin offset specified
    PartBeginOffsetMissing,
    /// Multiple parts (parts > 1), but no end offset specified
    PartEndOffsetMissing,
    /// Multiple parts (parts > 1), and begin offset larger than end offset
    PartOffsetsInvalidRange,
    /// I/O Error
    IoError(io::Error),
}

impl From<io::Error> for DecodeError {
    fn from(error: io::Error) -> DecodeError {
        DecodeError::IoError(error)
    }
}

impl From<io::Error> for EncodeError {
    fn from(error: io::Error) -> EncodeError {
        EncodeError::IoError(error)
    }
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            DecodeError::IncompleteData {
                ref expected_size,
                ref actual_size,
            } => write!(
                f,
                "Incomplete data: expected size {}, actual size {}",
                expected_size, actual_size
            ),
            DecodeError::InvalidHeader { ref line, position } => {
                write!(f, "Invalid header: \n{}\n{}^", line, " ".repeat(position))
            }
            DecodeError::InvalidChecksum => write!(f, "Invalid checksum"),
            DecodeError::IoError(ref err) => write!(f, "I/O error {}", err),
        }
    }
}

impl fmt::Display for EncodeError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            EncodeError::PartNumberMissing => {
                write!(f, "Multiple parts, but no part number specified.")
            }
            EncodeError::PartBeginOffsetMissing => {
                write!(f, "Multiple parts, but no begin offset specified.")
            }
            EncodeError::PartEndOffsetMissing => {
                write!(f, "Multiple parts, but no end offset specified.")
            }
            EncodeError::PartOffsetsInvalidRange => {
                write!(f, "Multiple parts, begin offset larger than end offset")
            }
            EncodeError::IoError(ref err) => write!(f, "I/O error {}", err),
        }
    }
}
// impl error::Error for DecodeError {}
<|endoftext|>


<commit_before>//! Manage xml character escapes

use std::borrow::Cow;
use errors::Result;
use errors::ErrorKind::Escape;
use memchr;

// UTF-8 ranges and tags for encoding characters
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;

enum ByteOrChar {
    Byte(u8),
    Char(u32),
}

/// helper function to escape a `&[u8]` and replace all
/// xml special characters (<, >, &, ', ") with their corresponding
/// xml escaped value.
pub fn escape(raw: &[u8]) -> Cow<[u8]> {
    let mut escapes: Vec<(usize, &'static [u8])> = Vec::new();
    let mut bytes = raw.iter();
    fn to_escape(b: u8) -> bool {
        match b {
            b'<' | b'>' | b'\'' | b'&' | b'"' => true,
            _ => false,
        }
    }

    let mut loc = 0;
    while let Some(i) = bytes.position(|&b| to_escape(b)) {
        loc += i;
        match raw[loc] {
            b'<' => escapes.push((loc, b"<")),
            b'>' => escapes.push((loc, b">")),
            b'\'' => escapes.push((loc, b"'")),
            b'&' => escapes.push((loc, b"&")),
            b'"' => escapes.push((loc, b""")),
            _ => unreachable!(),
        }
        loc += 1;
    }

    if escapes.is_empty() {
        Cow::Borrowed(raw)
    } else {
        let len = raw.len();
        let mut v = Vec::with_capacity(len);
        let mut start = 0;

        for (i, r) in escapes {
            v.extend_from_slice(&raw[start..i]);
            start += i + 1;
            v.extend_from_slice(r);
        }

        if start < len {
            v.extend_from_slice(&raw[start..]);
        }
        Cow::Owned(v)
    }
}

/// helper function to unescape a `&[u8]` and replace all
/// xml escaped characters ('&...;') into their corresponding value
pub fn unescape(raw: &[u8]) -> Result<Cow<[u8]>> {
    let mut escapes = Vec::new();

    let mut start = 0;
    while let Some(i) = memchr::memchr(b'&', &raw[start..]) {
        start += i + 1;
        if let Some(j) = memchr::memchr(b';', &raw[start..]) {
            let end = start + j;
            // search for character correctness
            let b_o_c = match &raw[start..end] {
                b"lt" => ByteOrChar::Byte(b'<'),
                b"gt" => ByteOrChar::Byte(b'>'),
                b"amp" => ByteOrChar::Byte(b'&'),
                b"apos" => ByteOrChar::Byte(b'\''),
                b"quot" => ByteOrChar::Byte(b'\"'),
                b"#x0" | b"#0" => bail!(Escape(
                    "Null character entity not allowed".to_string(),
                    start..end
                )),
                bytes if bytes.starts_with(b"#x") => {
                    ByteOrChar::Char(parse_hexadecimal(&bytes[2..])?)
                }
                bytes if bytes.starts_with(b"#") => ByteOrChar::Char(parse_decimal(&bytes[1..])?),
                bytes => bail!(Escape(
                    format!(
                        "Unrecognized escape symbol: {:?}",
                        ::std::str::from_utf8(bytes)
                    ),
                    start..end
                )),
            };
            escapes.push((start - 1..end, b_o_c));
            start = end + 1;
        } else {
            bail!(Escape(
                "Cannot find ';' after '&'".to_string(),
                start..raw.len()
            ));
        }
    }
    if escapes.is_empty() {
        Ok(Cow::Borrowed(raw))
    } else {
        let len = raw.len();
        let mut v = Vec::with_capacity(len);
        let mut start = 0;
        for (r, b) in escapes {
            v.extend_from_slice(&raw[start..r.start]);
            match b {
                ByteOrChar::Byte(b) => v.push(b),
                ByteOrChar::Char(c) => push_utf8(&mut v, c),
            }
            start = r.end + 1;
        }
        if start < raw.len() {
            v.extend_from_slice(&raw[start..]);
        }
        Ok(Cow::Owned(v))
    }
}

fn push_utf8(buf: &mut Vec<u8>, code: u32) {
    if code < MAX_ONE_B {
        buf.push(code as u8);
    } else if code < MAX_TWO_B {
        buf.push((code >> 6 & 0x1F) as u8 | TAG_TWO_B);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    } else if code < MAX_THREE_B {
        buf.push((code >> 12 & 0x0F) as u8 | TAG_THREE_B);
        buf.push((code >> 6 & 0x3F) as u8 | TAG_CONT);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    } else {
        buf.push((code >> 18 & 0x07) as u8 | TAG_FOUR_B);
        buf.push((code >> 12 & 0x3F) as u8 | TAG_CONT);
        buf.push((code >> 6 & 0x3F) as u8 | TAG_CONT);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    }
}

fn parse_hexadecimal(bytes: &[u8]) -> Result<u32> {
    let mut code = 0;
    for &b in bytes {
        code <<= 4;
        code += match b {
            b'0'...b'9' => b - b'0',
            b'a'...b'f' => b - b'a' + 10,
            b'A'...b'F' => b - b'A' + 10,
            b => bail!("'{}' is not a valid hexadecimal character", b as char),
        } as u32;
    }
    Ok(code)
}

fn parse_decimal(bytes: &[u8]) -> Result<u32> {
    let mut code = 0;
    for &b in bytes {
        code *= 10;
        code += match b {
            b'0'...b'9' => b - b'0',
            b => bail!("'{}' is not a valid decimal character", b as char),
        } as u32;
    }
    Ok(code)
}

#[test]
fn test_escape() {
    assert_eq!(&*unescape(b"test").unwrap(), b"test");
    assert_eq!(&*unescape(b"<test>").unwrap(), b"<test>");
    println!(
        "{}",
        ::std::str::from_utf8(&*unescape(b"©").unwrap()).unwrap()
    );
    assert_eq!(&*unescape(b"0").unwrap(), b"0");
    assert_eq!(&*unescape(b"0").unwrap(), b"0");
    assert_eq!(&*unescape(b"0").unwrap(), b"0");
}
<commit_msg>fix escape wrong offset when more than 2 occurences (#88)<commit_after>//! Manage xml character escapes

use std::borrow::Cow;
use errors::Result;
use errors::ErrorKind::Escape;
use memchr;

// UTF-8 ranges and tags for encoding characters
const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;

enum ByteOrChar {
    Byte(u8),
    Char(u32),
}

/// helper function to escape a `&[u8]` and replace all
/// xml special characters (<, >, &, ', ") with their corresponding
/// xml escaped value.
pub fn escape(raw: &[u8]) -> Cow<[u8]> {
    let mut escapes: Vec<(usize, &'static [u8])> = Vec::new();
    let mut bytes = raw.iter();
    fn to_escape(b: u8) -> bool {
        match b {
            b'<' | b'>' | b'\'' | b'&' | b'"' => true,
            _ => false,
        }
    }

    let mut loc = 0;
    while let Some(i) = bytes.position(|&b| to_escape(b)) {
        loc += i;
        match raw[loc] {
            b'<' => escapes.push((loc, b"<")),
            b'>' => escapes.push((loc, b">")),
            b'\'' => escapes.push((loc, b"'")),
            b'&' => escapes.push((loc, b"&")),
            b'"' => escapes.push((loc, b""")),
            _ => unreachable!("Only '<', '>','\', '&' and '\"' are escaped"),
        }
        loc += 1;
    }

    if escapes.is_empty() {
        Cow::Borrowed(raw)
    } else {
        let len = raw.len();
        let mut v = Vec::with_capacity(len);
        let mut start = 0;
        for (i, r) in escapes {
            v.extend_from_slice(&raw[start..i]);
            v.extend_from_slice(r);
            start = i + 1;
        }

        if start < len {
            v.extend_from_slice(&raw[start..]);
        }
        Cow::Owned(v)
    }
}

/// helper function to unescape a `&[u8]` and replace all
/// xml escaped characters ('&...;') into their corresponding value
pub fn unescape(raw: &[u8]) -> Result<Cow<[u8]>> {
    let mut escapes = Vec::new();

    let mut start = 0;
    while let Some(i) = memchr::memchr(b'&', &raw[start..]) {
        start += i + 1;
        if let Some(j) = memchr::memchr(b';', &raw[start..]) {
            let end = start + j;
            // search for character correctness
            let b_o_c = match &raw[start..end] {
                b"lt" => ByteOrChar::Byte(b'<'),
                b"gt" => ByteOrChar::Byte(b'>'),
                b"amp" => ByteOrChar::Byte(b'&'),
                b"apos" => ByteOrChar::Byte(b'\''),
                b"quot" => ByteOrChar::Byte(b'\"'),
                b"#x0" | b"#0" => bail!(Escape(
                    "Null character entity not allowed".to_string(),
                    start..end
                )),
                bytes if bytes.starts_with(b"#x") => {
                    ByteOrChar::Char(parse_hexadecimal(&bytes[2..])?)
                }
                bytes if bytes.starts_with(b"#") => ByteOrChar::Char(parse_decimal(&bytes[1..])?),
                bytes => bail!(Escape(
                    format!(
                        "Unrecognized escape symbol: {:?}",
                        ::std::str::from_utf8(bytes)
                    ),
                    start..end
                )),
            };
            escapes.push((start - 1..end, b_o_c));
            start = end + 1;
        } else {
            bail!(Escape(
                "Cannot find ';' after '&'".to_string(),
                start..raw.len()
            ));
        }
    }
    if escapes.is_empty() {
        Ok(Cow::Borrowed(raw))
    } else {
        let len = raw.len();
        let mut v = Vec::with_capacity(len);
        let mut start = 0;
        for (r, b) in escapes {
            v.extend_from_slice(&raw[start..r.start]);
            match b {
                ByteOrChar::Byte(b) => v.push(b),
                ByteOrChar::Char(c) => push_utf8(&mut v, c),
            }
            start = r.end + 1;
        }
        if start < raw.len() {
            v.extend_from_slice(&raw[start..]);
        }
        Ok(Cow::Owned(v))
    }
}

fn push_utf8(buf: &mut Vec<u8>, code: u32) {
    if code < MAX_ONE_B {
        buf.push(code as u8);
    } else if code < MAX_TWO_B {
        buf.push((code >> 6 & 0x1F) as u8 | TAG_TWO_B);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    } else if code < MAX_THREE_B {
        buf.push((code >> 12 & 0x0F) as u8 | TAG_THREE_B);
        buf.push((code >> 6 & 0x3F) as u8 | TAG_CONT);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    } else {
        buf.push((code >> 18 & 0x07) as u8 | TAG_FOUR_B);
        buf.push((code >> 12 & 0x3F) as u8 | TAG_CONT);
        buf.push((code >> 6 & 0x3F) as u8 | TAG_CONT);
        buf.push((code & 0x3F) as u8 | TAG_CONT);
    }
}

fn parse_hexadecimal(bytes: &[u8]) -> Result<u32> {
    let mut code = 0;
    for &b in bytes {
        code <<= 4;
        code += match b {
            b'0'...b'9' => b - b'0',
            b'a'...b'f' => b - b'a' + 10,
            b'A'...b'F' => b - b'A' + 10,
            b => bail!("'{}' is not a valid hexadecimal character", b as char),
        } as u32;
    }
    Ok(code)
}

fn parse_decimal(bytes: &[u8]) -> Result<u32> {
    let mut code = 0;
    for &b in bytes {
        code *= 10;
        code += match b {
            b'0'...b'9' => b - b'0',
            b => bail!("'{}' is not a valid decimal character", b as char),
        } as u32;
    }
    Ok(code)
}

#[test]
fn test_unescape() {
    assert_eq!(&*unescape(b"test").unwrap(), b"test");
    assert_eq!(&*unescape(b"<test>").unwrap(), b"<test>");
    assert_eq!(&*unescape(b"0").unwrap(), b"0");
    assert_eq!(&*unescape(b"0").unwrap(), b"0");
}

#[test]
fn test_escape() {
    assert_eq!(&*escape(b"test"), b"test");
    assert_eq!(&*escape(b"<test>"), b"<test>");
    assert_eq!(&*escape(b"\"a\"bc"), b""a"bc");
    assert_eq!(&*escape(b"\"a\"b&c"), b""a"b&c");
    assert_eq!(
        &*escape(b"prefix_\"a\"b&<>c"),
        "prefix_"a"b&<>c".as_bytes()
    );
}
<|endoftext|>


<commit_before>
pub struct Events {
    up: bool,
    down: bool,
    left: bool,
    right: bool,
}

impl Events {
    fn is_up() -> bool {
        self.up
    }

    fn is_down() -> bool {
        self.down
    }

    fn is_left() -> bool {
        self.left
    }

    fn is_right() -> bool {
        self.right
    }
}

<commit_msg>events module public functions<commit_after>
pub struct Events {
    up: bool,
    down: bool,
    left: bool,
    right: bool,
}

impl Events {
    pub fn is_up() -> bool {
        self.up
    }

    pub fn is_down() -> bool {
        self.down
    }

    pub fn is_left() -> bool {
        self.left
    }

    pub fn is_right() -> bool {
        self.right
    }
}

<|endoftext|>


<commit_before>#![allow(dead_code)]

//! Helper functions allowing you to avoid writing boilerplate code for common operations, such as
//! parsing JSON or reading files.

// Copyright (c) 2016 Google Inc (lewinb@google.com).
//
// Refer to the project root for licensing information.

use serde_json;

use std::fs;
use std::io::{self, Read};
use std::path::Path;

use crate::service_account::ServiceAccountKey;
use crate::types::{ApplicationSecret, ConsoleApplicationSecret};

/// Read an application secret from a file.
pub fn read_application_secret(path: &Path) -> io::Result<ApplicationSecret> {
    let mut secret = String::new();
    let mut file = fs::OpenOptions::new().read(true).open(path)?;
    file.read_to_string(&mut secret)?;

    parse_application_secret(&secret)
}

/// Read an application secret from a JSON string.
pub fn parse_application_secret<S: AsRef<str>>(secret: S) -> io::Result<ApplicationSecret> {
    let result: serde_json::Result<ConsoleApplicationSecret> =
        serde_json::from_str(secret.as_ref());
    match result {
        Err(e) => Err(io::Error::new(
            io::ErrorKind::InvalidData,
            format!("Bad application secret: {}", e),
        )),
        Ok(decoded) => {
            if decoded.web.is_some() {
                Ok(decoded.web.unwrap())
            } else if decoded.installed.is_some() {
                Ok(decoded.installed.unwrap())
            } else {
                Err(io::Error::new(
                    io::ErrorKind::InvalidData,
                    "Unknown application secret format",
                ))
            }
        }
    }
}

/// Read a service account key from a JSON file. You can download the JSON keys from the Google
/// Cloud Console or the respective console of your service provider.
pub fn service_account_key_from_file<S: AsRef<Path>>(path: S) -> io::Result<ServiceAccountKey> {
    let mut key = String::new();
    let mut file = fs::OpenOptions::new().read(true).open(path)?;
    file.read_to_string(&mut key)?;

    match serde_json::from_str(&key) {
        Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, format!("{}", e))),
        Ok(decoded) => Ok(decoded),
    }
}

pub(crate) fn join<T>(pieces: &[T], separator: &str) -> String
where
    T: AsRef<str>,
{
    let mut iter = pieces.iter();
    let first = match iter.next() {
        Some(p) => p,
        None => return String::new(),
    };
    let num_separators = pieces.len() - 1;
    let pieces_size: usize = pieces.iter().map(|p| p.as_ref().len()).sum();
    let size = pieces_size + separator.len() * num_separators;
    let mut result = String::with_capacity(size);
    result.push_str(first.as_ref());
    for p in iter {
        result.push_str(separator);
        result.push_str(p.as_ref());
    }
    debug_assert_eq!(size, result.len());
    result
}<commit_msg>Make some of the helpers a bit more idiomatic.<commit_after>#![allow(dead_code)]

//! Helper functions allowing you to avoid writing boilerplate code for common operations, such as
//! parsing JSON or reading files.

// Copyright (c) 2016 Google Inc (lewinb@google.com).
//
// Refer to the project root for licensing information.

use serde_json;

use std::io;
use std::path::Path;

use crate::service_account::ServiceAccountKey;
use crate::types::{ApplicationSecret, ConsoleApplicationSecret};

/// Read an application secret from a file.
pub fn read_application_secret<P: AsRef<Path>>(path: P) -> io::Result<ApplicationSecret> {
    parse_application_secret(std::fs::read_to_string(path)?)
}

/// Read an application secret from a JSON string.
pub fn parse_application_secret<S: AsRef<str>>(secret: S) -> io::Result<ApplicationSecret> {
    let decoded: ConsoleApplicationSecret = serde_json::from_str(secret.as_ref()).map_err(|e| {
        io::Error::new(
            io::ErrorKind::InvalidData,
            format!("Bad application secret: {}", e),
        )
    })?;

    if let Some(web) = decoded.web {
        Ok(web)
    } else if let Some(installed) = decoded.installed {
        Ok(installed)
    } else {
        Err(io::Error::new(
            io::ErrorKind::InvalidData,
            "Unknown application secret format",
        ))
    }
}

/// Read a service account key from a JSON file. You can download the JSON keys from the Google
/// Cloud Console or the respective console of your service provider.
pub fn service_account_key_from_file<S: AsRef<Path>>(path: S) -> io::Result<ServiceAccountKey> {
    let key = std::fs::read_to_string(path)?;
    serde_json::from_str(&key)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, format!("{}", e)))
}

pub(crate) fn join<T>(pieces: &[T], separator: &str) -> String
where
    T: AsRef<str>,
{
    let mut iter = pieces.iter();
    let first = match iter.next() {
        Some(p) => p,
        None => return String::new(),
    };
    let num_separators = pieces.len() - 1;
    let pieces_size: usize = pieces.iter().map(|p| p.as_ref().len()).sum();
    let size = pieces_size + separator.len() * num_separators;
    let mut result = String::with_capacity(size);
    result.push_str(first.as_ref());
    for p in iter {
        result.push_str(separator);
        result.push_str(p.as_ref());
    }
    debug_assert_eq!(size, result.len());
    result
}
<|endoftext|>


<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    try!(l[0].atom()).i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string());
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string());
    let desc = try!(l[1].string());
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()))
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>display net name<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone,PartialEq)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone,PartialEq)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") || self.name.len()==0 {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    try!(l[0].atom()).i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse_net(e:&Sexp) -> ERes<Element> {
    let l = try!(e.slice_atom("net"));
    let num = try!(l[0].i());
    let name = try!(l[1].string());
    Ok(Element::Net(Net { name:name, num:num }))
}

fn parse_net_class(e:&Sexp) -> ERes<Element> {
    fn parse(e:&Sexp, name:&str) -> ERes<f64> {
        let l = try!(e.slice_atom(name));
        l[0].f()
    }
    let l = try!(e.slice_atom("net_class"));
    let name = try!(l[0].string());
    let desc = try!(l[1].string());
    let mut clearance = 0.1524;
    let mut trace_width = 0.2032;
    let mut via_dia = 0.675;
    let mut via_drill = 0.25;
    let mut uvia_dia = 0.508;
    let mut uvia_drill = 0.127;
    let mut nets = vec![];
    for x in &l[2..] {
        let list_name = try!(x.list_name());
        let xn = &list_name[..];
        match xn {
            "add_net" => {
                let l1 = try!(x.slice_atom("add_net"));
                nets.push(try!(l1[0].string()))
            },
            "clearance" => clearance = try!(parse(x, xn)),
            "trace_width" => trace_width = try!(parse(x, xn)),
            "via_dia" => via_dia = try!(parse(x, xn)),
            "via_drill" => via_drill = try!(parse(x, xn)),
            "uvia_dia" => uvia_dia = try!(parse(x, xn)),
            "uvia_drill" => uvia_drill = try!(parse(x, xn)),
            _ => return Err(format!("unknown net_class field {}", list_name))
        }
    }
    let net_class = NetClass {
        name:name, desc:desc, clearance:clearance, via_dia:via_dia,
        via_drill:via_drill, uvia_dia:uvia_dia, uvia_drill:uvia_drill,
        nets:nets, trace_width:trace_width,
    };
    Ok(Element::NetClass(net_class))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            "net" => layout.elements.push(try!(parse_net(e))),
            "net_class" => layout.elements.push(try!(parse_net_class(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>


<commit_before>
macro_rules! bit_struct {
    (
        $(#[$attr:meta])*
        pub struct $struct_name:ident {
            $(pub $field_name:ident : $field_type:ty),+
        }
        deserialize($reader:ident) {
            $($field:ident : { $($tokens:tt)+ }),+
        }
    ) => (
        $(#[$attr])*
        pub struct $struct_name {
            $(pub $field_name: $field_type),+
        }
        impl ::base::Deserialize for $struct_name {
            fn deserialize($reader: &mut ::bitreader::BitReader) -> ::base::DeserializationResult<$struct_name> {
                $( bit_struct!(field $field : $reader : { $($tokens)+ } ); )+
                Ok($struct_name {
                    $($field_name: $field_name),+
                })
            }
        }
    );

    (field reserved : $reader:ident : { $bits:expr }) => (
        try!(::base::reserved($reader, $bits))
    );

    (field expect : $reader:ident : { bits: $bits:expr, reference: $value:expr }) => (
        try!(::base::expect($reader, $bits, $value))
    );

    (field crc : $reader:ident : { 32 }) => (
        try!($reader.skip(32));
    );

    (field skip : $reader:ident : { $bits:expr }) => (
        try!($reader.skip($bits));
    );

    (field $field:ident : $reader:ident : { value : $e:expr }) => (
        let $field = $e;
    );

    (field $field:ident : $reader:ident : { $bits:expr }) => (
        let $field = try!(::bitreader::ReadInto::read($reader, $bits));
    );

    (field $field:ident : $reader:ident : { $bits:expr, map: $closure:expr }) => (
        let $field = ($closure)(try!(::bitreader::ReadInto::read($reader, $bits)));
    );

    (field $field:ident : $reader:ident : { $bits:expr, type: $T:ty }) => (
        let $field: $T = try!(::bitreader::ReadInto::read($reader, $bits));
    );
}
<commit_msg>Use a relative bitreader in bit_struct!() macro.<commit_after>
macro_rules! bit_struct {
    (
        $(#[$attr:meta])*
        pub struct $struct_name:ident {
            $(pub $field_name:ident : $field_type:ty),+
        }
        deserialize($reader:ident) {
            $($field:ident : { $($tokens:tt)+ }),+
        }
    ) => (
        $(#[$attr])*
        pub struct $struct_name {
            $(pub $field_name: $field_type),+
        }
        impl ::base::Deserialize for $struct_name {
            fn deserialize(original_reader: &mut ::bitreader::BitReader) -> ::base::DeserializationResult<$struct_name> {
                let mut relative_reader = original_reader.relative_reader();
                let $reader = &mut relative_reader;
                $( bit_struct!(field $field : $reader : { $($tokens)+ } ); )+
                try!(original_reader.skip($reader.position() as u32));
                Ok($struct_name {
                    $($field_name: $field_name),+
                })
            }
        }
    );

    (field reserved : $reader:ident : { $bits:expr }) => (
        try!(::base::reserved($reader, $bits))
    );

    (field expect : $reader:ident : { bits: $bits:expr, reference: $value:expr }) => (
        try!(::base::expect($reader, $bits, $value))
    );

    (field crc : $reader:ident : { 32 }) => (
        try!($reader.skip(32));
    );

    (field skip : $reader:ident : { $bits:expr }) => (
        try!($reader.skip($bits));
    );

    (field $field:ident : $reader:ident : { value : $e:expr }) => (
        let $field = $e;
    );

    (field $field:ident : $reader:ident : { $bits:expr }) => (
        let $field = try!(::bitreader::ReadInto::read($reader, $bits));
    );

    (field $field:ident : $reader:ident : { $bits:expr, map: $closure:expr }) => (
        let $field = ($closure)(try!(::bitreader::ReadInto::read($reader, $bits)));
    );

    (field $field:ident : $reader:ident : { $bits:expr, type: $T:ty }) => (
        let $field: $T = try!(::bitreader::ReadInto::read($reader, $bits));
    );
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or 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.

// Format list-like macro invocations. These are invocations whose token trees
// can be interpreted as expressions and separated by commas.
// Note that these token trees do not actually have to be interpreted as
// expressions by the compiler. An example of an invocation we would reformat is
// foo!( x, y, z ). The token x may represent an identifier in the code, but we
// interpreted as an expression.
// Macro uses which are not-list like, such as bar!(key => val), will not be
// reformated.
// List-like invocations with parentheses will be formatted as function calls,
// and those with brackets will be formatted as array literals.

use std::thread;

use syntax::ast;
use syntax::parse::token::{Eof, Comma, Token};
use syntax::parse::{ParseSess, tts_to_parser};

use Indent;
use rewrite::RewriteContext;
use expr::{rewrite_call, rewrite_array};
use comment::FindUncommented;
use utils::wrap_str;

// We need to pass `TokenTree`s to our expression parsing thread, but they are
// not `Send`. We wrap them in a `Send` container to force our will.
// FIXME: this is a pretty terrible hack. Any other solution would be preferred.
struct ForceSend<T>(pub T);
unsafe impl<T> Send for ForceSend<T> {}

// FIXME: use the enum from libsyntax?
enum MacroStyle {
    Parens,
    Brackets,
    Braces,
}

pub fn rewrite_macro(mac: &ast::Mac,
                     context: &RewriteContext,
                     width: usize,
                     offset: Indent)
                     -> Option<String> {
    let ast::Mac_::MacInvocTT(ref path, ref tt_vec, _) = mac.node;
    let style = macro_style(mac, context);
    let macro_name = format!("{}!", path);

    if let MacroStyle::Braces = style {
        return None;
    } else if tt_vec.is_empty() {
        return if let MacroStyle::Parens = style {
            Some(format!("{}()", macro_name))
        } else {
            Some(format!("{}[]", macro_name))
        };
    }

    let wrapped_tt_vec = ForceSend((*tt_vec).clone());
    // Wrap expression parsing logic in a thread since the libsyntax parser
    // panicks on failure, which we do not want to propagate.
    let expr_vec_result = thread::catch_panic(move || {
        let parse_session = ParseSess::new();
        let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]);
        let mut expr_vec = vec![];

        loop {
            expr_vec.push(parser.parse_expr());

            match parser.token {
                Token::Eof => break,
                Token::Comma => (),
                _ => panic!("Macro not list-like, skiping..."),
            }

            let _ = parser.bump();
        }

        expr_vec
    });
    let expr_vec = try_opt!(expr_vec_result.ok());

    match style {
        MacroStyle::Parens => {
            // Format macro invocation as function call.
            rewrite_call(context, &macro_name, &expr_vec, mac.span, width, offset)
        }
        MacroStyle::Brackets => {
            // Format macro invocation as array literal.
            let extra_offset = macro_name.len();
            let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x),
                                                 mac.span,
                                                 context,
                                                 try_opt!(width.checked_sub(extra_offset)),
                                                 offset + extra_offset));
            Some(format!("{}{}", macro_name, rewrite))
        }
        MacroStyle::Braces => {
            // Skip macro invocations with braces, for now.
            wrap_str(context.snippet(mac.span), context.config.max_width, width, offset)
        }
    }
}

fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle {
    let snippet = context.snippet(mac.span);
    let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value());
    let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value());
    let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value());

    if paren_pos < bracket_pos && paren_pos < brace_pos {
        MacroStyle::Parens
    } else if bracket_pos < brace_pos {
        MacroStyle::Brackets
    } else {
        MacroStyle::Braces
    }
}
<commit_msg>adapt to rust sytax::ast::Mac changes<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or 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.

// Format list-like macro invocations. These are invocations whose token trees
// can be interpreted as expressions and separated by commas.
// Note that these token trees do not actually have to be interpreted as
// expressions by the compiler. An example of an invocation we would reformat is
// foo!( x, y, z ). The token x may represent an identifier in the code, but we
// interpreted as an expression.
// Macro uses which are not-list like, such as bar!(key => val), will not be
// reformated.
// List-like invocations with parentheses will be formatted as function calls,
// and those with brackets will be formatted as array literals.

use std::thread;

use syntax::ast;
use syntax::parse::token::{Eof, Comma, Token};
use syntax::parse::{ParseSess, tts_to_parser};

use Indent;
use rewrite::RewriteContext;
use expr::{rewrite_call, rewrite_array};
use comment::FindUncommented;
use utils::wrap_str;

// We need to pass `TokenTree`s to our expression parsing thread, but they are
// not `Send`. We wrap them in a `Send` container to force our will.
// FIXME: this is a pretty terrible hack. Any other solution would be preferred.
struct ForceSend<T>(pub T);
unsafe impl<T> Send for ForceSend<T> {}

// FIXME: use the enum from libsyntax?
enum MacroStyle {
    Parens,
    Brackets,
    Braces,
}

pub fn rewrite_macro(mac: &ast::Mac,
                     context: &RewriteContext,
                     width: usize,
                     offset: Indent)
                     -> Option<String> {
    let style = macro_style(mac, context);
    let macro_name = format!("{}!", mac.node.path);

    if let MacroStyle::Braces = style {
        return None;
    } else if mac.node.tts.is_empty() {
        return if let MacroStyle::Parens = style {
            Some(format!("{}()", macro_name))
        } else {
            Some(format!("{}[]", macro_name))
        };
    }

    let wrapped_tt_vec = ForceSend(mac.node.tts.clone());
    // Wrap expression parsing logic in a thread since the libsyntax parser
    // panicks on failure, which we do not want to propagate.
    let expr_vec_result = thread::catch_panic(move || {
        let parse_session = ParseSess::new();
        let mut parser = tts_to_parser(&parse_session, wrapped_tt_vec.0, vec![]);
        let mut expr_vec = vec![];

        loop {
            expr_vec.push(parser.parse_expr());

            match parser.token {
                Token::Eof => break,
                Token::Comma => (),
                _ => panic!("Macro not list-like, skiping..."),
            }

            let _ = parser.bump();
        }

        expr_vec
    });
    let expr_vec = try_opt!(expr_vec_result.ok());

    match style {
        MacroStyle::Parens => {
            // Format macro invocation as function call.
            rewrite_call(context, &macro_name, &expr_vec, mac.span, width, offset)
        }
        MacroStyle::Brackets => {
            // Format macro invocation as array literal.
            let extra_offset = macro_name.len();
            let rewrite = try_opt!(rewrite_array(expr_vec.iter().map(|x| &**x),
                                                 mac.span,
                                                 context,
                                                 try_opt!(width.checked_sub(extra_offset)),
                                                 offset + extra_offset));
            Some(format!("{}{}", macro_name, rewrite))
        }
        MacroStyle::Braces => {
            // Skip macro invocations with braces, for now.
            wrap_str(context.snippet(mac.span), context.config.max_width, width, offset)
        }
    }
}

fn macro_style(mac: &ast::Mac, context: &RewriteContext) -> MacroStyle {
    let snippet = context.snippet(mac.span);
    let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value());
    let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value());
    let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value());

    if paren_pos < bracket_pos && paren_pos < brace_pos {
        MacroStyle::Parens
    } else if bracket_pos < brace_pos {
        MacroStyle::Brackets
    } else {
        MacroStyle::Braces
    }
}
<|endoftext|>


<commit_before>
#[macro_export]
macro_rules! impl_func_delegate {
	($name:ident) => (
		impl FuncDelegate for $name {
		    fn delegate(&mut self) -> &mut Function {
    		    &mut self.delegate
    		}
		}

	)
}

#[macro_export]
macro_rules! impl_mod_delegate {
	($name:ident) => (
        impl<T: ::tensor::NumLimits> ModDelegate<T> for $name<T> {
		    fn delegate(&mut self) -> &mut Module<T> {
    		    &mut self.delegate
    		}
            fn params_iter_mut(&mut self) -> ::std::vec::IntoIter<Variable<T>> {
                let mut v : Vec<Variable<T>> = Vec::new();
                for name in self.delegate()._params.clone().iter() {
                    if let Some(id) = self.get_param(name) {
                        v.push(id.into())
                    }
                }
                v.into_iter()
            }
    fn _apply(&mut self, callback: fn(&mut ::tensor::Tensor<T>)) {
        let mod_names = self.delegate()._modules.clone();
        for name in mod_names {
            let module = self.get_module(name);
            module._apply(callback)
        }
        for mut param in self.params_iter_mut() {
            param.apply(callback);
            if let &mut Some(ref mut g) = param.grad() {
                g.apply(callback)
            }
            /* see also _buffers */
        }
    }
    fn apply(&mut self, callback: fn(&mut ModIntf<T>)) {
        let mod_names = self.delegate()._modules.clone();
        for name in mod_names {
            let module = self.get_module(name);
            module.apply(callback)
        }
        callback(self)
    }
    }

	)
}

#[macro_export]
macro_rules! typecast {
    ($value:expr, $type:ident) => {$value as *mut $type}
}

#[macro_export]
macro_rules! impl_func {
	($name:ident) => (
        #[derive(Clone)]
        pub struct $name {
            delegate: Function,
            saved_tensors: Vec<::tensor::TensorKind>,
        }
        impl $name {
    		pub fn new() -> FIWrap<Self> {
                FIWrap::new($name {
                    delegate: Function::new(),
                    saved_tensors: Vec::new() })
    		}
		}
		impl FuncDelegate for $name {
		    fn delegate(&mut self) -> &mut Function {
    		    &mut self.delegate
    		}
		}

	)
}

#[macro_export]
macro_rules! impl_func_args {
	($name:ident, $args:ident) => (

#[derive(Clone)]
pub struct $name {
    delegate: Function,
    args: $args,
    saved_tensors: Vec<::tensor::TensorKind>,
}

impl $name {
    pub fn new(args: & $args) -> FIWrap<Self> {
        FIWrap::new($name {
                        delegate: Function::new(),
                        args: args.clone(),
                        saved_tensors: Vec::new(),
                    })
    }
}

impl FuncDelegate for $name {
    fn delegate(&mut self) -> &mut Function {
        &mut self.delegate
    }
}
)}

#[macro_export]
macro_rules! map(
    { $($key:expr => $value:expr),+ } => {
        {
            let mut m = ::std::collections::HashMap::new();
            $(
                m.insert($key, $value);
            )+
            m
        }
     };
);

#[macro_export]
macro_rules! map_opt(
    { $($key:expr => $value:expr),+ } => {
        {
            let mut m = ::std::collections::HashMap::<&'static str, ::utils::TRVal>::new();
            $(
                m.insert($key, $value .into());
            )+
            m
        }
     };
);
<commit_msg>add additional func macro to be able to stash arbitrary args<commit_after>
#[macro_export]
macro_rules! impl_func_delegate {
	($name:ident) => (
		impl FuncDelegate for $name {
		    fn delegate(&mut self) -> &mut Function {
    		    &mut self.delegate
    		}
		}

	)
}

#[macro_export]
macro_rules! impl_mod_delegate {
	($name:ident) => (
        impl<T: ::tensor::NumLimits> ModDelegate<T> for $name<T> {
		    fn delegate(&mut self) -> &mut Module<T> {
    		    &mut self.delegate
    		}
            fn params_iter_mut(&mut self) -> ::std::vec::IntoIter<Variable<T>> {
                let mut v : Vec<Variable<T>> = Vec::new();
                for name in self.delegate()._params.clone().iter() {
                    if let Some(id) = self.get_param(name) {
                        v.push(id.into())
                    }
                }
                v.into_iter()
            }
    fn _apply(&mut self, callback: fn(&mut ::tensor::Tensor<T>)) {
        let mod_names = self.delegate()._modules.clone();
        for name in mod_names {
            let module = self.get_module(name);
            module._apply(callback)
        }
        for mut param in self.params_iter_mut() {
            param.apply(callback);
            if let &mut Some(ref mut g) = param.grad() {
                g.apply(callback)
            }
            /* see also _buffers */
        }
    }
    fn apply(&mut self, callback: fn(&mut ModIntf<T>)) {
        let mod_names = self.delegate()._modules.clone();
        for name in mod_names {
            let module = self.get_module(name);
            module.apply(callback)
        }
        callback(self)
    }
    }

	)
}

#[macro_export]
macro_rules! typecast {
    ($value:expr, $type:ident) => {$value as *mut $type}
}

#[macro_export]
macro_rules! impl_func {
	($name:ident) => (
        #[derive(Clone)]
        pub struct $name {
            delegate: Function,
            saved_tensors: Vec<::tensor::TensorKind>,
        }
        impl $name {
    		pub fn new() -> FIWrap<Self> {
                FIWrap::new($name {
                    delegate: Function::new(),
                    saved_tensors: Vec::new() })
    		}
		}
		impl FuncDelegate for $name {
		    fn delegate(&mut self) -> &mut Function {
    		    &mut self.delegate
    		}
		}

	)
}

#[macro_export]
macro_rules! impl_func_args {
    ($name:ident, $args:ident) => (

#[derive(Clone)]
pub struct $name {
    delegate: Function,
    args: $args,
    saved_tensors: Vec<::tensor::TensorKind>,
}

impl $name {
    pub fn new(args: & $args) -> FIWrap<Self> {
        FIWrap::new($name {
                        delegate: Function::new(),
                        args: args.clone(),
                        saved_tensors: Vec::new(),
                    })
    }
}

impl FuncDelegate for $name {
    fn delegate(&mut self) -> &mut Function {
        &mut self.delegate
    }
}
)}

#[macro_export]
macro_rules! impl_func_args_other {
    ($name:ident, $args:ident) => (

#[derive(Clone)]
pub struct $name {
    delegate: Function,
    args: $args,
    saved_trvalue: Vec<::utils::TRVal>,
}

impl $name {
    pub fn new(args: & $args) -> FIWrap<Self> {
        FIWrap::new($name {
                        delegate: Function::new(),
                        args: args.clone(),
                        saved_trvalue: Vec::new(),
                    })
    }
}

impl FuncDelegate for $name {
    fn delegate(&mut self) -> &mut Function {
        &mut self.delegate
    }
}
)}

#[macro_export]
macro_rules! map(
    { $($key:expr => $value:expr),+ } => {
        {
            let mut m = ::std::collections::HashMap::new();
            $(
                m.insert($key, $value);
            )+
            m
        }
     };
);

#[macro_export]
macro_rules! map_opt(
    { $($key:expr => $value:expr),+ } => {
        {
            let mut m = ::std::collections::HashMap::<&'static str, ::utils::TRVal>::new();
            $(
                m.insert($key, $value .into());
            )+
            m
        }
     };
);
<|endoftext|>


<commit_before>pub mod responses {

    use std::fmt;

    use serde;
    use serde_json as json;

    #[derive(Deserialize, Debug)]
    pub struct AuthResponse {
        pub session: SessionResponse,
    }

    #[derive(Deserialize, Debug, Clone)]
    pub struct SessionResponse {
        pub key: String,
        pub subscriber: i64,
        pub name: String,
    }

    #[derive(Deserialize)]
    pub struct NowPlayingResponseWrapper {
        pub nowplaying: NowPlayingResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct NowPlayingResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize)]
    pub struct ScrobbleResponseWrapper {
        pub scrobbles: SingleScrobble,
    }

    #[derive(Deserialize)]
    pub struct SingleScrobble {
        pub scrobble: ScrobbleResponse,
    }

    #[derive(Deserialize, Debug, WrappedVec)]
    #[CollectionName="ScrobbleList"]
    #[CollectionDerives="Debug, Deserialize"]
    pub struct ScrobbleResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
        pub timestamp: String,
    }

    #[derive(Debug)]
    pub struct BatchScrobbleResponse {
        pub scrobbles: ScrobbleList
    }

    #[derive(Deserialize, Debug)]
    pub struct BatchScrobbleResponseWrapper {
        pub scrobbles: BatchScrobbles,
    }

    #[derive(Deserialize, Debug)]
    pub struct BatchScrobbles {
        #[serde(rename="scrobble")]
        pub scrobbles: ScrobbleList
    }

    #[derive(Deserialize, Debug)]
    pub struct CorrectableString {
        #[serde(deserialize_with="CorrectableString::deserialize_corrected_field")]
        pub corrected: bool,
        #[serde(rename="#text", default)]
        pub text: String,
    }

    impl CorrectableString {
        fn deserialize_corrected_field<'de, D>(de: D) -> Result<bool, D::Error>
            where D: serde::Deserializer<'de>
        {
            let deser_result: json::Value = try!(serde::Deserialize::deserialize(de));
            match deser_result {
                json::Value::String(ref s) if &*s == "1" => Ok(true),
                json::Value::String(ref s) if &*s == "0" => Ok(false),
                _ => Err(serde::de::Error::custom("Unexpected value")),
            }
        }
    }

    impl fmt::Display for CorrectableString {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.text)
        }
    }

}

pub mod metadata {

    use std::collections::HashMap;

    /// Repesents a single track play (aka a "scrobble")
    #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, WrappedVec)]
    #[CollectionName="ScrobbleBatch"]
    #[CollectionDoc="A batch of Scrobbles to be submitted to Last.fm together."]
    #[CollectionDerives="Clone, Debug"]
    pub struct Scrobble {
        artist: String,
        track: String,
        album: String,

        timestamp: Option<u64>
    }

    impl Scrobble {

        /// Constructs a new Scrobble instance, representing a music track
        /// played in the past.
        pub fn new(artist: String, track: String, album: String) -> Scrobble {
            Scrobble{ artist: artist, track: track, album: album, timestamp: None }
        }

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

        /// Converts the Scrobble metadata (track name, artist & album name)
        /// into a HashMap. Map keys are `"track"`, `"artist"` and `"album"`,
        /// respectively.
        pub fn as_map(&self) -> HashMap<String, String> {
            let mut params = HashMap::new();
            params.insert("track".to_string(), self.track.clone());
            params.insert("artist".to_string(), self.artist.clone());
            params.insert("album".to_string(), self.album.clone());

            if let Some(timestamp) = self.timestamp {
                params.insert("timestamp".to_string(), timestamp.to_string());
            }

            params
        }

    }

}<commit_msg>Add artist/track/album getters to Scrobble<commit_after>pub mod responses {

    use std::fmt;

    use serde;
    use serde_json as json;

    #[derive(Deserialize, Debug)]
    pub struct AuthResponse {
        pub session: SessionResponse,
    }

    #[derive(Deserialize, Debug, Clone)]
    pub struct SessionResponse {
        pub key: String,
        pub subscriber: i64,
        pub name: String,
    }

    #[derive(Deserialize)]
    pub struct NowPlayingResponseWrapper {
        pub nowplaying: NowPlayingResponse,
    }

    #[derive(Deserialize, Debug)]
    pub struct NowPlayingResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
    }

    #[derive(Deserialize)]
    pub struct ScrobbleResponseWrapper {
        pub scrobbles: SingleScrobble,
    }

    #[derive(Deserialize)]
    pub struct SingleScrobble {
        pub scrobble: ScrobbleResponse,
    }

    #[derive(Deserialize, Debug, WrappedVec)]
    #[CollectionName="ScrobbleList"]
    #[CollectionDerives="Debug, Deserialize"]
    pub struct ScrobbleResponse {
        pub artist: CorrectableString,
        pub album: CorrectableString,
        #[serde(rename="albumArtist")]
        pub album_artist: CorrectableString,
        pub track: CorrectableString,
        pub timestamp: String,
        //  TODO: Ignored field here? (#20)
    }

    #[derive(Debug)]
    pub struct BatchScrobbleResponse {
        pub scrobbles: ScrobbleList
    }

    #[derive(Deserialize, Debug)]
    pub struct BatchScrobbleResponseWrapper {
        pub scrobbles: BatchScrobbles,
    }

    #[derive(Deserialize, Debug)]
    pub struct BatchScrobbles {
        #[serde(rename="scrobble")]
        pub scrobbles: ScrobbleList
    }

    #[derive(Deserialize, Debug)]
    pub struct CorrectableString {
        #[serde(deserialize_with="CorrectableString::deserialize_corrected_field")]
        pub corrected: bool,
        #[serde(rename="#text", default)]
        pub text: String,
    }

    impl CorrectableString {
        fn deserialize_corrected_field<'de, D>(de: D) -> Result<bool, D::Error>
            where D: serde::Deserializer<'de>
        {
            let deser_result: json::Value = try!(serde::Deserialize::deserialize(de));
            match deser_result {
                json::Value::String(ref s) if &*s == "1" => Ok(true),
                json::Value::String(ref s) if &*s == "0" => Ok(false),
                _ => Err(serde::de::Error::custom("Unexpected value")),
            }
        }
    }

    impl fmt::Display for CorrectableString {
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
            write!(f, "{}", self.text)
        }
    }

}

pub mod metadata {

    use std::collections::HashMap;

    /// Repesents a single track play (aka a "scrobble")
    #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, WrappedVec)]
    #[CollectionName="ScrobbleBatch"]
    #[CollectionDoc="A batch of Scrobbles to be submitted to Last.fm together."]
    #[CollectionDerives="Clone, Debug"]
    pub struct Scrobble {
        artist: String,
        track: String,
        album: String,

        timestamp: Option<u64>
    }

    impl Scrobble {

        /// Constructs a new Scrobble instance, representing a music track
        /// played in the past.
        pub fn new(artist: String, track: String, album: String) -> Scrobble {
            Scrobble{ artist: artist, track: track, album: album, timestamp: None }
        }

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

        /// Converts the Scrobble metadata (track name, artist & album name)
        /// into a HashMap. Map keys are `"track"`, `"artist"` and `"album"`,
        /// respectively.
        pub fn as_map(&self) -> HashMap<String, String> {
            let mut params = HashMap::new();
            params.insert("track".to_string(), self.track.clone());
            params.insert("artist".to_string(), self.artist.clone());
            params.insert("album".to_string(), self.album.clone());

            if let Some(timestamp) = self.timestamp {
                params.insert("timestamp".to_string(), timestamp.to_string());
            }

            params
        }

        pub fn artist(&self) -> String {
            self.artist.clone()
        }

        pub fn track(&self) -> String {
            self.track.clone()
        }

        pub fn album(&self) -> String {
            self.album.clone()
        }

    }

}<|endoftext|>


<commit_before>// Copyright (c) 2017 Simon Dickson
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::path::Path;

use rocket::Route;
use rocket::State;
use rocket::config::Config;
use rocket_contrib::Json;

use data::init::establish_connection;
use data::movies::{page_movies, get_movie};
use partial_file::{serve_partial, PartialFile};

#[derive(Serialize)]
pub struct Movie {
    pub id: i32,
    pub title: String,
    pub background_image: String,
    pub card_image: String,
    pub video_url: String
}

#[derive(FromForm)]
pub struct PageRequest {
    page: Option<i64>,
    count: Option<i64>
}

#[get("/")]
pub fn all_movies_root(config: State<Config>) -> Json {
    all_movies(config, PageRequest{ page: None, count: None })
}

#[get("/?<page_request>")]
pub fn all_movies(config: State<Config>, page_request: PageRequest) -> Json {
    let conn = establish_connection();
    let page = match page_request.page { Some(v) => v, None => 0 };
    let count = match page_request.count { Some(v) => v, None => 10 };

    let movies = page_movies(&conn, page, count);

    Json(json!({
        "results": movies.into_iter().map(|m| Movie {
            id: m.id,
            title: m.title,
            background_image: "https://storage.googleapis.com/android-tv/Sample%20videos/Google%2B/Google%2B_%20Instant%20Upload/bg.jpg".to_owned(), //m.background_image,
            card_image: "https://storage.googleapis.com/android-tv/Sample%20videos/Google%2B/Google%2B_%20Instant%20Upload/card.jpg".to_owned(), //m.card_image,
            video_url: format!("http://{}:{}/api/movies/play/{}", config.address, config.port, m.id).to_owned()
    })))
}

#[get("/play/<movie_id>")]
pub fn play_movie(movie_id: i32) -> io::Result<PartialFile>  {
    let conn = establish_connection();
    let movie = get_movie(&conn, movie_id as i64);
    serve_partial(Path::new(&movie.file_path))
}

pub fn routes() -> Vec<Route> {
    routes![all_movies_root, all_movies, play_movie]
}
<commit_msg>Fix build<commit_after>// Copyright (c) 2017 Simon Dickson
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::io;
use std::path::Path;

use rocket::Route;
use rocket::State;
use rocket::config::Config;
use rocket_contrib::Json;

use data::init::establish_connection;
use data::movies::{page_movies, get_movie};
use partial_file::{serve_partial, PartialFile};

#[derive(Serialize)]
pub struct Movie {
    pub id: i32,
    pub title: String,
    pub background_image: String,
    pub card_image: String,
    pub video_url: String
}

#[derive(FromForm)]
pub struct PageRequest {
    page: Option<i64>,
    count: Option<i64>
}

#[get("/")]
pub fn all_movies_root(config: State<Config>) -> Json {
    all_movies(config, PageRequest{ page: None, count: None })
}

#[get("/?<page_request>")]
pub fn all_movies(config: State<Config>, page_request: PageRequest) -> Json {
    let conn = establish_connection();
    let page = match page_request.page { Some(v) => v, None => 0 };
    let count = match page_request.count { Some(v) => v, None => 10 };

    let movies = page_movies(&conn, page, count);

    Json(json!({
        "results": movies.into_iter().map(|m| Movie {
            id: m.id,
            title: m.title,
            background_image: "https://storage.googleapis.com/android-tv/Sample%20videos/Google%2B/Google%2B_%20Instant%20Upload/bg.jpg".to_owned(),
            card_image: "https://storage.googleapis.com/android-tv/Sample%20videos/Google%2B/Google%2B_%20Instant%20Upload/card.jpg".to_owned(),
            video_url: format!("http://{}:{}/api/movies/play/{}", config.address, config.port, m.id).to_owned()
        }).collect::<Vec<_>>(),
    }))
}

#[get("/play/<movie_id>")]
pub fn play_movie(movie_id: i32) -> io::Result<PartialFile>  {
    let conn = establish_connection();
    let movie = get_movie(&conn, movie_id as i64);
    serve_partial(Path::new(&movie.file_path))
}

pub fn routes() -> Vec<Route> {
    routes![all_movies_root, all_movies, play_movie]
}
<|endoftext|>


<commit_before>use super::interface::DBusInterface;

extern crate dbus;
use self::dbus::{Connection, Error};

use std::collections::btree_map::BTreeMap;

pub struct DBusObject<'a> {
    ifaces: BTreeMap<String, Box<DBusInterface>>,

    conn: &'a Connection,
    path: String,
}

impl<'a> DBusObject<'a> {
    pub fn new(conn: &'a Connection, ifaces: BTreeMap<String, Box<DBusInterface>>, path: &str) -> Result<Self, Error> {
        try!(conn.register_object_path(path));

        Ok(DBusObject {
            ifaces: ifaces,

            conn: conn,
            path: path.to_string(),
        })
    }

    pub fn path(&self) -> &str {
        &self.path[..]
    }
}

impl<'a> Drop for DBusObject<'a> {
    fn drop(&mut self) {
        self.conn.unregister_object_path(self.path())
    }
}
<commit_msg>object: add a method to get an interface<commit_after>use super::interface::DBusInterface;

extern crate dbus;
use self::dbus::{Connection, Error};

use std::collections::btree_map::BTreeMap;

pub struct DBusObject<'a> {
    ifaces: BTreeMap<String, Box<DBusInterface>>,

    conn: &'a Connection,
    path: String,
}

impl<'a> DBusObject<'a> {
    pub fn new(conn: &'a Connection, ifaces: BTreeMap<String, Box<DBusInterface>>, path: &str) -> Result<Self, Error> {
        try!(conn.register_object_path(path));

        Ok(DBusObject {
            ifaces: ifaces,

            conn: conn,
            path: path.to_string(),
        })
    }

    pub fn path(&self) -> &str {
        &self.path[..]
    }

    pub fn get_interface(&self, interface: &str) -> Option<&DBusInterface> {
        self.ifaces.get(interface).map(|iface| {
            &**iface
        })
    }
}

impl<'a> Drop for DBusObject<'a> {
    fn drop(&mut self) {
        self.conn.unregister_object_path(self.path())
    }
}
<|endoftext|>


<commit_before>use std::net::SocketAddr;
use std::sync::{ Arc, RwLock };
use std::thread::{ JoinHandle, spawn };
use ::config::ServerConfig;
use ::state::State;
use tokio::prelude::Future;
use tokio::net::{ TcpStream, TcpListener };
use tokio::io;

#[derive(Clone)]
pub struct Server {
    config: ServerConfig,
    state: Arc<RwLock<State>>
}

impl Server {
    pub fn new(config: ServerConfig, state: Arc<RwLock<State>>) -> Self {
        Self { config, state }
    }

    pub fn start(&mut self) {
        let addr = SocketAddr::new(self.config.listen_address, self.config.listen_port);

        if let Ok(listener) = TcpListener::bind(&addr) {
            let server = listener.incoming().for_each(move |socket| {
                println!("New connection: {:?}", socket.peer_addr().unwrap());

                let connection = AcceptClient::new(socket).then(|_| {
                    println!("Accepted and stuff");
                    Ok(())
                });

                ::tokio::spawn(connection);

                Ok(())
            }).map_err(|err| println!("Accept error: {:?}", err));

            ::tokio::run(server);
        } else {
            println!("Failed to bind to address: {:?}", addr);
        }
    }

    pub fn start_detached(&mut self) -> JoinHandle<()> {
        let mut self_clone = self.clone();

        spawn(move || {
            self_clone.start();
        })
    }

    pub fn stop(self, handle: JoinHandle<()>) {
        match handle.join() {
            Ok(h) => println!("Server stopped {:?}", h),
            Err(err) => println!("Error while joining {:?}", err)
        }
    }
}

enum ClientState {
    Connecting(TcpStream),
}

struct AcceptClient {
    state: ClientState
}

impl AcceptClient {
    pub fn new(stream: TcpStream) -> AcceptClient {
        Self { state: ClientState::Connecting(stream) }
    }
}

impl Future for AcceptClient {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
        println!("Polling around");

        match self.state {
            ClientState::Connecting(ref mut stream) => {

            }
        }
        Ok(Async::NotReady)
    }
}<commit_msg>Compiling and essentially working, but quite broken still<commit_after>use std::net::SocketAddr;
use std::sync::{ Arc, RwLock };
use std::thread::{ JoinHandle, spawn };
use ::config::ServerConfig;
use ::state::State;
use tokio::prelude::{ Async, Future, Stream };
use tokio::net::{ TcpStream, TcpListener };
use tokio::io;

#[derive(Clone)]
pub struct Server {
    config: ServerConfig,
    state: Arc<RwLock<State>>
}

impl Server {
    pub fn new(config: ServerConfig, state: Arc<RwLock<State>>) -> Self {
        Self { config, state }
    }

    pub fn start(&mut self) {
        let addr = SocketAddr::new(self.config.listen_address, self.config.listen_port);

        if let Ok(listener) = TcpListener::bind(&addr) {
            let server = listener.incoming().for_each(move |socket| {
                println!("New connection: {:?}", socket.peer_addr().unwrap());

                let connection = AcceptClient::new(socket).then(|_| {
                    println!("Accepted and stuff");
                    Ok(())
                });

                ::tokio::spawn(connection);

                Ok(())
            }).map_err(|err| println!("Accept error: {:?}", err));

            ::tokio::run(server);
        } else {
            println!("Failed to bind to address: {:?}", addr);
        }
    }

    pub fn start_detached(&mut self) -> JoinHandle<()> {
        let mut self_clone = self.clone();

        spawn(move || {
            self_clone.start();
        })
    }

    pub fn stop(self, handle: JoinHandle<()>) {
        match handle.join() {
            Ok(h) => println!("Server stopped {:?}", h),
            Err(err) => println!("Error while joining {:?}", err)
        }
    }
}

enum ClientState {
    NewConnection(TcpStream),
}

struct AcceptClient {
    state: ClientState,
}

impl AcceptClient {
    pub fn new(stream: TcpStream) -> AcceptClient {
        Self { state: ClientState::NewConnection(stream) }
    }
}

impl Future for AcceptClient {
    type Item = ();
    type Error = io::Error;

    fn poll(&mut self) -> Result<Async<Self::Item>, Self::Error> {
        /*
        match self.state {
            ClientState::NewConnection(ref mut stream) => {
                let mut a = io::write_all(stream, "HELLO\n")
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "ACK\n") })
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "KTHXBYE\n") })
                .map(|_| ());

                a.poll()
            }
        }
        */

        match self.state {
            ClientState::NewConnection(ref mut stream) => {
                let mut a = io::write_all(stream, "HELLO\n")
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "ACK\n") })
                .and_then(|(s, b)| {
                    let buf = vec![0; 5];
                    io::read_exact(s, buf)
                })
                .and_then(|(s, b)| { io::write_all(s, "KTHXBYE\n") })
                .map(|_| ());

                loop {
                    let v = match a.poll() {
                        Ok(Async::Ready(t)) => t,
                        Ok(Async::NotReady) => return Ok(Async::NotReady),
                        Err(err) => return Err(err)
                    };

                    println!("Got result: {:?}", v);
                    break;
                };

                Ok(Async::Ready(()))
            }
        }
    }
}<|endoftext|>


<commit_before>use structs::{Op, OpStream};
use structs::Op::*;

pub fn parse(text: &[u8]) -> Result<Vec<Op>, String> {
    let mut stack = vec![];
    let mut current = vec![];
    let mut line = 1;
    let mut column = 1;

    for c in text {
        match *c {
            b'+' => current.push(Add(0x01)),
            b'-' => current.push(Add(0xff)),
            b'>' => current.push(Mov(1)),
            b'<' => current.push(Mov(-1)),
            b'.' => current.push(Out),
            b',' => current.push(In),
            b'[' => {
                stack.push(current);
                current = vec![];
            }
            b']' => {
                let opstream = OpStream { ops: current };
                current = match stack.pop() {
                    Some(v) => v,
                    None => return Err(format!("Stray ] in line {}, column {}", line, column)),
                };
                current.push(Loop(opstream));
            }
            _ => {}
        }
        if *c == b'\n' {
            line += 1;
            column = 1;
        } else {
            column += 1;
        }
    }
    if !stack.is_empty() {
        return Err(format!("Missing ] in line {}, column {}", line, column));
    }
    Ok(current)
}

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

    use structs::OpStream;
    use structs::Op::*;

    #[test]
    fn test_parse() {
        let input = b"+>-[+.,]+<";
        assert_eq!(parse(&input[..]),
                   Ok(vec![Add(0x01),
                           Mov(1),
                           Add(0xff),
                           Loop(OpStream { ops: vec![Add(1), Out, In] }),
                           Add(0x01),
                           Mov(-1)]));
    }

    #[test]
    fn test_parse_stray() {
        let input = include_bytes!("../test_cases/stray.bf");
        assert_eq!(parse(&input[..]),
                   Err("Stray ] in line 3, column 3".to_string()));
    }

    #[test]
    fn test_parse_incomplete() {
        let input = include_bytes!("../test_cases/incomplete.bf");
        assert_eq!(parse(&input[..]),
                   Err("Missing ] in line 4, column 1".to_string()));
    }
}
<commit_msg>test: parse empty inputs<commit_after>use structs::{Op, OpStream};
use structs::Op::*;

pub fn parse(text: &[u8]) -> Result<Vec<Op>, String> {
    let mut stack = vec![];
    let mut current = vec![];
    let mut line = 1;
    let mut column = 1;

    for c in text {
        match *c {
            b'+' => current.push(Add(0x01)),
            b'-' => current.push(Add(0xff)),
            b'>' => current.push(Mov(1)),
            b'<' => current.push(Mov(-1)),
            b'.' => current.push(Out),
            b',' => current.push(In),
            b'[' => {
                stack.push(current);
                current = vec![];
            }
            b']' => {
                let opstream = OpStream { ops: current };
                current = match stack.pop() {
                    Some(v) => v,
                    None => return Err(format!("Stray ] in line {}, column {}", line, column)),
                };
                current.push(Loop(opstream));
            }
            _ => {}
        }
        if *c == b'\n' {
            line += 1;
            column = 1;
        } else {
            column += 1;
        }
    }
    if !stack.is_empty() {
        return Err(format!("Missing ] in line {}, column {}", line, column));
    }
    Ok(current)
}

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

    use structs::OpStream;
    use structs::Op::*;

    #[test]
    fn test_parse() {
        let input = b"+>-[+.,]+<";
        assert_eq!(parse(&input[..]),
                   Ok(vec![Add(0x01),
                           Mov(1),
                           Add(0xff),
                           Loop(OpStream { ops: vec![Add(1), Out, In] }),
                           Add(0x01),
                           Mov(-1)]));
    }

    #[test]
    fn test_parse_empty() {
        assert_eq!(parse(&b""[..]), Ok(vec![]));
    }

    #[test]
    fn test_parse_stray() {
        let input = include_bytes!("../test_cases/stray.bf");
        assert_eq!(parse(&input[..]),
                   Err("Stray ] in line 3, column 3".to_string()));
    }

    #[test]
    fn test_parse_incomplete() {
        let input = include_bytes!("../test_cases/incomplete.bf");
        assert_eq!(parse(&input[..]),
                   Err("Missing ] in line 4, column 1".to_string()));
    }
}
<|endoftext|>


<commit_before>#![plugin(peg_syntax_ext)]

use std::collections::HashMap;

peg_file! gremlin("gremlin.rustpeg");

pub fn parse(g: &str) -> Result<ParsedGraphQuery, gremlin::ParseError> {
    let parsed = pre_parse(g);
    // verify all the steps actually make sense
    // is it a query to a single vertex or a global query?
    parsed
}

pub fn pre_parse(g: &str) -> Result<ParsedGraphQuery, gremlin::ParseError> {
    gremlin::query(g)
}

/*
returned from the peg parser
we'll need to take each of the steps
and use them to construct an actual GraphQuery
*/
pub struct ParsedGraphQuery {
    pub steps: Vec<RawStep>
}

/*
scope of the query.  determines if we're looking at the
entire graph or just from a handful of vertices
*/
pub enum Scope {
    Global,
    Vertex(Vec<i64>),
}

/*
generic step used in ParsedGraphQuery
will be turned into specific steps
*/
pub struct RawStep {
    pub name: String,
    pub args: Vec<Arg>,
}

#[derive(Debug, Display)]
pub enum Arg {
    Integer(i64),
    Float(f64),
    String(String),
}

impl RawStep {
    pub fn new(name: String, args: Vec<Arg>) -> RawStep {
        RawStep{name:name, args:args}
    }
}

struct GraphQueryResult;

impl ParsedGraphQuery {
    fn execute(&self) -> Result<GraphQueryResult, &str> {
        // get the starting point(s)

        // for now lets just put this hash table here

        let mut steps_table = HashMap::new();
        steps_table.insert("outV", traverse_out);

        // i'm tempted to say global graph traversals must include a
        // starting point, g.v(predicate)

        // execute each of the steps sequentially
        for step in self.steps.iter() {
            // lookup step in hash table
            // execute function, passing step args
        }
        Result::Err("meh")
    }
}

fn traverse_out() {

}
<commit_msg>traverse in<commit_after>#![plugin(peg_syntax_ext)]

use std::collections::HashMap;

peg_file! gremlin("gremlin.rustpeg");

pub fn parse(g: &str) -> Result<ParsedGraphQuery, gremlin::ParseError> {
    let parsed = pre_parse(g);
    // verify all the steps actually make sense
    // is it a query to a single vertex or a global query?
    parsed
}

pub fn pre_parse(g: &str) -> Result<ParsedGraphQuery, gremlin::ParseError> {
    gremlin::query(g)
}

/*
returned from the peg parser
we'll need to take each of the steps
and use them to construct an actual GraphQuery
*/
pub struct ParsedGraphQuery {
    pub steps: Vec<RawStep>
}

/*
scope of the query.  determines if we're looking at the
entire graph or just from a handful of vertices
*/
pub enum Scope {
    Global,
    Vertex(Vec<i64>),
}

/*
generic step used in ParsedGraphQuery
will be turned into specific steps
*/
pub struct RawStep {
    pub name: String,
    pub args: Vec<Arg>,
}

#[derive(Debug, Display)]
pub enum Arg {
    Integer(i64),
    Float(f64),
    String(String),
}

impl RawStep {
    pub fn new(name: String, args: Vec<Arg>) -> RawStep {
        RawStep{name:name, args:args}
    }
}

struct GraphQueryResult;

impl ParsedGraphQuery {
    fn execute(&self) -> Result<GraphQueryResult, &str> {
        // get the starting point(s)

        // for now lets just put this hash table here

        let mut steps_table = HashMap::new();
        steps_table.insert("outV", traverse_out);
        steps_table.insert("inV", traverse_out);

        // i'm tempted to say global graph traversals must include a
        // starting point, g.v(predicate)

        // execute each of the steps sequentially
        for step in self.steps.iter() {
            // lookup step in hash table
            // execute function, passing step args
        }
        Result::Err("meh")
    }
}

fn traverse_out() {

}

fn traverse_in() {

}
<|endoftext|>


<commit_before>use std::str::from_utf8;
use nom::IResult;

#[derive(Debug,PartialEq,Eq)]
pub struct PosixHeader<'a> {
    pub name:     & 'a str,
    pub mode:     & 'a str,
    pub uid:      u64,
    pub gid:      u64,
    pub size:     u64,
    pub mtime:    u64,
    pub chksum:   & 'a str,
    pub typeflag: TypeFlag,
    pub linkname: & 'a str,
    pub ustar:    Option<UStarHeader<'a>>
}

#[derive(Debug,PartialEq,Eq)]
pub struct UStarHeader<'a> {
    pub magic:    & 'a str,
    pub version:  & 'a str,
    pub uname:    & 'a str,
    pub gname:    & 'a str,
    pub devmajor: u64,
    pub devminor: u64,
    pub prefix:   & 'a str,
}

#[derive(Debug,PartialEq,Eq)]
pub struct TarEntry<'a> {
    pub header:   PosixHeader<'a>,
    pub contents: & 'a str
}

/* TODO: support vendor specific + sparse */
#[derive(Debug,PartialEq,Eq)]
pub enum TypeFlag {
    NormalFile,
    HardLink,
    SymbolicLink,
    CharacterSpecial,
    BlockSpecial,
    Directory,
    FIFO,
    ContiguousFile,
    GlobalExtendedHeaderWithMetadata,
    ExtendedHeaderWithMetadataForNext,
    VendorSpecific,
    Invalid
}

/* TODO: validation */
fn str_to_u64(s: &str, base: u64) -> u64 {
    let mut u = 0;
    let mut f = 1;

    for c in s.chars().rev().skip_while(|&c| c == '\0') {
        u += f * ((c as u64) - ('0' as u64));
        f *= base;
    }

    u
}

pub fn octal_to_u64(o: &str) -> u64 {
    str_to_u64(o, 8)
}

fn char_to_type_flag(c: char) -> TypeFlag {
    match c {
        '0' | '\0' => TypeFlag::NormalFile,
        '1' => TypeFlag::HardLink,
        '2' => TypeFlag::SymbolicLink,
        '3' => TypeFlag::CharacterSpecial,
        '4' => TypeFlag::BlockSpecial,
        '5' => TypeFlag::Directory,
        '6' => TypeFlag::FIFO,
        '7' => TypeFlag::ContiguousFile,
        'g' => TypeFlag::GlobalExtendedHeaderWithMetadata,
        'x' => TypeFlag::ExtendedHeaderWithMetadataForNext,
        'A' ... 'Z' => TypeFlag::VendorSpecific,
        _ => TypeFlag::Invalid
    }
}

macro_rules! take_str_eat_garbage (
 ( $i:expr, $size:expr ) => ( chain!( $i, s: map_res!(take_until!("\0"), from_utf8) ~ take!($size - s.len()), ||{ s } ));
);

fn parse_ustar00(i: &[u8]) -> IResult<&[u8], Option<UStarHeader>> {
    chain!(i,
        tag!("00")                           ~
        uname:    take_str_eat_garbage!(32)  ~
        gname:    take_str_eat_garbage!(32)  ~
        devmajor: take_str_eat_garbage!(8)   ~
        devminor: take_str_eat_garbage!(8)   ~
        prefix:   take_str_eat_garbage!(155) ~
        take!(12), /* padding to 512 */
        ||{
            Some(UStarHeader {
                magic:    "ustar\0",
                version:  "00",
                uname:    uname,
                gname:    gname,
                devmajor: octal_to_u64(devmajor),
                devminor: octal_to_u64(devminor),
                prefix:   prefix
            })
        }
    )
}

fn parse_ustar(i: &[u8]) -> IResult<&[u8], Option<UStarHeader>> {
    chain!(i,
        tag!("ustar\0") ~
        ustar: parse_ustar00,
        ||{
            ustar
        }
    )
}

fn parse_posix(i: &[u8]) -> IResult<&[u8], Option<UStarHeader>> {
    chain!(i,
        take!(255), /* padding to 512 */
        ||{
            None
        }
    )
}

fn parse_header(i: &[u8]) -> IResult<&[u8], PosixHeader> {
    chain!(i,
        name:     take_str_eat_garbage!(100) ~
        mode:     take_str_eat_garbage!(8)   ~
        uid:      take_str_eat_garbage!(8)   ~
        gid:      take_str_eat_garbage!(8)   ~
        size:     take_str_eat_garbage!(12)  ~
        mtime:    take_str_eat_garbage!(12)  ~
        chksum:   take_str_eat_garbage!(8)   ~
        typeflag: take!(1)                   ~
        linkname: take_str_eat_garbage!(100) ~
        ustar:    alt!(parse_ustar | parse_posix),
        ||{
            PosixHeader {
                name:     name,
                mode:     mode,
                uid:      octal_to_u64(uid),
                gid:      octal_to_u64(gid),
                size:     octal_to_u64(size),
                mtime:    octal_to_u64(mtime),
                chksum:   chksum,
                typeflag: char_to_type_flag(typeflag[0] as char),
                linkname: linkname,
                ustar:    ustar
            }
        }
    )
}

fn parse_contents(i: &[u8], size: u64) -> IResult<&[u8], &str> {
    let trailing = size % 512;
    let padding = match trailing {
        0 => 0,
        t => 512 - t
    };
    chain!(i,
        contents: take_str!(size as usize) ~
        take!(padding as usize),
        ||{
            contents
        }
    )
}

fn parse_entry(i: &[u8]) -> IResult<&[u8], TarEntry> {
    chain!(i,
        header:   parse_header ~
        contents: apply!(parse_contents, header.size),
        ||{
            TarEntry {
                header: header,
                contents: contents
            }
        }
    )
}

pub fn parse_tar(i: &[u8]) -> IResult<&[u8], Vec<TarEntry>> {
    many0!(i, parse_entry)
}

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

    #[test]
    fn octal_to_u64_test() {
        match octal_to_u64("756") {
            494 => {},
            o => panic!("octal_to_u64 failed, expected 494 but got {}", o)
        }
        match octal_to_u64("") {
            0 => {},
            o => panic!("octal_to_u64 failed, expected 0 but got {}", o)
        }
    }
}
<commit_msg>strip NUL entries<commit_after>use std::str::from_utf8;
use std::result::Result;
use nom::IResult;

#[derive(Debug,PartialEq,Eq)]
pub struct PosixHeader<'a> {
    pub name:     & 'a str,
    pub mode:     & 'a str,
    pub uid:      u64,
    pub gid:      u64,
    pub size:     u64,
    pub mtime:    u64,
    pub chksum:   & 'a str,
    pub typeflag: TypeFlag,
    pub linkname: & 'a str,
    pub ustar:    Option<UStarHeader<'a>>
}

#[derive(Debug,PartialEq,Eq)]
pub struct UStarHeader<'a> {
    pub magic:    & 'a str,
    pub version:  & 'a str,
    pub uname:    & 'a str,
    pub gname:    & 'a str,
    pub devmajor: u64,
    pub devminor: u64,
    pub prefix:   & 'a str,
}

#[derive(Debug,PartialEq,Eq)]
pub struct TarEntry<'a> {
    pub header:   PosixHeader<'a>,
    pub contents: & 'a str
}

/* TODO: support vendor specific + sparse */
#[derive(Debug,PartialEq,Eq)]
pub enum TypeFlag {
    NormalFile,
    HardLink,
    SymbolicLink,
    CharacterSpecial,
    BlockSpecial,
    Directory,
    FIFO,
    ContiguousFile,
    GlobalExtendedHeaderWithMetadata,
    ExtendedHeaderWithMetadataForNext,
    VendorSpecific,
    Invalid
}

/* TODO: validation */
fn str_to_u64(s: &str, base: u64) -> u64 {
    let mut u = 0;
    let mut f = 1;

    for c in s.chars().rev().skip_while(|&c| c == '\0') {
        u += f * ((c as u64) - ('0' as u64));
        f *= base;
    }

    u
}

pub fn octal_to_u64(o: &str) -> u64 {
    str_to_u64(o, 8)
}

fn char_to_type_flag(c: char) -> TypeFlag {
    match c {
        '0' | '\0' => TypeFlag::NormalFile,
        '1' => TypeFlag::HardLink,
        '2' => TypeFlag::SymbolicLink,
        '3' => TypeFlag::CharacterSpecial,
        '4' => TypeFlag::BlockSpecial,
        '5' => TypeFlag::Directory,
        '6' => TypeFlag::FIFO,
        '7' => TypeFlag::ContiguousFile,
        'g' => TypeFlag::GlobalExtendedHeaderWithMetadata,
        'x' => TypeFlag::ExtendedHeaderWithMetadataForNext,
        'A' ... 'Z' => TypeFlag::VendorSpecific,
        _ => TypeFlag::Invalid
    }
}

macro_rules! take_str_eat_garbage (
 ( $i:expr, $size:expr ) => ( chain!( $i, s: map_res!(take_until!("\0"), from_utf8) ~ take!($size - s.len()), ||{ s } ));
);

fn parse_ustar00(i: &[u8]) -> IResult<&[u8], Option<UStarHeader>> {
    chain!(i,
        tag!("00")                           ~
        uname:    take_str_eat_garbage!(32)  ~
        gname:    take_str_eat_garbage!(32)  ~
        devmajor: take_str_eat_garbage!(8)   ~
        devminor: take_str_eat_garbage!(8)   ~
        prefix:   take_str_eat_garbage!(155) ~
        take!(12), /* padding to 512 */
        ||{
            Some(UStarHeader {
                magic:    "ustar\0",
                version:  "00",
                uname:    uname,
                gname:    gname,
                devmajor: octal_to_u64(devmajor),
                devminor: octal_to_u64(devminor),
                prefix:   prefix
            })
        }
    )
}

fn parse_ustar(i: &[u8]) -> IResult<&[u8], Option<UStarHeader>> {
    chain!(i,
        tag!("ustar\0") ~
        ustar: parse_ustar00,
        ||{
            ustar
        }
    )
}

fn parse_posix(i: &[u8]) -> IResult<&[u8], Option<UStarHeader>> {
    chain!(i,
        take!(255), /* padding to 512 */
        ||{
            None
        }
    )
}

fn parse_header(i: &[u8]) -> IResult<&[u8], PosixHeader> {
    chain!(i,
        name:     take_str_eat_garbage!(100) ~
        mode:     take_str_eat_garbage!(8)   ~
        uid:      take_str_eat_garbage!(8)   ~
        gid:      take_str_eat_garbage!(8)   ~
        size:     take_str_eat_garbage!(12)  ~
        mtime:    take_str_eat_garbage!(12)  ~
        chksum:   take_str_eat_garbage!(8)   ~
        typeflag: take!(1)                   ~
        linkname: take_str_eat_garbage!(100) ~
        ustar:    alt!(parse_ustar | parse_posix),
        ||{
            PosixHeader {
                name:     name,
                mode:     mode,
                uid:      octal_to_u64(uid),
                gid:      octal_to_u64(gid),
                size:     octal_to_u64(size),
                mtime:    octal_to_u64(mtime),
                chksum:   chksum,
                typeflag: char_to_type_flag(typeflag[0] as char),
                linkname: linkname,
                ustar:    ustar
            }
        }
    )
}

fn parse_contents(i: &[u8], size: u64) -> IResult<&[u8], &str> {
    let trailing = size % 512;
    let padding = match trailing {
        0 => 0,
        t => 512 - t
    };
    chain!(i,
        contents: take_str!(size as usize) ~
        take!(padding as usize),
        ||{
            contents
        }
    )
}

fn parse_entry(i: &[u8]) -> IResult<&[u8], TarEntry> {
    chain!(i,
        header:   parse_header ~
        contents: apply!(parse_contents, header.size),
        ||{
            TarEntry {
                header: header,
                contents: contents
            }
        }
    )
}

fn filter_entries(entries: Vec<TarEntry>) -> Result<Vec<TarEntry>, &'static str> {
    Ok(entries.into_iter().filter(|e| e.header.name != "").collect::<Vec<TarEntry>>())
}

pub fn parse_tar(i: &[u8]) -> IResult<&[u8], Vec<TarEntry>> {
    map_res!(i, many0!(parse_entry), filter_entries)
}

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

    #[test]
    fn octal_to_u64_test() {
        match octal_to_u64("756") {
            494 => {},
            o => panic!("octal_to_u64 failed, expected 494 but got {}", o)
        }
        match octal_to_u64("") {
            0 => {},
            o => panic!("octal_to_u64 failed, expected 0 but got {}", o)
        }
    }
}
<|endoftext|>