<commit_before>// Copyright 2012-2014 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.

#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private))]

#[cfg(feature = "with-syntex")]
extern crate syntex_syntax as syntax;

#[cfg(not(feature = "with-syntex"))]
extern crate syntax;

use std::rc::Rc;

use syntax::ast::{self, TokenTree, Generics, Expr};
use syntax::codemap::{DUMMY_SP, Spanned, dummy_spanned};
use syntax::ext::base::ExtCtxt;
use syntax::parse::{self, classify, parse_tts_from_source_str, token};
use syntax::print::pprust;
use syntax::ptr::P;

pub trait ToTokens {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree>;
}

impl ToTokens for TokenTree {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec!(self.clone())
    }
}

impl<'a, T: ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        (**self).to_tokens(cx)
    }
}

impl<'a, T: ToTokens> ToTokens for &'a [T] {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        self.iter()
            .flat_map(|t| t.to_tokens(cx).into_iter())
            .collect()
    }
}

impl<T: ToTokens> ToTokens for Vec<T> {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        self.iter().flat_map(|t| t.to_tokens(cx).into_iter()).collect()
    }
}

impl<T: ToTokens> ToTokens for Spanned<T> {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        // FIXME: use the span?
        self.node.to_tokens(cx)
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        match self {
            &Some(ref t) => t.to_tokens(cx),
            &None => Vec::new(),
        }
    }
}

impl ToTokens for ast::Ident {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(DUMMY_SP, token::Ident(*self, token::Plain))]
    }
}

impl ToTokens for ast::Path {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtPath(Box::new(self.clone()))))]
    }
}

impl ToTokens for ast::Ty {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtTy(P(self.clone()))))]
    }
}

impl ToTokens for P<ast::Ty> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtTy(self.clone())))]
    }
}

impl ToTokens for P<ast::Block> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtBlock(self.clone())))]
    }
}

impl ToTokens for P<ast::Item> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtItem(self.clone())))]
    }
}

impl ToTokens for P<ast::ImplItem> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtImplItem(self.clone())))]
    }
}

impl ToTokens for P<ast::TraitItem> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtTraitItem(self.clone())))]
    }
}

impl ToTokens for ast::Generics {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        let s = pprust::generics_to_string(self);

        parse_tts_from_source_str("<quote expansion>".to_string(), s, cx.cfg(), cx.parse_sess())
    }
}

impl ToTokens for ast::WhereClause {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        let s = pprust::to_string(|s| {
            s.print_where_clause(&self)
        });

        parse_tts_from_source_str("<quote expansion>".to_string(), s, cx.cfg(), cx.parse_sess())
    }
}

impl ToTokens for P<ast::Stmt> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        let mut tts = vec![
            ast::TtToken(self.span, token::Interpolated(token::NtStmt(self.clone())))
        ];

        // Some statements require a trailing semicolon.
        if classify::stmt_ends_with_semi(&self.node) {
            tts.push(ast::TtToken(self.span, token::Semi));
        }

        tts
    }
}

impl ToTokens for P<ast::Expr> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtExpr(self.clone())))]
    }
}

impl ToTokens for P<ast::Pat> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtPat(self.clone())))]
    }
}

impl ToTokens for ast::Arm {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtArm(self.clone())))]
    }
}

macro_rules! impl_to_tokens_slice {
    ($t: ty, $sep: expr) => {
        impl ToTokens for [$t] {
            fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
                let mut v = vec![];
                for (i, x) in self.iter().enumerate() {
                    if i > 0 {
                        v.extend($sep.iter().cloned());
                    }
                    v.extend(x.to_tokens(cx));
                }
                v
            }
        }
    };
}

impl_to_tokens_slice! { ast::Ty, [ast::TtToken(DUMMY_SP, token::Comma)] }
impl_to_tokens_slice! { P<ast::Item>, [] }

impl ToTokens for P<ast::MetaItem> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtMeta(self.clone())))]
    }
}

impl ToTokens for ast::Attribute {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        let mut r = vec![];
        // FIXME: The spans could be better
        r.push(ast::TtToken(self.span, token::Pound));
        if self.node.style == ast::AttrInner {
            r.push(ast::TtToken(self.span, token::Not));
        }
        r.push(ast::TtDelimited(self.span, Rc::new(ast::Delimited {
            delim: token::Bracket,
            open_span: self.span,
            tts: self.node.value.to_tokens(cx),
            close_span: self.span,
        })));
        r
    }
}

impl ToTokens for str {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        let lit = ast::LitStr(
            token::intern_and_get_ident(self), ast::CookedStr);
        dummy_spanned(lit).to_tokens(cx)
    }
}

impl ToTokens for () {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtDelimited(DUMMY_SP, Rc::new(ast::Delimited {
            delim: token::Paren,
            open_span: DUMMY_SP,
            tts: vec![],
            close_span: DUMMY_SP,
        }))]
    }
}

impl ToTokens for ast::Lit {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        // FIXME: This is wrong
        P(ast::Expr {
            id: ast::DUMMY_NODE_ID,
            node: ast::ExprLit(P(self.clone())),
            span: DUMMY_SP,
        }).to_tokens(cx)
    }
}

impl ToTokens for bool {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        dummy_spanned(ast::LitBool(*self)).to_tokens(cx)
    }
}

impl ToTokens for char {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        dummy_spanned(ast::LitChar(*self)).to_tokens(cx)
    }
}

macro_rules! impl_to_tokens_int {
    (signed, $t:ty, $tag:expr) => (
        impl ToTokens for $t {
            fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
                let lit = ast::LitInt(*self as u64, ast::SignedIntLit($tag,
                                                                      ast::Sign::new(*self)));
                dummy_spanned(lit).to_tokens(cx)
            }
        }
    );
    (unsigned, $t:ty, $tag:expr) => (
        impl ToTokens for $t {
            fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
                let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit($tag));
                dummy_spanned(lit).to_tokens(cx)
            }
        }
    );
}

impl_to_tokens_int! { signed, isize, ast::TyIs }
impl_to_tokens_int! { signed, i8,  ast::TyI8 }
impl_to_tokens_int! { signed, i16, ast::TyI16 }
impl_to_tokens_int! { signed, i32, ast::TyI32 }
impl_to_tokens_int! { signed, i64, ast::TyI64 }

impl_to_tokens_int! { unsigned, usize, ast::TyUs }
impl_to_tokens_int! { unsigned, u8,   ast::TyU8 }
impl_to_tokens_int! { unsigned, u16,  ast::TyU16 }
impl_to_tokens_int! { unsigned, u32,  ast::TyU32 }
impl_to_tokens_int! { unsigned, u64,  ast::TyU64 }

pub trait ExtParseUtils {
    fn parse_item(&self, s: String) -> P<ast::Item>;
    fn parse_expr(&self, s: String) -> P<ast::Expr>;
    fn parse_stmt(&self, s: String) -> P<ast::Stmt>;
    fn parse_tts(&self, s: String) -> Vec<ast::TokenTree>;
}

impl<'a> ExtParseUtils for ExtCtxt<'a> {

    fn parse_item(&self, s: String) -> P<ast::Item> {
        parse::parse_item_from_source_str(
            "<quote expansion>".to_string(),
            s,
            self.cfg(),
            self.parse_sess()).expect("parse error")
    }

    fn parse_stmt(&self, s: String) -> P<ast::Stmt> {
        parse::parse_stmt_from_source_str("<quote expansion>".to_string(),
                                          s,
                                          self.cfg(),
                                          self.parse_sess()).expect("parse error")
    }

    fn parse_expr(&self, s: String) -> P<ast::Expr> {
        parse::parse_expr_from_source_str("<quote expansion>".to_string(),
                                          s,
                                          self.cfg(),
                                          self.parse_sess())
    }

    fn parse_tts(&self, s: String) -> Vec<ast::TokenTree> {
        parse::parse_tts_from_source_str("<quote expansion>".to_string(),
                                         s,
                                         self.cfg(),
                                         self.parse_sess())
    }
}
<commit_msg>chore(rustup): Update to latest nightly/syntex<commit_after>// Copyright 2012-2014 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.

#![cfg_attr(not(feature = "with-syntex"), feature(rustc_private))]

#[cfg(feature = "with-syntex")]
extern crate syntex_syntax as syntax;

#[cfg(not(feature = "with-syntex"))]
extern crate syntax;

use std::rc::Rc;

use syntax::ast::{self, TokenTree, Generics, Expr};
use syntax::codemap::{DUMMY_SP, Spanned, dummy_spanned};
use syntax::ext::base::ExtCtxt;
use syntax::parse::{self, classify, parse_tts_from_source_str, token};
use syntax::print::pprust;
use syntax::ptr::P;

pub trait ToTokens {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree>;
}

impl ToTokens for TokenTree {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec!(self.clone())
    }
}

impl<'a, T: ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        (**self).to_tokens(cx)
    }
}

impl<'a, T: ToTokens> ToTokens for &'a [T] {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        self.iter()
            .flat_map(|t| t.to_tokens(cx).into_iter())
            .collect()
    }
}

impl<T: ToTokens> ToTokens for Vec<T> {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        self.iter().flat_map(|t| t.to_tokens(cx).into_iter()).collect()
    }
}

impl<T: ToTokens> ToTokens for Spanned<T> {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        // FIXME: use the span?
        self.node.to_tokens(cx)
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        match self {
            &Some(ref t) => t.to_tokens(cx),
            &None => Vec::new(),
        }
    }
}

impl ToTokens for ast::Ident {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(DUMMY_SP, token::Ident(*self, token::Plain))]
    }
}

impl ToTokens for ast::Path {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtPath(Box::new(self.clone()))))]
    }
}

impl ToTokens for ast::Ty {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtTy(P(self.clone()))))]
    }
}

impl ToTokens for P<ast::Ty> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtTy(self.clone())))]
    }
}

impl ToTokens for P<ast::Block> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtBlock(self.clone())))]
    }
}

impl ToTokens for P<ast::Item> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtItem(self.clone())))]
    }
}

impl ToTokens for P<ast::ImplItem> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtImplItem(self.clone())))]
    }
}

impl ToTokens for P<ast::TraitItem> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtTraitItem(self.clone())))]
    }
}

impl ToTokens for ast::Generics {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        let s = pprust::generics_to_string(self);

        parse_tts_from_source_str("<quote expansion>".to_string(), s, cx.cfg(), cx.parse_sess())
    }
}

impl ToTokens for ast::WhereClause {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        let s = pprust::to_string(|s| {
            s.print_where_clause(&self)
        });

        parse_tts_from_source_str("<quote expansion>".to_string(), s, cx.cfg(), cx.parse_sess())
    }
}

impl ToTokens for P<ast::Stmt> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        let mut tts = vec![
            ast::TtToken(self.span, token::Interpolated(token::NtStmt(self.clone())))
        ];

        // Some statements require a trailing semicolon.
        if classify::stmt_ends_with_semi(&self.node) {
            tts.push(ast::TtToken(self.span, token::Semi));
        }

        tts
    }
}

impl ToTokens for P<ast::Expr> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtExpr(self.clone())))]
    }
}

impl ToTokens for P<ast::Pat> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(self.span, token::Interpolated(token::NtPat(self.clone())))]
    }
}

impl ToTokens for ast::Arm {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtArm(self.clone())))]
    }
}

macro_rules! impl_to_tokens_slice {
    ($t: ty, $sep: expr) => {
        impl ToTokens for [$t] {
            fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
                let mut v = vec![];
                for (i, x) in self.iter().enumerate() {
                    if i > 0 {
                        v.extend($sep.iter().cloned());
                    }
                    v.extend(x.to_tokens(cx));
                }
                v
            }
        }
    };
}

impl_to_tokens_slice! { ast::Ty, [ast::TtToken(DUMMY_SP, token::Comma)] }
impl_to_tokens_slice! { P<ast::Item>, [] }

impl ToTokens for P<ast::MetaItem> {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtToken(DUMMY_SP, token::Interpolated(token::NtMeta(self.clone())))]
    }
}

impl ToTokens for ast::Attribute {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        let mut r = vec![];
        // FIXME: The spans could be better
        r.push(ast::TtToken(self.span, token::Pound));
        if self.node.style == ast::AttrStyle::Inner {
            r.push(ast::TtToken(self.span, token::Not));
        }
        r.push(ast::TtDelimited(self.span, Rc::new(ast::Delimited {
            delim: token::Bracket,
            open_span: self.span,
            tts: self.node.value.to_tokens(cx),
            close_span: self.span,
        })));
        r
    }
}

impl ToTokens for str {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        let lit = ast::LitStr(
            token::intern_and_get_ident(self), ast::CookedStr);
        dummy_spanned(lit).to_tokens(cx)
    }
}

impl ToTokens for () {
    fn to_tokens(&self, _cx: &ExtCtxt) -> Vec<TokenTree> {
        vec![ast::TtDelimited(DUMMY_SP, Rc::new(ast::Delimited {
            delim: token::Paren,
            open_span: DUMMY_SP,
            tts: vec![],
            close_span: DUMMY_SP,
        }))]
    }
}

impl ToTokens for ast::Lit {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        // FIXME: This is wrong
        P(ast::Expr {
            id: ast::DUMMY_NODE_ID,
            node: ast::ExprLit(P(self.clone())),
            span: DUMMY_SP,
        }).to_tokens(cx)
    }
}

impl ToTokens for bool {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        dummy_spanned(ast::LitBool(*self)).to_tokens(cx)
    }
}

impl ToTokens for char {
    fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
        dummy_spanned(ast::LitChar(*self)).to_tokens(cx)
    }
}

macro_rules! impl_to_tokens_int {
    (signed, $t:ty, $tag:expr) => (
        impl ToTokens for $t {
            fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
                let lit = ast::LitInt(*self as u64, ast::SignedIntLit($tag,
                                                                      ast::Sign::new(*self)));
                dummy_spanned(lit).to_tokens(cx)
            }
        }
    );
    (unsigned, $t:ty, $tag:expr) => (
        impl ToTokens for $t {
            fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
                let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit($tag));
                dummy_spanned(lit).to_tokens(cx)
            }
        }
    );
}

impl_to_tokens_int! { signed, isize, ast::TyIs }
impl_to_tokens_int! { signed, i8,  ast::TyI8 }
impl_to_tokens_int! { signed, i16, ast::TyI16 }
impl_to_tokens_int! { signed, i32, ast::TyI32 }
impl_to_tokens_int! { signed, i64, ast::TyI64 }

impl_to_tokens_int! { unsigned, usize, ast::TyUs }
impl_to_tokens_int! { unsigned, u8,   ast::TyU8 }
impl_to_tokens_int! { unsigned, u16,  ast::TyU16 }
impl_to_tokens_int! { unsigned, u32,  ast::TyU32 }
impl_to_tokens_int! { unsigned, u64,  ast::TyU64 }

pub trait ExtParseUtils {
    fn parse_item(&self, s: String) -> P<ast::Item>;
    fn parse_expr(&self, s: String) -> P<ast::Expr>;
    fn parse_stmt(&self, s: String) -> P<ast::Stmt>;
    fn parse_tts(&self, s: String) -> Vec<ast::TokenTree>;
}

impl<'a> ExtParseUtils for ExtCtxt<'a> {

    fn parse_item(&self, s: String) -> P<ast::Item> {
        parse::parse_item_from_source_str(
            "<quote expansion>".to_string(),
            s,
            self.cfg(),
            self.parse_sess()).expect("parse error")
    }

    fn parse_stmt(&self, s: String) -> P<ast::Stmt> {
        parse::parse_stmt_from_source_str("<quote expansion>".to_string(),
                                          s,
                                          self.cfg(),
                                          self.parse_sess()).expect("parse error")
    }

    fn parse_expr(&self, s: String) -> P<ast::Expr> {
        parse::parse_expr_from_source_str("<quote expansion>".to_string(),
                                          s,
                                          self.cfg(),
                                          self.parse_sess())
    }

    fn parse_tts(&self, s: String) -> Vec<ast::TokenTree> {
        parse::parse_tts_from_source_str("<quote expansion>".to_string(),
                                         s,
                                         self.cfg(),
                                         self.parse_sess())
    }
}
<|endoftext|>


<commit_before>use common::util::*;

static UTIL_NAME: &'static str = "base64";

#[test]
fn test_encode() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let input = "hello, world!";
    let result = ucmd.run_piped_stdin(input.as_bytes());

    assert_empty_stderr!(result);
    assert!(result.success);
    assert_eq!(result.stdout, "aGVsbG8sIHdvcmxkIQ==\n");
}

#[test]
fn test_decode() {
    for decode_param in vec!["-d", "--decode"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "aGVsbG8sIHdvcmxkIQ==";
        let result = ucmd.arg(decode_param).run_piped_stdin(input.as_bytes());

        assert_empty_stderr!(result);
        assert!(result.success);
        assert_eq!(result.stdout, "hello, world!");
    }
}

#[test]
fn test_garbage() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let input = "aGVsbG8sIHdvcmxkIQ==\0";
    let result = ucmd.arg("-d").run_piped_stdin(input.as_bytes());

    assert!(!result.success);
    assert_eq!(result.stderr,
               "base64: error: invalid character (Invalid character '0' at position 20)\n");
}

#[test]
fn test_ignore_garbage() {
    for ignore_garbage_param in vec!["-i", "--ignore-garbage"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "aGVsbG8sIHdvcmxkIQ==\0";
        let result = ucmd.arg("-d").arg(ignore_garbage_param).run_piped_stdin(input.as_bytes());
        assert_empty_stderr!(result);
        assert!(result.success);
        assert_eq!(result.stdout, "hello, world!");
    }
}

#[test]
fn test_wrap() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "The quick brown fox jumps over the lazy dog.";
        let result = ucmd.arg(wrap_param).arg("20").run_piped_stdin(input.as_bytes());

        assert_empty_stderr!(result);
        assert!(result.success);
        assert_eq!(result.stdout,
                   "VGhlIHF1aWNrIGJyb3du\nIGZveCBqdW1wcyBvdmVy\nIHRoZSBsYXp5IGRvZy4=\n");
    }
}

#[test]
fn test_wrap_no_arg() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let result = ucmd.arg(wrap_param).run();

        assert!(!result.success);
        assert!(result.stdout.len() == 0);
        assert_eq!(result.stderr.trim_right(),
                   format!("base64: error: Argument to option '{}' missing.",
                           if wrap_param == "-w" { "w" } else { "wrap" }));
    }
}

#[test]
fn test_wrap_bad_arg() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let result = ucmd.arg(wrap_param).arg("b").run();

        assert!(!result.success);
        assert!(result.stdout.len() == 0);
        assert_eq!(result.stderr.trim_right(),
                   "base64: error: Argument to option 'wrap' improperly formatted: invalid digit found in string");
    }
}
<commit_msg>base64: refactor tests to be more terse<commit_after>use common::util::*;

static UTIL_NAME: &'static str = "base64";

#[test]
fn test_encode() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let input = "hello, world!";
    ucmd.run_piped_stdin(input.as_bytes())
        .success()
        .stdout_only("aGVsbG8sIHdvcmxkIQ==\n");
}

#[test]
fn test_decode() {
    for decode_param in vec!["-d", "--decode"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "aGVsbG8sIHdvcmxkIQ==";
        ucmd.arg(decode_param).run_piped_stdin(input.as_bytes())
            .success()
            .stdout_only("hello, world!");
    }
}

#[test]
fn test_garbage() {
    let (_, mut ucmd) = testing(UTIL_NAME);
    let input = "aGVsbG8sIHdvcmxkIQ==\0";
    ucmd.arg("-d").run_piped_stdin(input.as_bytes())
        .failure()
        .stderr_only("base64: error: invalid character (Invalid character '0' at position 20)\n");
}

#[test]
fn test_ignore_garbage() {
    for ignore_garbage_param in vec!["-i", "--ignore-garbage"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "aGVsbG8sIHdvcmxkIQ==\0";
        ucmd.arg("-d").arg(ignore_garbage_param).run_piped_stdin(input.as_bytes())
            .success()
            .stdout_only("hello, world!");
    }
}

#[test]
fn test_wrap() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        let input = "The quick brown fox jumps over the lazy dog.";
        ucmd.arg(wrap_param).arg("20").run_piped_stdin(input.as_bytes())
            .success()
            .stdout_only("VGhlIHF1aWNrIGJyb3du\nIGZveCBqdW1wcyBvdmVy\nIHRoZSBsYXp5IGRvZy4=\n");
    }
}

#[test]
fn test_wrap_no_arg() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        ucmd.arg(wrap_param).run()
            .failure()
            .stderr_only(
                format!("base64: error: Argument to option '{}' missing.",
                        if wrap_param == "-w" { "w" } else { "wrap" }));
    }
}

#[test]
fn test_wrap_bad_arg() {
    for wrap_param in vec!["-w", "--wrap"] {
        let (_, mut ucmd) = testing(UTIL_NAME);
        ucmd.arg(wrap_param).arg("b").run()
            .failure()
            .stderr_only("base64: error: Argument to option 'wrap' improperly formatted: invalid digit found in string");
    }
}
<|endoftext|>


<commit_before>use basm;
use clap::ArgMatches;
use definitions::{DisplayResolution, ImageBuilder, InternalInterrupt, Target, Value};
use definitions::typedef::*;
use error::*;
use std::fs::File;
use std::io::Write;

pub fn stock(_matches: &ArgMatches) -> Result<()> {
    let mut builder = ImageBuilder::new();

    let res_def = DisplayResolution::default();

    let max = res_def.width * res_def.height;

    for x in 0..max {
        builder.push(Target::ValueIndex(0), Value::Integer(x as Integer));
        builder.push(Target::Framebuffer, Value::Color(0, 0, 0));
    }

    // Triangle
    builder.push(
        Target::ValueIndex(0),
        Value::Integer((res_def.width + 1) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 2) + 2) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 3) + 3) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 4) + 4) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 5) + 3) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 6) + 2) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 1) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    // Underscore
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 6) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 7) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 8) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 9) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 10) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 11) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.int(InternalInterrupt::FlushFramebuffer);

    builder.pause();
    builder.jmp(max + 1);

    let program_data = builder.gen();

    let mut output_file = File::create("stock.img").chain_err(|| "unable to open output file")?;

    output_file.write_all(&program_data[..]).chain_err(|| "unable to write output file")?;

    output_file.sync_all().chain_err(|| "unable to sync output file to file system")?;

    Ok(())
}

pub fn compile(matches: &ArgMatches) -> Result<()> {
    let input_file_name = if let Some(file_name) = matches.value_of("input") {
        file_name
    } else {
        bail!("no file name given");
    };

    let file = File::open(input_file_name).chain_err(|| "unable to open file")?;

    if matches.is_present("basm") {
        let program = basm::compile(file).chain_err(|| "unable to compile file")?;

        let output_file_name = if let Some(file_name) = matches.value_of("output") {
            file_name.to_owned()
        } else {
            format!("{}.bin", input_file_name)
        };

        let mut file = File::create(output_file_name).chain_err(|| "unable to create file")?;

        file.write_all(&program[..]).chain_err(|| "unable to write program data")?;

        file.sync_all().chain_err(|| "unable to sync output file to file system")?;
    }

    Ok(())
}
<commit_msg>Changed binary file extension to .img<commit_after>use basm;
use clap::ArgMatches;
use definitions::{DisplayResolution, ImageBuilder, InternalInterrupt, Target, Value};
use definitions::typedef::*;
use error::*;
use std::fs::File;
use std::io::Write;

pub fn stock(_matches: &ArgMatches) -> Result<()> {
    let mut builder = ImageBuilder::new();

    let res_def = DisplayResolution::default();

    let max = res_def.width * res_def.height;

    for x in 0..max {
        builder.push(Target::ValueIndex(0), Value::Integer(x as Integer));
        builder.push(Target::Framebuffer, Value::Color(0, 0, 0));
    }

    // Triangle
    builder.push(
        Target::ValueIndex(0),
        Value::Integer((res_def.width + 1) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 2) + 2) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 3) + 3) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 4) + 4) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 5) + 3) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 6) + 2) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 1) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    // Underscore
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 6) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 7) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 8) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 9) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 10) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));
    builder.push(
        Target::ValueIndex(0),
        Value::Integer(((res_def.width * 7) + 11) as Integer),
    );
    builder.push(Target::Framebuffer, Value::Color(0xFF, 0xFF, 0xFF));

    builder.int(InternalInterrupt::FlushFramebuffer);

    builder.pause();
    builder.jmp(max + 1);

    let program_data = builder.gen();

    let mut output_file = File::create("stock.img").chain_err(|| "unable to open output file")?;

    output_file.write_all(&program_data[..]).chain_err(|| "unable to write output file")?;

    output_file.sync_all().chain_err(|| "unable to sync output file to file system")?;

    Ok(())
}

pub fn compile(matches: &ArgMatches) -> Result<()> {
    let input_file_name = if let Some(file_name) = matches.value_of("input") {
        file_name
    } else {
        bail!("no file name given");
    };

    let file = File::open(input_file_name).chain_err(|| "unable to open file")?;

    if matches.is_present("basm") {
        let program = basm::compile(file).chain_err(|| "unable to compile file")?;

        let output_file_name = if let Some(file_name) = matches.value_of("output") {
            file_name.to_owned()
        } else {
            format!("{}.img", input_file_name)
        };

        let mut file = File::create(output_file_name).chain_err(|| "unable to create file")?;

        file.write_all(&program[..]).chain_err(|| "unable to write program data")?;

        file.sync_all().chain_err(|| "unable to sync output file to file system")?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>extern crate rs6502;
extern crate sdl2;
extern crate vm;

mod ship;

use std::path::Path;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::image::LoadTexture;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::TextureQuery;

use rs6502::{Assembler, Cpu};
use vm::VirtualMachine;

const FPS_STEP: u32 = 1000 / 60;

fn main() {

    let bytecode = assemble("level.asm");
    let cpu = init_cpu(&bytecode);
    let mut vm = VirtualMachine::new(cpu, 0xC000, 150);

    let sdl_context = sdl2::init().unwrap();
    let ttf_context = sdl2::ttf::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("Hakka", 400, 720)
        .position_centered()
        .build()
        .unwrap();

    let mut renderer = window.renderer()
        .accelerated()
        .build()
        .unwrap();

    let ship_texture = renderer.load_texture(Path::new("ship.png")).unwrap();
    let ship_flame_texture = renderer.load_texture(Path::new("ship-flame.png")).unwrap();

    let mut win_font = ttf_context.load_font(Path::new("FantasqueSansMono-Bold.ttf"), 64).unwrap();
    win_font.set_style(sdl2::ttf::STYLE_BOLD);

    let mut finish_font = ttf_context.load_font(Path::new("FantasqueSansMono-Bold.ttf"), 64)
        .unwrap();
    finish_font.set_style(sdl2::ttf::STYLE_BOLD);

    let win_message_surface = win_font.render("You win!")
        .blended(Color::RGBA(0, 153, 192, 255))
        .unwrap();
    let finish_banner_surface = finish_font.render("FINISH")
        .blended_wrapped(Color::RGBA(0, 0, 0, 255), 56)
        .unwrap();
    let win_message_texture = renderer.create_texture_from_surface(&win_message_surface)
        .unwrap();
    let finish_banner_texture = renderer.create_texture_from_surface(&finish_banner_surface)
        .unwrap();
    let mut events = sdl_context.event_pump().unwrap();

    let mut ship = ship::Ship::new(ship_texture, ship_flame_texture);
    let mut last_fps = 0;
    let mut monitor_last = 0;
    let TextureQuery { width: win_width, height: win_height, .. } = win_message_texture.query();
    let TextureQuery { width: finish_width, height: finish_height, .. } =
        finish_banner_texture.query();

    'running: loop {

        for event in events.poll_iter() {
            match event {
                Event::Quit { .. } => break 'running,
                Event::KeyDown { keycode: Option::Some(Keycode::Up), .. } => {
                    vm.cpu.memory[0x04] = 38;
                }
                Event::KeyDown { keycode: Option::Some(Keycode::Down), .. } => {
                    vm.cpu.memory[0x04] = 40;
                }
                Event::KeyUp { keycode: Option::Some(Keycode::Up), .. } => {
                    vm.cpu.memory[0x04] = 0;
                }
                Event::KeyUp { keycode: Option::Some(Keycode::Down), .. } => {
                    vm.cpu.memory[0x04] = 0;
                }
                Event::KeyDown { keycode: Option::Some(Keycode::Escape), .. } => break 'running,
                _ => (),
            }
        }

        if ship.y < 0xA0 {
            renderer.clear();
            renderer.copy(&win_message_texture,
                      None,
                      Some(Rect::new(75, 200, win_width, win_height)))
                .unwrap();
            renderer.present();
        } else {
            vm.try_execute_command();
            ship.process(&vm.cpu.memory[..]);

            // Pull the ship back so it can't go past a certain spot
            if ship.y <= 0x190 && vm.cpu.memory[0x04] != 0 {
                vm.cpu.memory[0x02] = 0x90;
                vm.cpu.memory[0x03] = 0x01;
            }

            let now = sdl_context.timer().unwrap().ticks();
            let delta = now - last_fps;
            if delta < FPS_STEP {
                sdl_context.timer().unwrap().delay(FPS_STEP - delta);
            } else {
                vm.cycle();
                if !vm.cpu.flags.interrupt_disabled {
                    renderer.clear();
                    renderer.set_draw_color(Color::RGB(0, 144, 192));
                    renderer.fill_rect(Rect::new(0, 0, 400, 120)).unwrap();
                    renderer.set_draw_color(Color::RGB(0, 0, 0));
                    renderer.copy(&finish_banner_texture,
                              None,
                              Some(Rect::new(100, 25, finish_width, finish_height)))
                        .unwrap();
                    if vm.cpu.memory[0x07] > 0 {
                        ship.render_flame(&mut renderer);
                    }
                    ship.render(&mut renderer);
                    renderer.present();
                    last_fps = now;
                }
            }

            // Dump the CPU memory at 1 second intervals if the monitor is enabled
            let delta = now - monitor_last;
            if delta > 1000 && vm.monitor.enabled {
                vm.dump_memory();
                monitor_last = now;
            }
        }
    }
}

fn assemble<P>(path: P) -> Vec<u8>
    where P: AsRef<Path>
{
    let mut assembler = Assembler::new();
    assembler.assemble_file(path).unwrap()
}

fn init_cpu(bytecode: &[u8]) -> Cpu {
    let mut cpu = Cpu::new();
    cpu.load(&bytecode[..], None).unwrap();
    cpu.flags.interrupt_disabled = false;

    cpu.memory[0x00] = 0x90;
    cpu.memory[0x02] = 0xFF;
    cpu.memory[0x03] = 0x01;
    cpu.memory[0x05] = 0x05;
    cpu.memory[0x06] = 0x00;

    cpu
}<commit_msg>Render the level complete message over the top of the scene<commit_after>extern crate rs6502;
extern crate sdl2;
extern crate vm;

mod ship;

use std::path::Path;

use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::image::LoadTexture;
use sdl2::pixels::Color;
use sdl2::rect::Rect;
use sdl2::render::TextureQuery;

use rs6502::{Assembler, Cpu};
use vm::VirtualMachine;

const FPS_STEP: u32 = 1000 / 60;

fn main() {

    let bytecode = assemble("level.asm");
    let cpu = init_cpu(&bytecode);
    let mut vm = VirtualMachine::new(cpu, 0xC000, 150);

    let sdl_context = sdl2::init().unwrap();
    let ttf_context = sdl2::ttf::init().unwrap();
    let video_subsystem = sdl_context.video().unwrap();

    let window = video_subsystem.window("Hakka", 400, 720)
        .position_centered()
        .build()
        .unwrap();

    let mut renderer = window.renderer()
        .accelerated()
        .build()
        .unwrap();

    let ship_texture = renderer.load_texture(Path::new("ship.png")).unwrap();
    let ship_flame_texture = renderer.load_texture(Path::new("ship-flame.png")).unwrap();

    let mut win_font = ttf_context.load_font(Path::new("FantasqueSansMono-Bold.ttf"), 64).unwrap();
    win_font.set_style(sdl2::ttf::STYLE_BOLD);

    let mut finish_font = ttf_context.load_font(Path::new("FantasqueSansMono-Bold.ttf"), 64)
        .unwrap();
    finish_font.set_style(sdl2::ttf::STYLE_BOLD);

    let win_message_surface = win_font.render("You win!")
        .blended(Color::RGBA(0, 153, 192, 255))
        .unwrap();
    let finish_banner_surface = finish_font.render("FINISH")
        .blended_wrapped(Color::RGBA(0, 0, 0, 255), 56)
        .unwrap();
    let win_message_texture = renderer.create_texture_from_surface(&win_message_surface)
        .unwrap();
    let finish_banner_texture = renderer.create_texture_from_surface(&finish_banner_surface)
        .unwrap();
    let mut events = sdl_context.event_pump().unwrap();

    let mut level_complete = false;
    let mut ship = ship::Ship::new(ship_texture, ship_flame_texture);
    let mut last_fps = 0;
    let mut monitor_last = 0;
    let TextureQuery { width: win_width, height: win_height, .. } = win_message_texture.query();
    let TextureQuery { width: finish_width, height: finish_height, .. } =
        finish_banner_texture.query();

    'running: loop {

        for event in events.poll_iter() {
            match event {
                Event::Quit { .. } => break 'running,
                Event::KeyDown { keycode: Option::Some(Keycode::Up), .. } => {
                    vm.cpu.memory[0x04] = 38;
                }
                Event::KeyDown { keycode: Option::Some(Keycode::Down), .. } => {
                    vm.cpu.memory[0x04] = 40;
                }
                Event::KeyUp { keycode: Option::Some(Keycode::Up), .. } => {
                    vm.cpu.memory[0x04] = 0;
                }
                Event::KeyUp { keycode: Option::Some(Keycode::Down), .. } => {
                    vm.cpu.memory[0x04] = 0;
                }
                Event::KeyDown { keycode: Option::Some(Keycode::Escape), .. } => break 'running,
                _ => (),
            }
        }

        if !level_complete {
            vm.try_execute_command();
            ship.process(&vm.cpu.memory[..]);

            // Pull the ship back so it can't go past a certain spot
            if ship.y <= 0x190 && ship.y >= 0x100 && vm.cpu.memory[0x04] != 0 {
                vm.cpu.memory[0x02] = 0x90;
                vm.cpu.memory[0x03] = 0x01;
            }
        }

        let now = sdl_context.timer().unwrap().ticks();
        let delta = now - last_fps;
        if delta < FPS_STEP {
            sdl_context.timer().unwrap().delay(FPS_STEP - delta);
        } else {
            vm.cycle();
            if !vm.cpu.flags.interrupt_disabled {
                renderer.clear();
                renderer.set_draw_color(Color::RGB(0, 144, 192));
                renderer.fill_rect(Rect::new(0, 0, 400, 120)).unwrap();
                renderer.set_draw_color(Color::RGB(0, 0, 0));
                renderer.copy(&finish_banner_texture,
                          None,
                          Some(Rect::new(100, 25, finish_width, finish_height)))
                    .unwrap();
                if vm.cpu.memory[0x07] > 0 {
                    ship.render_flame(&mut renderer);
                }
                ship.render(&mut renderer);
                if ship.y <= 0x8C {
                    level_complete = true;
                    renderer.copy(&win_message_texture,
                              None,
                              Some(Rect::new(75, 200, win_width, win_height)))
                        .unwrap();
                }
                renderer.present();
                last_fps = now;
            }
        }

        // Dump the CPU memory at 1 second intervals if the monitor is enabled
        let delta = now - monitor_last;
        if delta > 1000 && vm.monitor.enabled {
            vm.dump_memory();
            monitor_last = now;
        }
    }
}

fn assemble<P>(path: P) -> Vec<u8>
    where P: AsRef<Path>
{
    let mut assembler = Assembler::new();
    assembler.assemble_file(path, 0xC000).unwrap()
}

fn init_cpu(bytecode: &[u8]) -> Cpu {
    let mut cpu = Cpu::new();
    cpu.load(&bytecode[..], None).unwrap();
    cpu.flags.interrupt_disabled = false;

    cpu.memory[0x00] = 0x90;
    cpu.memory[0x02] = 0xFF;
    cpu.memory[0x03] = 0x01;
    cpu.memory[0x05] = 0x05;
    cpu.memory[0x06] = 0x00;

    cpu
}<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

//! Event types
//!
//! This module contains types that represent events. These types (which wrap FileLockEntries from
//! the Store) represent Events, thus they have functionality for settings the start and end-time,
//! getting the start and end time and also deleting start and end time.
//!

use chrono::naive::NaiveDateTime;

use libimagstore::store::Entry;
use libimagerror::into::IntoError;

use tag::TimeTrackingTag as TTT;
use error::TimeTrackErrorKind as TTEK;
use error::MapErrInto;
use result::Result;
use constants::*;

use toml::Value;
use toml_query::delete::TomlValueDeleteExt;
use toml_query::insert::TomlValueInsertExt;
use toml_query::read::TomlValueReadExt;

pub trait TimeTracking {

    fn get_timetrack_tag(&self) -> Result<TTT>;

    fn set_start_datetime(&mut self, dt: NaiveDateTime) -> Result<()>;

    fn get_start_datetime(&self) -> Result<Option<NaiveDateTime>>;

    fn delete_start_datetime(&mut self) -> Result<()>;

    fn set_end_datetime(&mut self, dt: NaiveDateTime) -> Result<()>;

    fn get_end_datetime(&self) -> Result<Option<NaiveDateTime>>;

    fn delete_end_datetime(&mut self) -> Result<()>;

    fn valid(&self) -> Result<bool>;

}

impl TimeTracking for Entry {

    fn get_timetrack_tag(&self) -> Result<TTT> {
        self.get_header()
            .read(DATE_TIME_TAG_HEADER_PATH)
            .map_err_into(TTEK::HeaderReadError)
            .map(|value| match value {
                Some(&Value::String(ref s)) => s.clone().into(),
                _ => unimplemented!(),
            })
    }

    fn set_start_datetime(&mut self, dt: NaiveDateTime) -> Result<()> {
        let s = dt.format(DATE_TIME_FORMAT).to_string();

        self.get_header_mut()
            .insert(DATE_TIME_START_HEADER_PATH, Value::String(s))
            .map_err_into(TTEK::HeaderWriteError)
            .map(|_| ())
    }

    fn get_start_datetime(&self) -> Result<Option<NaiveDateTime>> {
        self.get_header()
            .read(DATE_TIME_START_HEADER_PATH)
            .map_err_into(TTEK::HeaderReadError)
            .and_then(header_value_to_dt)
    }

    fn delete_start_datetime(&mut self) -> Result<()> {
        self.get_header_mut()
            .delete(DATE_TIME_START_HEADER_PATH)
            .map_err_into(TTEK::HeaderWriteError)
            .map(|_| ())
    }

    fn set_end_datetime(&mut self, dt: NaiveDateTime) -> Result<()> {
        let s = dt.format(DATE_TIME_FORMAT).to_string();

        self.get_header_mut()
            .insert(DATE_TIME_END_HEADER_PATH, Value::String(s))
            .map_err_into(TTEK::HeaderWriteError)
            .map(|_| ())
    }

    fn get_end_datetime(&self) -> Result<Option<NaiveDateTime>> {
        self.get_header()
            .read(DATE_TIME_END_HEADER_PATH)
            .map_err_into(TTEK::HeaderReadError)
            .and_then(header_value_to_dt)
    }

    fn delete_end_datetime(&mut self) -> Result<()> {
        self.get_header_mut()
            .delete(DATE_TIME_END_HEADER_PATH)
            .map_err_into(TTEK::HeaderWriteError)
            .map(|_| ())
    }

    /// Check whether the Event is valid
    ///
    /// That is:
    ///
    /// * The end date is after the start date (or not set)
    ///
    /// # Return values
    ///
    /// Ok(true) if Event is valid
    /// Ok(false) if Event is invalid
    /// Err(e) if checking validity failed
    ///
    fn valid(&self) -> Result<bool> {
        self.get_start_datetime().and_then(|st| self.get_end_datetime().map(|et| st <= et))
    }

}

fn header_value_to_dt(val: Option<&Value>) -> Result<Option<NaiveDateTime>> {
    match val {
        Some(&Value::String(ref s)) => {
            NaiveDateTime::parse_from_str(s, DATE_TIME_FORMAT)
                .map_err_into(TTEK::DateTimeParserError)
                .map(Some)

        },
        Some(_) => Err(TTEK::HeaderFieldTypeError.into_error()),
        None => Ok(None),
    }
}

<commit_msg>Fix TimeTracking::get_timetrack_tag() for Entry<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

//! Event types
//!
//! This module contains types that represent events. These types (which wrap FileLockEntries from
//! the Store) represent Events, thus they have functionality for settings the start and end-time,
//! getting the start and end time and also deleting start and end time.
//!

use chrono::naive::NaiveDateTime;

use libimagstore::store::Entry;
use libimagerror::into::IntoError;

use tag::TimeTrackingTag as TTT;
use error::TimeTrackErrorKind as TTEK;
use error::MapErrInto;
use result::Result;
use constants::*;

use toml::Value;
use toml_query::delete::TomlValueDeleteExt;
use toml_query::insert::TomlValueInsertExt;
use toml_query::read::TomlValueReadExt;

pub trait TimeTracking {

    fn get_timetrack_tag(&self) -> Result<TTT>;

    fn set_start_datetime(&mut self, dt: NaiveDateTime) -> Result<()>;

    fn get_start_datetime(&self) -> Result<Option<NaiveDateTime>>;

    fn delete_start_datetime(&mut self) -> Result<()>;

    fn set_end_datetime(&mut self, dt: NaiveDateTime) -> Result<()>;

    fn get_end_datetime(&self) -> Result<Option<NaiveDateTime>>;

    fn delete_end_datetime(&mut self) -> Result<()>;

    fn valid(&self) -> Result<bool>;

}

impl TimeTracking for Entry {

    fn get_timetrack_tag(&self) -> Result<TTT> {
        self.get_header()
            .read(DATE_TIME_TAG_HEADER_PATH)
            .map_err_into(TTEK::HeaderReadError)
            .and_then(|value| match value {
                Some(&Value::String(ref s)) => Ok(s.clone().into()),
                Some(_) => Err(TTEK::HeaderFieldTypeError.into_error()),
                _ => Err(TTEK::HeaderReadError.into_error())
            })
    }

    fn set_start_datetime(&mut self, dt: NaiveDateTime) -> Result<()> {
        let s = dt.format(DATE_TIME_FORMAT).to_string();

        self.get_header_mut()
            .insert(DATE_TIME_START_HEADER_PATH, Value::String(s))
            .map_err_into(TTEK::HeaderWriteError)
            .map(|_| ())
    }

    fn get_start_datetime(&self) -> Result<Option<NaiveDateTime>> {
        self.get_header()
            .read(DATE_TIME_START_HEADER_PATH)
            .map_err_into(TTEK::HeaderReadError)
            .and_then(header_value_to_dt)
    }

    fn delete_start_datetime(&mut self) -> Result<()> {
        self.get_header_mut()
            .delete(DATE_TIME_START_HEADER_PATH)
            .map_err_into(TTEK::HeaderWriteError)
            .map(|_| ())
    }

    fn set_end_datetime(&mut self, dt: NaiveDateTime) -> Result<()> {
        let s = dt.format(DATE_TIME_FORMAT).to_string();

        self.get_header_mut()
            .insert(DATE_TIME_END_HEADER_PATH, Value::String(s))
            .map_err_into(TTEK::HeaderWriteError)
            .map(|_| ())
    }

    fn get_end_datetime(&self) -> Result<Option<NaiveDateTime>> {
        self.get_header()
            .read(DATE_TIME_END_HEADER_PATH)
            .map_err_into(TTEK::HeaderReadError)
            .and_then(header_value_to_dt)
    }

    fn delete_end_datetime(&mut self) -> Result<()> {
        self.get_header_mut()
            .delete(DATE_TIME_END_HEADER_PATH)
            .map_err_into(TTEK::HeaderWriteError)
            .map(|_| ())
    }

    /// Check whether the Event is valid
    ///
    /// That is:
    ///
    /// * The end date is after the start date (or not set)
    ///
    /// # Return values
    ///
    /// Ok(true) if Event is valid
    /// Ok(false) if Event is invalid
    /// Err(e) if checking validity failed
    ///
    fn valid(&self) -> Result<bool> {
        self.get_start_datetime().and_then(|st| self.get_end_datetime().map(|et| st <= et))
    }

}

fn header_value_to_dt(val: Option<&Value>) -> Result<Option<NaiveDateTime>> {
    match val {
        Some(&Value::String(ref s)) => {
            NaiveDateTime::parse_from_str(s, DATE_TIME_FORMAT)
                .map_err_into(TTEK::DateTimeParserError)
                .map(Some)

        },
        Some(_) => Err(TTEK::HeaderFieldTypeError.into_error()),
        None => Ok(None),
    }
}

<|endoftext|>


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

extern crate claxon;
extern crate hound;
extern crate walkdir;

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

fn run_metaflac_streaminfo<P: AsRef<Path>>(fname: P) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all streaminfo data.
    let output = Command::new("metaflac")
        .arg("--show-min-blocksize")
        .arg("--show-max-blocksize")
        .arg("--show-min-framesize")
        .arg("--show-max-framesize")
        .arg("--show-sample-rate")
        .arg("--show-channels")
        .arg("--show-bps")
        .arg("--show-total-samples")
        .arg("--show-md5sum")
        .arg(fname.as_ref().to_str().expect("unsupported filename"))
        .output()
        .expect("failed to run metaflac");
    String::from_utf8(output.stdout).expect("metaflac wrote invalid UTF-8")
}

fn run_metaflac_vorbis_comment<P: AsRef<Path>>(fname: P) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all Vorbis comment data.
    let output = Command::new("metaflac")
        .arg("--block-type=VORBIS_COMMENT")
        .arg("--list")
        .arg(fname.as_ref().to_str().expect("unsupported filename"))
        .output()
        .expect("failed to run metaflac");
    String::from_utf8(output.stdout).expect("metaflac wrote invalid UTF-8")
}

fn decode_file<P: AsRef<Path>>(fname: P) -> Vec<u8> {
    use std::process::Command;

    // Run the the reference flac decoder on the file.
    let output = Command::new("flac")
        .arg("--decode")
        .arg("--silent")
        .arg("--stdout")
        .arg(fname.as_ref().to_str().expect("unsupported filename"))
        .output()
        .expect("failed to run flac");

    assert!(output.status.success());
    output.stdout
}

fn print_hex(seq: &[u8]) -> String {
    let vec: Vec<String> = seq.iter().map(|x| format!("{:0>2x}", *x)).collect();
    vec.concat()
}

fn read_streaminfo<P: AsRef<Path>>(fname: P) -> String {
    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let reader = io::BufReader::new(file);
    let stream = claxon::FlacReader::new(reader).unwrap();
    let streaminfo = stream.streaminfo();

    // Format the streaminfo in the same way that metaflac prints it.
    format!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
            streaminfo.min_block_size,
            streaminfo.max_block_size,
            streaminfo.min_frame_size.unwrap_or(0),
            streaminfo.max_frame_size.unwrap_or(0),
            streaminfo.sample_rate,
            streaminfo.channels,
            streaminfo.bits_per_sample,
            streaminfo.samples.unwrap_or(0),
            print_hex(&streaminfo.md5sum)) // TODO implement LowerHex for &[u8] and submit a PR.
}

fn compare_metaflac_streaminfo<P: AsRef<Path>>(fname: P) {
    let metaflac = run_metaflac_streaminfo(&fname);
    let streaminfo = read_streaminfo(&fname);
    let mut mf_lines = metaflac.lines();
    let mut si_lines = streaminfo.lines();
    while let (Some(mf), Some(si)) = (mf_lines.next(), si_lines.next()) {
        if mf != si {
            println!("metaflac\n--------\n{}", metaflac);
            println!("streaminfo\n----------\n{}", streaminfo);
            panic!("metaflac disagrees on parsed streaminfo");
        }
    }
}

fn compare_metaflac_vorbis_comment<P: AsRef<Path>>(fname: P) {
    let metaflac = run_metaflac_vorbis_comment(&fname);

    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let buf_reader = io::BufReader::new(file);
    let reader = claxon::FlacReader::new(buf_reader).unwrap();

    let mut mf_lines = metaflac.lines();

    // Search for the vendor string in the metaflac output.
    while let Some(line) = mf_lines.next() {
        let prefix = "  vendor string: ";
        if line.starts_with(prefix) {
            let mf_vendor_string = &line[prefix.len()..];
            assert_eq!(reader.vendor(), Some(mf_vendor_string));
            break
        }
    }

    let mut tags = reader.tags().iter();

    // Loop through all of the comments.
    while let Some(line) = mf_lines.next() {
        let prefix = "    comment[";
        if line.starts_with(prefix) {
            let mf_line = &line[prefix.len()..];
            let prefix_sep_index = mf_line.find(' ').unwrap();
            let mf_pair = &mf_line[prefix_sep_index + 1..];

            let sep_index = mf_pair.find('=').unwrap();
            let mf_name = &mf_pair[..sep_index];
            let mf_value = &mf_pair[sep_index + 1..];

            let &(ref name, ref value) = tags.next().unwrap();

            assert_eq!(name, mf_name);
            assert_eq!(value, mf_value);
        }
    }
}

fn compare_decoded_stream<P: AsRef<Path>>(fname: P) {
    let wav = decode_file(&fname);
    let cursor = io::Cursor::new(wav);

    // Compare the reference decoded by the 'flac' program (stored as wav, which
    // we read with Hound) to how Claxon decodes it, sample by sample.
    let mut ref_wav_reader = hound::WavReader::new(cursor).unwrap();

    let try_file = fs::File::open(fname).unwrap();
    let try_buf_reader = io::BufReader::new(try_file);
    let mut try_flac_reader = claxon::FlacReader::new(try_buf_reader).unwrap();

    // The streaminfo test will ensure that things like bit depth and
    // sample rate match, only the actual samples are compared here.
    let mut ref_samples = ref_wav_reader.samples::<i32>();

    let samples = try_flac_reader.streaminfo().samples.unwrap();
    let n_channels = try_flac_reader.streaminfo().channels;
    let mut blocks = try_flac_reader.blocks();
    let mut sample = 0u64;
    let mut b = 0u64;
    let mut buffer = Vec::new();

    while sample < samples {
        let block = blocks.read_next_or_eof(buffer).unwrap().unwrap();
        {
            let mut channels: Vec<_> = (0..n_channels)
                                           .map(|i| block.channel(i).iter().cloned())
                                           .collect();
            for i in 0..block.duration() {
                for ch in 0..n_channels as usize {
                    let ref_sample = ref_samples.next().map(|r| r.ok().unwrap());
                    let try_sample = channels[ch].next();
                    if ref_sample != try_sample {
                        println!("disagreement at sample {} of block {} in channel {}: \
                                  reference is {} but decoded is {}",
                                 i,
                                 b,
                                 ch,
                                 ref_sample.unwrap(),
                                 try_sample.unwrap());
                        panic!("decoding differs from reference decoder");
                    }
                }
            }
            sample = sample + block.duration() as u64;
        }
        b = b + 1;
        buffer = block.into_buffer();
    }
}

// Hard-coded tests for the test samples added py populate.sh.
// This allows us to run these tests in parallel and follow progress without
// enabling --nocapture.

#[test]
fn verify_streaminfo_p0() {
    compare_metaflac_streaminfo("testsamples/p0.flac");
}

#[test]
fn verify_streaminfo_p1() {
    compare_metaflac_streaminfo("testsamples/p1.flac");
}

#[test]
fn verify_streaminfo_p2() {
    compare_metaflac_streaminfo("testsamples/p2.flac");
}

#[test]
fn verify_streaminfo_p3() {
    compare_metaflac_streaminfo("testsamples/p3.flac");
}

#[test]
fn verify_streaminfo_p4() {
    compare_metaflac_streaminfo("testsamples/p4.flac");
}

#[test]
fn verify_streaminfo_pop() {
    compare_metaflac_streaminfo("testsamples/pop.flac");
}

#[test]
fn verify_streaminfo_short() {
    compare_metaflac_streaminfo("testsamples/short.flac");
}

#[test]
fn verify_streaminfo_wasted_bits() {
    compare_metaflac_streaminfo("testsamples/wasted_bits.flac");
}

#[test]
fn verify_vorbis_comment_p0() {
    compare_metaflac_vorbis_comment("testsamples/p0.flac");
}

#[test]
fn verify_vorbis_comment_p1() {
    compare_metaflac_vorbis_comment("testsamples/p1.flac");
}

#[test]
fn verify_vorbis_comment_p2() {
    compare_metaflac_vorbis_comment("testsamples/p2.flac");
}

#[test]
fn verify_vorbis_comment_p3() {
    compare_metaflac_vorbis_comment("testsamples/p3.flac");
}

#[test]
fn verify_vorbis_comment_p4() {
    compare_metaflac_vorbis_comment("testsamples/p4.flac");
}

#[test]
fn verify_decoded_stream_p0() {
    compare_decoded_stream("testsamples/p0.flac");
}

#[test]
fn verify_decoded_stream_p1() {
    compare_decoded_stream("testsamples/p1.flac");
}

#[test]
fn verify_decoded_stream_p2() {
    compare_decoded_stream("testsamples/p2.flac");
}

#[test]
fn verify_decoded_stream_p3() {
    compare_decoded_stream("testsamples/p3.flac");
}

#[test]
fn verify_decoded_stream_p4() {
    compare_decoded_stream("testsamples/p4.flac");
}

#[test]
fn verify_decoded_stream_pop() {
    compare_decoded_stream("testsamples/pop.flac");
}

#[test]
fn verify_decoded_stream_short() {
    // The short sample has only 4 samples, even less than pop.flac.
    compare_decoded_stream("testsamples/short.flac");
}

#[test]
fn verify_decoded_stream_wasted_bits() {
    // This sample has subframes where the number of wasted bits is not 0.
    compare_decoded_stream("testsamples/wasted_bits.flac");
}

#[test]
fn verify_limits_on_vendor_string() {
    // This file claims to have a vendor string which would not fit in the
    // block.
    let file = fs::File::open("testsamples/large_vendor_string.flac").unwrap();
    match claxon::FlacReader::new(file) {
        Ok(..) => panic!("This file should fail to load"),
        Err(err) => {
            assert_eq!(err, claxon::Error::FormatError("vendor string too long"))
        }
    }
}

#[test]
fn verify_limits_on_vorbis_comment_block() {
    // This file claims to have a very large Vorbis comment block, which could
    // make the decoder go OOM.
    let file = fs::File::open("testsamples/large_vorbis_comment_block.flac").unwrap();
    match claxon::FlacReader::new(file) {
        Ok(..) => panic!("This file should fail to load"),
        Err(claxon::Error::Unsupported(..)) => { }
        Err(..) => panic!("Expected 'Unsupported' error."),
    }
}

#[test]
fn verify_extra_samples() {
    use std::ffi::OsStr;

    if !Path::new("testsamples/extra").exists() {
        return
    }

    let wd = walkdir::WalkDir::new("testsamples/extra")
        .follow_links(true)
        .into_iter()
        .filter_map(|e| e.ok());

    // Recursively enumerate all the flac files in the testsamples/extra
    // directory, and compare the streaminfo and stream itself for those.
    for entry in wd {
        let path = entry.path();
        if path.is_file() && path.extension() == Some(OsStr::new("flac")) {
            print!("    comparing {} ...", path.to_str()
                                               .expect("unsupported filename"));
            compare_metaflac_streaminfo(&path);
            compare_metaflac_vorbis_comment(&path);
            compare_decoded_stream(&path);
            println!(" ok");
        }
    }
}

#[test]
fn regression_test_fuzz_samples() {
    use std::ffi::OsStr;

    // Enumerate all the flac files in the testsamples/fuzz directory,
    // and ensure that they can be decoded without panic.
    let dir = fs::read_dir("testsamples/fuzz")
                 .ok().expect("failed to enumerate flac files");
    for path in dir {
        let path = path.ok().expect("failed to obtain path info").path();
        if path.is_file() && path.extension() == Some(OsStr::new("flac")) {
            print!("    regression testing {} ...", path.to_str()
                   .expect("unsupported filename"));

            if let Ok(mut reader) = claxon::FlacReader::open(&path) {
                let mut buffer = Vec::new();
                while let Ok(Some(block)) = reader.blocks().read_next_or_eof(buffer) {
                    buffer = block.into_buffer();
                }
            }
            println!(" ok");
        }
    }
}
<commit_msg>Deal with idiosyncrasies in metaflac output<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2014 Ruud van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

extern crate claxon;
extern crate hound;
extern crate walkdir;

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

fn run_metaflac_streaminfo<P: AsRef<Path>>(fname: P) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all streaminfo data.
    let output = Command::new("metaflac")
        .arg("--show-min-blocksize")
        .arg("--show-max-blocksize")
        .arg("--show-min-framesize")
        .arg("--show-max-framesize")
        .arg("--show-sample-rate")
        .arg("--show-channels")
        .arg("--show-bps")
        .arg("--show-total-samples")
        .arg("--show-md5sum")
        .arg(fname.as_ref().to_str().expect("unsupported filename"))
        .output()
        .expect("failed to run metaflac");
    String::from_utf8(output.stdout).expect("metaflac wrote invalid UTF-8")
}

fn run_metaflac_vorbis_comment<P: AsRef<Path>>(fname: P) -> String {
    use std::process::Command;

    // Run metaflac on the specified file and print all Vorbis comment data.
    let output = Command::new("metaflac")
        .arg("--block-type=VORBIS_COMMENT")
        .arg("--list")
        .arg(fname.as_ref().to_str().expect("unsupported filename"))
        .output()
        .expect("failed to run metaflac");
    String::from_utf8(output.stdout).expect("metaflac wrote invalid UTF-8")
}

fn decode_file<P: AsRef<Path>>(fname: P) -> Vec<u8> {
    use std::process::Command;

    // Run the the reference flac decoder on the file.
    let output = Command::new("flac")
        .arg("--decode")
        .arg("--silent")
        .arg("--stdout")
        .arg(fname.as_ref().to_str().expect("unsupported filename"))
        .output()
        .expect("failed to run flac");

    assert!(output.status.success());
    output.stdout
}

fn print_hex(seq: &[u8]) -> String {
    let vec: Vec<String> = seq.iter().map(|x| format!("{:0>2x}", *x)).collect();
    vec.concat()
}

fn read_streaminfo<P: AsRef<Path>>(fname: P) -> String {
    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let reader = io::BufReader::new(file);
    let stream = claxon::FlacReader::new(reader).unwrap();
    let streaminfo = stream.streaminfo();

    // Format the streaminfo in the same way that metaflac prints it.
    format!("{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n",
            streaminfo.min_block_size,
            streaminfo.max_block_size,
            streaminfo.min_frame_size.unwrap_or(0),
            streaminfo.max_frame_size.unwrap_or(0),
            streaminfo.sample_rate,
            streaminfo.channels,
            streaminfo.bits_per_sample,
            streaminfo.samples.unwrap_or(0),
            print_hex(&streaminfo.md5sum)) // TODO implement LowerHex for &[u8] and submit a PR.
}

fn compare_metaflac_streaminfo<P: AsRef<Path>>(fname: P) {
    let metaflac = run_metaflac_streaminfo(&fname);
    let streaminfo = read_streaminfo(&fname);
    let mut mf_lines = metaflac.lines();
    let mut si_lines = streaminfo.lines();
    while let (Some(mf), Some(si)) = (mf_lines.next(), si_lines.next()) {
        if mf != si {
            println!("metaflac\n--------\n{}", metaflac);
            println!("streaminfo\n----------\n{}", streaminfo);
            panic!("metaflac disagrees on parsed streaminfo");
        }
    }
}

fn compare_metaflac_vorbis_comment<P: AsRef<Path>>(fname: P) {
    let metaflac = run_metaflac_vorbis_comment(&fname);

    // Use a buffered reader, this speeds up the test by 120%.
    let file = fs::File::open(fname).unwrap();
    let buf_reader = io::BufReader::new(file);
    let reader = claxon::FlacReader::new(buf_reader).unwrap();

    let mut mf_lines = metaflac.lines();

    // Search for the vendor string in the metaflac output.
    while let Some(line) = mf_lines.next() {
        let prefix = "  vendor string: ";
        if line.starts_with(prefix) {
            let mf_vendor_string = &line[prefix.len()..];

            // If the vendor string starts with a null byte, metaflac will not
            // print it -- my guess is because metaflac is written in C and uses
            // C-style string manipulation. In that case we skip it.
            match reader.vendor() {
                Some(x) if x.starts_with('\0') => break,
                _ => {}
            }

            assert_eq!(reader.vendor(), Some(mf_vendor_string));
            break
        }
    }

    let mut tags = reader.tags().iter();

    // Loop through all of the comments.
    while let Some(line) = mf_lines.next() {
        let prefix = "    comment[";
        if line.starts_with(prefix) {
            let mf_line = &line[prefix.len()..];
            let prefix_sep_index = mf_line.find(' ').unwrap();
            let mf_pair = &mf_line[prefix_sep_index + 1..];

            let sep_index = mf_pair.find('=').unwrap();
            let mf_name = &mf_pair[..sep_index];
            let mf_value = &mf_pair[sep_index + 1..];

            let &(ref name, ref value_lines) = tags.next().unwrap();
            let mut value_lines_iter = value_lines.lines();
            let value = value_lines_iter.next().unwrap();

            assert_eq!(name, mf_name);
            assert_eq!(value, mf_value);

            // If there are newlines, then we also need to read those as
            // separate lines from the metaflac untput. This does assume that
            // the newline count that Claxon read is correct, and because of the
            // behavior of the `.lines()` iterator this does not accurately
            // verify carriage returns, but we could not anyway, because
            // metaflac does not escape them.
            while let Some(actual_line) = value_lines_iter.next() {
                assert_eq!(actual_line, mf_lines.next().unwrap());
            }
        }
    }
}

fn compare_decoded_stream<P: AsRef<Path>>(fname: P) {
    let wav = decode_file(&fname);
    let cursor = io::Cursor::new(wav);

    // Compare the reference decoded by the 'flac' program (stored as wav, which
    // we read with Hound) to how Claxon decodes it, sample by sample.
    let mut ref_wav_reader = hound::WavReader::new(cursor).unwrap();

    let try_file = fs::File::open(fname).unwrap();
    let try_buf_reader = io::BufReader::new(try_file);
    let mut try_flac_reader = claxon::FlacReader::new(try_buf_reader).unwrap();

    // The streaminfo test will ensure that things like bit depth and
    // sample rate match, only the actual samples are compared here.
    let mut ref_samples = ref_wav_reader.samples::<i32>();

    let samples = try_flac_reader.streaminfo().samples.unwrap();
    let n_channels = try_flac_reader.streaminfo().channels;
    let mut blocks = try_flac_reader.blocks();
    let mut sample = 0u64;
    let mut b = 0u64;
    let mut buffer = Vec::new();

    while sample < samples {
        let block = blocks.read_next_or_eof(buffer).unwrap().unwrap();
        {
            let mut channels: Vec<_> = (0..n_channels)
                                           .map(|i| block.channel(i).iter().cloned())
                                           .collect();
            for i in 0..block.duration() {
                for ch in 0..n_channels as usize {
                    let ref_sample = ref_samples.next().map(|r| r.ok().unwrap());
                    let try_sample = channels[ch].next();
                    if ref_sample != try_sample {
                        println!("disagreement at sample {} of block {} in channel {}: \
                                  reference is {} but decoded is {}",
                                 i,
                                 b,
                                 ch,
                                 ref_sample.unwrap(),
                                 try_sample.unwrap());
                        panic!("decoding differs from reference decoder");
                    }
                }
            }
            sample = sample + block.duration() as u64;
        }
        b = b + 1;
        buffer = block.into_buffer();
    }
}

// Hard-coded tests for the test samples added py populate.sh.
// This allows us to run these tests in parallel and follow progress without
// enabling --nocapture.

#[test]
fn verify_streaminfo_p0() {
    compare_metaflac_streaminfo("testsamples/p0.flac");
}

#[test]
fn verify_streaminfo_p1() {
    compare_metaflac_streaminfo("testsamples/p1.flac");
}

#[test]
fn verify_streaminfo_p2() {
    compare_metaflac_streaminfo("testsamples/p2.flac");
}

#[test]
fn verify_streaminfo_p3() {
    compare_metaflac_streaminfo("testsamples/p3.flac");
}

#[test]
fn verify_streaminfo_p4() {
    compare_metaflac_streaminfo("testsamples/p4.flac");
}

#[test]
fn verify_streaminfo_pop() {
    compare_metaflac_streaminfo("testsamples/pop.flac");
}

#[test]
fn verify_streaminfo_short() {
    compare_metaflac_streaminfo("testsamples/short.flac");
}

#[test]
fn verify_streaminfo_wasted_bits() {
    compare_metaflac_streaminfo("testsamples/wasted_bits.flac");
}

#[test]
fn verify_vorbis_comment_p0() {
    compare_metaflac_vorbis_comment("testsamples/p0.flac");
}

#[test]
fn verify_vorbis_comment_p1() {
    compare_metaflac_vorbis_comment("testsamples/p1.flac");
}

#[test]
fn verify_vorbis_comment_p2() {
    compare_metaflac_vorbis_comment("testsamples/p2.flac");
}

#[test]
fn verify_vorbis_comment_p3() {
    compare_metaflac_vorbis_comment("testsamples/p3.flac");
}

#[test]
fn verify_vorbis_comment_p4() {
    compare_metaflac_vorbis_comment("testsamples/p4.flac");
}

#[test]
fn verify_decoded_stream_p0() {
    compare_decoded_stream("testsamples/p0.flac");
}

#[test]
fn verify_decoded_stream_p1() {
    compare_decoded_stream("testsamples/p1.flac");
}

#[test]
fn verify_decoded_stream_p2() {
    compare_decoded_stream("testsamples/p2.flac");
}

#[test]
fn verify_decoded_stream_p3() {
    compare_decoded_stream("testsamples/p3.flac");
}

#[test]
fn verify_decoded_stream_p4() {
    compare_decoded_stream("testsamples/p4.flac");
}

#[test]
fn verify_decoded_stream_pop() {
    compare_decoded_stream("testsamples/pop.flac");
}

#[test]
fn verify_decoded_stream_short() {
    // The short sample has only 4 samples, even less than pop.flac.
    compare_decoded_stream("testsamples/short.flac");
}

#[test]
fn verify_decoded_stream_wasted_bits() {
    // This sample has subframes where the number of wasted bits is not 0.
    compare_decoded_stream("testsamples/wasted_bits.flac");
}

#[test]
fn verify_limits_on_vendor_string() {
    // This file claims to have a vendor string which would not fit in the
    // block.
    let file = fs::File::open("testsamples/large_vendor_string.flac").unwrap();
    match claxon::FlacReader::new(file) {
        Ok(..) => panic!("This file should fail to load"),
        Err(err) => {
            assert_eq!(err, claxon::Error::FormatError("vendor string too long"))
        }
    }
}

#[test]
fn verify_limits_on_vorbis_comment_block() {
    // This file claims to have a very large Vorbis comment block, which could
    // make the decoder go OOM.
    let file = fs::File::open("testsamples/large_vorbis_comment_block.flac").unwrap();
    match claxon::FlacReader::new(file) {
        Ok(..) => panic!("This file should fail to load"),
        Err(claxon::Error::Unsupported(..)) => { }
        Err(..) => panic!("Expected 'Unsupported' error."),
    }
}

#[test]
fn verify_extra_samples() {
    use std::ffi::OsStr;

    if !Path::new("testsamples/extra").exists() {
        return
    }

    let wd = walkdir::WalkDir::new("testsamples/extra")
        .follow_links(true)
        .into_iter()
        .filter_map(|e| e.ok());

    // Recursively enumerate all the flac files in the testsamples/extra
    // directory, and compare the streaminfo and stream itself for those.
    for entry in wd {
        let path = entry.path();
        if path.is_file() && path.extension() == Some(OsStr::new("flac")) {
            print!("    comparing {} ...", path.to_str()
                                               .expect("unsupported filename"));
            compare_metaflac_streaminfo(&path);
            compare_metaflac_vorbis_comment(&path);
            compare_decoded_stream(&path);
            println!(" ok");
        }
    }
}

#[test]
fn regression_test_fuzz_samples() {
    use std::ffi::OsStr;

    // Enumerate all the flac files in the testsamples/fuzz directory,
    // and ensure that they can be decoded without panic.
    let dir = fs::read_dir("testsamples/fuzz")
                 .ok().expect("failed to enumerate flac files");
    for path in dir {
        let path = path.ok().expect("failed to obtain path info").path();
        if path.is_file() && path.extension() == Some(OsStr::new("flac")) {
            print!("    regression testing {} ...", path.to_str()
                   .expect("unsupported filename"));

            if let Ok(mut reader) = claxon::FlacReader::open(&path) {
                let mut buffer = Vec::new();
                while let Ok(Some(block)) = reader.blocks().read_next_or_eof(buffer) {
                    buffer = block.into_buffer();
                }
            }
            println!(" ok");
        }
    }
}
<|endoftext|>


<commit_before>#![feature(libc)]

extern crate libc;

#[macro_use]
extern crate apache2;

use apache2::{Request, Status};

apache2_module!(coming_soon_module, coming_soon_handler, b"mod_coming_soon\0");

fn coming_soon_handler(r: &Request) -> Status {
   if r.handler().unwrap() != "coming_soon" || r.uri().unwrap() != "/" {
      return Status::DECLINED
   }

   r.set_content_type("text/html");

   r.write(
      "<!doctype html>

         <meta charset=\"utf-8\">
         <title>Coming Soon...</title>

Coming Soon...

      "
   );

   Status::OK
}
<commit_msg>Renaming the coming soon handler name.<commit_after>#![feature(libc)]

extern crate libc;

#[macro_use]
extern crate apache2;

use apache2::{Request, Status};

apache2_module!(coming_soon_module, coming_soon_handler, b"mod_coming_soon\0");

fn coming_soon_handler(r: &Request) -> Status {
   if r.handler().unwrap() != "coming-soon" || r.uri().unwrap() != "/" {
      return Status::DECLINED
   }

   r.set_content_type("text/html");

   r.write(
      "<!doctype html>

         <meta charset=\"utf-8\">
         <title>Coming Soon...</title>

Coming Soon...

      "
   );

   Status::OK
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::collections::HashMap;

pub fn single_night_1(file: &str) -> i64 {
    let graph = generate_graph(file);
    (0..graph.nodes.len()).map(|i| salesman(&graph, i))
        .inspect(|distance| println!("{}", distance))
        .min().unwrap()
}

pub fn single_night_2(file: &str) -> i64 {
    let graph = generate_graph(file);
    (0..graph.nodes.len()).map(|i| salesman(&graph, i))
        .inspect(|distance| println!("{}", distance))
        .max().unwrap()
}

fn generate_graph(file: &str) -> Graph {
    let input = File::open(file).expect("File open fail.");
    let reader = BufReader::new(input);

    let mut nodes = Vec::new();
    let edge_cmds = reader.lines()
        .filter_map(Result::ok)
        .map(|line| {
            let words = line.split_whitespace().collect::<Vec<&str>>();
            let from = words[0].to_owned();
            let to = words[2].to_owned();
            let distance = words[4].parse::<i64>().expect("parse error");

            nodes.push(from.clone());
            nodes.push(to.clone());
            (from, to, distance)
        })
        .collect::<Vec<(String, String, i64)>>();
//    println!("{:?}", edge_cmds);
    nodes.sort();
    nodes.dedup();
    println!("{:?}", nodes);

    let mut edge_lengths = HashMap::new();
    let mut edges = HashMap::new();
    for &(ref from, ref to, ref distance) in edge_cmds.iter() {
        if let Ok(from_idx) = nodes.binary_search(&&from) {
            if let Ok(to_idx) = nodes.binary_search(&&to) {
//                println!("{} <-> {}", from_idx, to_idx);
                {
                    edge_lengths.insert((from_idx, to_idx), *distance);
                    let mut neighbors = edges.entry(from_idx).or_insert(Vec::new());
                    neighbors.push(to_idx);
                }
                {
                    // bi-directional
                    edge_lengths.insert((to_idx, from_idx), *distance);
                    let mut neighbors = edges.entry(to_idx).or_insert(Vec::new());
                    neighbors.push(from_idx);
                }
            }
        }
    }
    println!("{:?}", edges);
    println!("{:?}", edge_lengths);
    Graph { nodes: nodes, edges: edges, edge_lengths: edge_lengths }
}

fn salesman(graph: &Graph, source: usize) -> i64 {
    let node_idxs = graph.nodes.iter()
        .enumerate()
        .map(|(i, _)| i)
    .collect::<Vec<usize>>();

    let mut visited = vec![false; graph.nodes.len()];
    let mut curr = source;
    visited[curr] = true;
    println!("visit: {:?}", graph.nodes[source]);
    let mut sum = 0;

    loop {
        if visited.iter().all(|&b| b) {
            break;
        }
        let node_idx = node_idxs[curr];
        if let Some(neighbors) = graph.edges.get(&node_idx) {
            if let Some((min_idx, &length))
                = neighbors.iter()
                    .filter(|&&n| !visited[n])
                    .map(|&neighbor| {
                        let edge_key = (node_idx, neighbor);
                        let length = graph.edge_lengths.get(&edge_key).unwrap();
                        (neighbor, length)
                    })
            .min_by_key(|&(_, &length)| length)
            {
                println!("visit: {:?}", graph.nodes[min_idx]);
                visited[min_idx] = true;
                curr = min_idx;
                sum += length;
            }
        }
    }
    sum
}

#[derive(Debug)]
struct Edge {
    from: usize,
    to: usize,
    length: i64,
}

struct Graph {
    nodes: Vec<String>,
    edges: HashMap<usize, Vec<usize>>,
    edge_lengths: HashMap<(usize, usize), i64>,
}
<commit_msg>Add solution day 9 2015 part 2.<commit_after>use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::collections::HashMap;

pub fn single_night_1(file: &str) -> i64 {
    let graph = generate_graph(file);
    (0..graph.nodes.len()).map(|i| salesman(&graph, i, true))
        .inspect(|distance| println!("{}", distance))
        .min().unwrap()
}

pub fn single_night_2(file: &str) -> i64 {
    let graph = generate_graph(file);
    (0..graph.nodes.len()).map(|i| salesman(&graph, i, false))
        .inspect(|distance| println!("{}", distance))
        .max().unwrap()
}

fn generate_graph(file: &str) -> Graph {
    let input = File::open(file).expect("File open fail.");
    let reader = BufReader::new(input);

    let mut nodes = Vec::new();
    let edge_cmds = reader.lines()
        .filter_map(Result::ok)
        .map(|line| {
            let words = line.split_whitespace().collect::<Vec<&str>>();
            let from = words[0].to_owned();
            let to = words[2].to_owned();
            let distance = words[4].parse::<i64>().expect("parse error");

            nodes.push(from.clone());
            nodes.push(to.clone());
            (from, to, distance)
        })
        .collect::<Vec<(String, String, i64)>>();
//    println!("{:?}", edge_cmds);
    nodes.sort();
    nodes.dedup();
    println!("nodes: {:?}", nodes);

    let mut edge_lengths = HashMap::new();
    let mut edges = HashMap::new();
    for &(ref from, ref to, ref distance) in edge_cmds.iter() {
        if let Ok(from_idx) = nodes.binary_search(&&from) {
            if let Ok(to_idx) = nodes.binary_search(&&to) {
//                println!("{} <-> {}", from_idx, to_idx);
                {
                    edge_lengths.insert((from_idx, to_idx), *distance);
                    let mut neighbors = edges.entry(from_idx).or_insert(Vec::new());
                    neighbors.push(to_idx);
                }
                {
                    // bi-directional
                    edge_lengths.insert((to_idx, from_idx), *distance);
                    let mut neighbors = edges.entry(to_idx).or_insert(Vec::new());
                    neighbors.push(from_idx);
                }
            }
        }
    }
    println!("edges: {:?}", edges);
    println!("edge lengths: {:?}", edge_lengths);
    Graph { nodes: nodes, edges: edges, edge_lengths: edge_lengths }
}

fn salesman(graph: &Graph, source: usize, min: bool) -> i64 {
    let node_idxs = graph.nodes.iter()
        .enumerate()
        .map(|(i, _)| i)
    .collect::<Vec<usize>>();

    let mut visited = vec![false; graph.nodes.len()];
    let mut curr = source;
    visited[curr] = true;
    println!("visit: {:?}", graph.nodes[source]);
    let mut sum = 0;

    loop {
        if visited.iter().all(|&b| b) {
            break;
        }
        let node_idx = node_idxs[curr];
        if let Some(neighbors) = graph.edges.get(&node_idx) {
            if min {
                if let Some((min_idx, &length)) = neighbors.iter()
                    .filter(|&&n| !visited[n])
                    .map(|&neighbor| {
                        let edge_key = (node_idx, neighbor);
                        let length = graph.edge_lengths.get(&edge_key).unwrap();
                        (neighbor, length)
                    })
                    .inspect(|n| println!("{:?}", n))
                    .min_by_key(|&(_, &length)| length) {
                    println!("visit: {:?}", graph.nodes[min_idx]);
                    visited[min_idx] = true;
                    curr = min_idx;
                    sum += length;
                }
            } else {
                if let Some((max_idx, &length)) = neighbors.iter()
                    .filter(|&&n| !visited[n])
                        .map(|&neighbor| {
                            let edge_key = (node_idx, neighbor);
                            let length = graph.edge_lengths.get(&edge_key).unwrap();
                            (neighbor, length)
                        })
                .inspect(|n| println!("{:?}", n))
                    .max_by_key(|&(_, &length)| length) {
                        println!("visit: {:?}", graph.nodes[max_idx]);
                        visited[max_idx] = true;
                        curr = max_idx;
                        sum += length;
                    }
            }
        }
    }
    sum
}

#[derive(Debug)]
struct Edge {
    from: usize,
    to: usize,
    length: i64,
}

struct Graph {
    nodes: Vec<String>,
    edges: HashMap<usize, Vec<usize>>,
    edge_lengths: HashMap<(usize, usize), i64>,
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate extra;

use std::env;
use std::fs;
use std::io::stderr;
use extra::option::OptionalExt;

fn main() {
    let mut stderr = stderr();
    let ref src = env::args().nth(1).fail("no source argument.", &mut stderr);
    let ref dst = env::args().nth(2).fail("no destination argument.", &mut stderr);

    fs::rename(src, dst).try(&mut stderr);
}
<commit_msg>Add manual page to mv, -h and --help options<commit_after>#![deny(warnings)]

extern crate extra;

use std::env;
use std::fs;
use std::io::{stderr, stdout, Write};
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{mv} */ r#"
NAME
    mv - move files

SYNOPSIS
    mv [ -h | --help ] SOURCE_FILE DESTINATION_FILE

DESCRIPTION
    The mv utility renames the file named by the SOURCE_FILE operand to the destination path named by the DESTINATION_FILE operand.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();

    if env::args().count() == 2 {
        if let Some(arg) = env::args().nth(1) {
            if arg == "--help" || arg == "-h" {
                stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
                stdout.flush().try(&mut stderr);
                return;
            }
        }
    }

    let ref src = env::args().nth(1).fail("No source argument. Use --help to see the usage.", &mut stderr);
    let ref dst = env::args().nth(2).fail("No destination argument. Use --help to see the usage.", &mut stderr);

    fs::rename(src, dst).try(&mut stderr);
}
<|endoftext|>