<commit_before>use cocoa::base::{id, nil};
use cocoa::foundation::NSString;
use sys::{MTLCreateSystemDefaultDevice, MTLDevice};
use std::borrow::Cow;
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::ffi::CStr;

pub struct Device(id);

impl Device {
    pub fn system_default_device() -> Result<Self, DeviceError> {
        let device = unsafe { MTLCreateSystemDefaultDevice() };
        if device != nil {
            Ok(Device(device))
        } else {
            Err(DeviceError::ConstructionFailed)
        }
    }

    pub fn is_headless(&self) -> bool {
        unsafe { self.0.headless() != 0 }
    }

    pub fn is_low_power(&self) -> bool {
        unsafe { self.0.lowPower() != 0 }
    }

    /// BEWARE: using this fn causes the process to exit abnormally.
    pub fn name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()) }.to_string_lossy()
    }
}

#[derive(Clone, Debug)]
pub enum DeviceError {
    ConstructionFailed
}

impl Display for DeviceError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let descr = match *self {
            DeviceError::ConstructionFailed => "DeviceError::ConstructionFailed"
        };
        write!(f, "{}", descr)
    }
}

impl Error for DeviceError {
    fn description(&self) -> &str {
        match *self {
            DeviceError::ConstructionFailed =>
                "Could not create a default device. Please ensure that you are using at least OSX 10.11 or iOS 8.0"
        }
    }
}
<commit_msg>Remove BEWARE comment because it is no longer relevant (bug fixed)<commit_after>use cocoa::base::{id, nil};
use cocoa::foundation::NSString;
use sys::{MTLCreateSystemDefaultDevice, MTLDevice};
use std::borrow::Cow;
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::ffi::CStr;

pub struct Device(id);

impl Device {
    pub fn system_default_device() -> Result<Self, DeviceError> {
        let device = unsafe { MTLCreateSystemDefaultDevice() };
        if device != nil {
            Ok(Device(device))
        } else {
            Err(DeviceError::ConstructionFailed)
        }
    }

    pub fn is_headless(&self) -> bool {
        unsafe { self.0.headless() != 0 }
    }

    pub fn is_low_power(&self) -> bool {
        unsafe { self.0.lowPower() != 0 }
    }

    pub fn name(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(self.0.name().UTF8String()) }.to_string_lossy()
    }
}

#[derive(Clone, Debug)]
pub enum DeviceError {
    ConstructionFailed
}

impl Display for DeviceError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let descr = match *self {
            DeviceError::ConstructionFailed => "DeviceError::ConstructionFailed"
        };
        write!(f, "{}", descr)
    }
}

impl Error for DeviceError {
    fn description(&self) -> &str {
        match *self {
            DeviceError::ConstructionFailed =>
                "Could not create a default device. Please ensure that you are using at least OSX 10.11 or iOS 8.0"
        }
    }
}
<|endoftext|>


<commit_before>extern crate klee;

#[test]
fn basic_test() {
  let mut a : i32;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let mut a : i32 = 0;
  let mut b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      klee::warning("this path is reachable");
    }
  }
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    klee::assert_warn(b == 0, "this assertion should not trigger");

    if b == 12 {
      klee::warning("This path should be unreachable");
    }

    klee::assert_warn(b == 101, "this assertion should trigger");
    klee::assert_warn(b == 150000, "this assersion should not trigger");
  }
}
<commit_msg>Update simple.rs<commit_after>extern crate klee;

#[test]
fn basic_test() {
  let mut a : i32 = 0;
  klee::symbol(&a, "a");
  assert_eq!(a, 56);
}

#[test]
fn other_test() {
  let mut a : i32 = 0;
  let mut b : i32 = 0;

  klee::symbol(&a, "a");
  klee::symbol(&b, "b");

  if a == 50 {
    if b == 49 {
      klee::warning("this path is reachable");
    }
  }
}

#[test]
fn another_test() {
  let a = klee::i32("a");
  if a > 60 && a < 90 {
    let b = a + 40;
    klee::assert_warn(b == 0, "this assertion should not trigger");

    if b == 12 {
      klee::warning("This path should be unreachable");
    }

    klee::assert_warn(b == 101, "this assertion should trigger");
    klee::assert_warn(b == 150000, "this assersion should not trigger");
  }
}
<|endoftext|>


<commit_before>#![feature(convert)]

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate yak_client;

mod common;
use common::*;

#[test]
fn test_put_read_empty() {
  env_logger::init().unwrap_or(());

  let (mut head, mut tail) = open_client("test_put_read_empty");
  let key = "key";

  head.truncate().unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 0);
}

#[test]
fn test_put_read_single_value() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_put_read_single_value");
  let key = "key";
  let val = "value";

  head.truncate().unwrap();

  head.write(key.as_bytes(), val.as_bytes()).unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 1);
  assert_eq!(resp[0].content, val.as_bytes())
}

#[test]
fn test_put_read_two_values() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_put_read_two_values");
  let key = "key";
  let vals = vec!["a".as_bytes(), "b".as_bytes()];

  head.truncate().unwrap();

  for val in &vals {
    head.write(key.as_bytes(), &val).unwrap();
  }

  let resp = tail.read(key.as_bytes()).unwrap();
  let returned : Vec<Vec<u8>> = resp.iter().map(|v| v.content.clone()).collect();
  assert_eq!(returned, vals);
}

#[test]
fn test_truncate() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_truncate");
  let key = "key";
  let val = "value";

  head.truncate().unwrap();
  head.write(key.as_bytes(), val.as_bytes()).unwrap();
  head.truncate().unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 0);
}

#[test]
fn test_subscribe_after_put_single_value() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_subscribe_after_put_single_value");
  let key = b"key";
  let val = b"value";
  head.truncate().unwrap();
  head.write(key, val).unwrap();

  let mut subscription = tail.subscribe().unwrap();
  let maybe_message = subscription.fetch_next().unwrap();

  assert_eq!(maybe_message.map(|message| (message.key, message.content)), Some((key.to_vec(), val.to_vec())))
}
<commit_msg>Add WIP test for async deliveries.<commit_after>#![feature(convert, scoped)]

#[macro_use]
extern crate log;
extern crate env_logger;
extern crate yak_client;

use std::thread;

mod common;
use common::*;

#[test]
fn test_put_read_empty() {
  env_logger::init().unwrap_or(());

  let (mut head, mut tail) = open_client("test_put_read_empty");
  let key = "key";

  head.truncate().unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 0);
}

#[test]
fn test_put_read_single_value() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_put_read_single_value");
  let key = "key";
  let val = "value";

  head.truncate().unwrap();

  head.write(key.as_bytes(), val.as_bytes()).unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 1);
  assert_eq!(resp[0].content, val.as_bytes())
}

#[test]
fn test_put_read_two_values() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_put_read_two_values");
  let key = "key";
  let vals = vec!["a".as_bytes(), "b".as_bytes()];

  head.truncate().unwrap();

  for val in &vals {
    head.write(key.as_bytes(), &val).unwrap();
  }

  let resp = tail.read(key.as_bytes()).unwrap();
  let returned : Vec<Vec<u8>> = resp.iter().map(|v| v.content.clone()).collect();
  assert_eq!(returned, vals);
}

#[test]
fn test_truncate() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_truncate");
  let key = "key";
  let val = "value";

  head.truncate().unwrap();
  head.write(key.as_bytes(), val.as_bytes()).unwrap();
  head.truncate().unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 0);
}

#[test]
fn test_subscribe_after_put_single_value() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_subscribe_after_put_single_value");
  let key = b"key";
  let val = b"value";
  head.truncate().unwrap();
  head.write(key, val).unwrap();

  let mut subscription = tail.subscribe().unwrap();
  let maybe_message = subscription.fetch_next().unwrap();

  assert_eq!(maybe_message.map(|message| (message.key, message.content)), Some((key.to_vec(), val.to_vec())))
}

#[test] #[should_panic]
fn test_subscribe_async_deliveries() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_subscribe_async_deliveries");
  let key = b"key";
  let val = b"value";
  head.truncate().unwrap();

  let sub_task = thread::scoped(move || {
    let mut subscription = tail.subscribe().unwrap();
    subscription.fetch_next().unwrap()
  });
  head.write(key, val).unwrap();

  let maybe_message = sub_task.join();

  assert_eq!(maybe_message.map(|message| (message.key, message.content)), Some((key.to_vec(), val.to_vec())))
}
<|endoftext|>


<commit_before>#![crate_name = "objc_test_utils"]
#![crate_type = "lib"]

#[allow(unstable)]
extern crate libc;

use libc::c_void;

#[link(name="block_utils", kind="static")]
extern {
    pub fn get_int_block() -> *mut c_void;
    pub fn get_int_block_with(i: i32) -> *mut c_void;
    pub fn get_add_block() -> *mut c_void;
    pub fn get_add_block_with(i: i32) -> *mut c_void;
    pub fn invoke_int_block(block: *mut c_void) -> i32;
    pub fn invoke_add_block(block: *mut c_void, a: i32) -> i32;
}
<commit_msg>Added documentation and tests for test_utils.<commit_after>#![crate_name = "objc_test_utils"]
#![crate_type = "lib"]

#![allow(unstable)]

#[link(name = "Foundation", kind = "framework")]
extern { }

/// A block that takes no arguments and returns an integer: `int32_t (^)()`.
#[allow(missing_copy_implementations)]
pub enum IntBlock { }

/// A block that takes one integer argument, adds to it, and returns the sum:
/// `int32_t (^)(int32_t)`.
#[allow(missing_copy_implementations)]
pub enum AddBlock { }

#[link(name="block_utils", kind="static")]
extern {
    /// Returns a pointer to a global `IntBlock` that returns 7.
    pub fn get_int_block() -> *mut IntBlock;
    /// Returns a pointer to a copied `IntBlock` that returns `i`.
    pub fn get_int_block_with(i: i32) -> *mut IntBlock;
    /// Returns a pointer to a global `AddBlock` that returns its argument + 7.
    pub fn get_add_block() -> *mut AddBlock;
    /// Returns a pointer to a copied `AddBlock` that returns its argument + `i`.
    pub fn get_add_block_with(i: i32) -> *mut AddBlock;
    /// Invokes an `IntBlock` and returns its result.
    pub fn invoke_int_block(block: *mut IntBlock) -> i32;
    /// Invokes an `AddBlock` with `a` and returns the result.
    pub fn invoke_add_block(block: *mut AddBlock, a: i32) -> i32;
}

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

    #[test]
    fn test_int_block() {
        unsafe {
            assert!(invoke_int_block(get_int_block()) == 7);
            assert!(invoke_int_block(get_int_block_with(13)) == 13);
        }
    }

    #[test]
    fn test_add_block() {
        unsafe {
            assert!(invoke_add_block(get_add_block(), 5) == 12);
            assert!(invoke_add_block(get_add_block_with(3), 5) == 8);
        }
    }
}
<|endoftext|>


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

#![feature(rustc_private, plugin_registrar)]

extern crate syntax;
extern crate rustc;

use syntax::ast::{MetaItem, Expr};
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, Annotatable};
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic::*;
use syntax::ext::deriving::generic::ty::*;
use syntax::parse::token;
use syntax::ptr::P;
use rustc::plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("derive_Rand"),
                                  base::MultiDecorator(Box::new(expand_deriving_rand)));
}

pub fn expand_deriving_rand(cx: &mut ExtCtxt,
                            span: Span,
                            mitem: &MetaItem,
                            item: &Annotatable,
                            push: &mut FnMut(Annotatable)) {
    let trait_def = TraitDef {
        span: span,
        attributes: Vec::new(),
        path: Path::new(vec!("rand", "Rand")),
        additional_bounds: Vec::new(),
        generics: LifetimeBounds::empty(),
        is_unsafe: false,
        methods: vec!(
            MethodDef {
                name: "rand",
                is_unsafe: false,
                generics: LifetimeBounds {
                    lifetimes: Vec::new(),
                    bounds: vec!(("R",
                                  vec!( Path::new(vec!("rand", "Rng")) )))
                },
                explicit_self: None,
                args: vec!(
                    Ptr(Box::new(Literal(Path::new_local("R"))),
                        Borrowed(None, ast::MutMutable))
                ),
                ret_ty: Self_,
                attributes: Vec::new(),
                combine_substructure: combine_substructure(Box::new(|a, b, c| {
                    rand_substructure(a, b, c)
                }))
            }
        ),
        associated_types: Vec::new(),
    };
    trait_def.expand(cx, mitem, &item, &mut |i| push(i))
}

fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
    let rng = if substr.nonself_args.len() == 1 {
        &substr.nonself_args[0]
    } else {
        cx.bug("Incorrect number of arguments to `rand` in `derive(Rand)`")
    };
    let rand_ident = vec!(
        cx.ident_of("rand"),
        cx.ident_of("Rand"),
        cx.ident_of("rand")
    );
    let rand_call = |cx: &mut ExtCtxt, span| {
        cx.expr_call_global(span,
                            rand_ident.clone(),
                            vec!(rng.clone()))
    };

    return match *substr.fields {
        StaticStruct(_, ref summary) => {
            let path = cx.path_ident(trait_span, substr.type_ident);
            rand_thing(cx, trait_span, path, summary, rand_call)
        }
        StaticEnum(_, ref variants) => {
            if variants.is_empty() {
                cx.span_err(trait_span, "`Rand` cannot be derived for enums with no variants");
                // let compilation continue
                return cx.expr_usize(trait_span, 0);
            }

            let variant_count = cx.expr_usize(trait_span, variants.len());

            let rand_name = cx.path_all(trait_span,
                                        true,
                                        rand_ident.clone(),
                                        Vec::new(),
                                        Vec::new(),
                                        Vec::new());
            let rand_name = cx.expr_path(rand_name);

            // ::rand::Rand::rand(rng)
            let rv_call = cx.expr_call(trait_span,
                                       rand_name,
                                       vec!(rng.clone()));

            // need to specify the usize-ness of the random number
            let usize_ty = cx.ty_ident(trait_span, cx.ident_of("usize"));
            let value_ident = cx.ident_of("__value");
            let let_statement = cx.stmt_let_typed(trait_span,
                                                  false,
                                                  value_ident,
                                                  usize_ty,
                                                  rv_call);

            // rand() % variants.len()
            let value_ref = cx.expr_ident(trait_span, value_ident);
            let rand_variant = cx.expr_binary(trait_span,
                                              ast::BiRem,
                                              value_ref,
                                              variant_count);

            let mut arms = variants.iter().enumerate().map(|(i, &(ident, v_span, ref summary))| {
                let i_expr = cx.expr_usize(v_span, i);
                let pat = cx.pat_lit(v_span, i_expr);

                let path = cx.path(v_span, vec![substr.type_ident, ident]);
                let thing = rand_thing(cx, v_span, path, summary, |cx, sp| rand_call(cx, sp));
                cx.arm(v_span, vec!( pat ), thing)
            }).collect::<Vec<ast::Arm> >();

            // _ => {} at the end. Should never occur
            arms.push(cx.arm_unreachable(trait_span));

            let match_expr = cx.expr_match(trait_span, rand_variant, arms);

            let block = cx.block(trait_span, vec!( let_statement ), Some(match_expr));
            cx.expr_block(block)
        }
        _ => cx.bug("Non-static method in `derive(Rand)`")
    };

    fn rand_thing<F>(cx: &mut ExtCtxt,
                     trait_span: Span,
                     ctor_path: ast::Path,
                     summary: &StaticFields,
                     mut rand_call: F)
                     -> P<Expr> where
        F: FnMut(&mut ExtCtxt, Span) -> P<Expr>,
    {
        let path = cx.expr_path(ctor_path.clone());
        match *summary {
            Unnamed(ref fields) => {
                if fields.is_empty() {
                    path
                } else {
                    let exprs = fields.iter().map(|span| rand_call(cx, *span)).collect();
                    cx.expr_call(trait_span, path, exprs)
                }
            }
            Named(ref fields) => {
                let rand_fields = fields.iter().map(|&(ident, span)| {
                    let e = rand_call(cx, span);
                    cx.field_imm(span, ident, e)
                }).collect();
                cx.expr_struct(trait_span, ctor_path, rand_fields)
            }
        }
    }
}
<commit_msg>Update rand_macros to use the rustc_plugin crate<commit_after>// Copyright 2012-2013 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.

#![feature(rustc_private, plugin_registrar)]

extern crate syntax;
extern crate rustc_plugin;

use syntax::ast::{MetaItem, Expr};
use syntax::ast;
use syntax::codemap::Span;
use syntax::ext::base;
use syntax::ext::base::{ExtCtxt, Annotatable};
use syntax::ext::build::AstBuilder;
use syntax::ext::deriving::generic::*;
use syntax::ext::deriving::generic::ty::*;
use syntax::parse::token;
use syntax::ptr::P;
use rustc_plugin::Registry;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("derive_Rand"),
                                  base::MultiDecorator(Box::new(expand_deriving_rand)));
}

pub fn expand_deriving_rand(cx: &mut ExtCtxt,
                            span: Span,
                            mitem: &MetaItem,
                            item: &Annotatable,
                            push: &mut FnMut(Annotatable)) {
    let trait_def = TraitDef {
        span: span,
        attributes: Vec::new(),
        path: Path::new(vec!("rand", "Rand")),
        additional_bounds: Vec::new(),
        generics: LifetimeBounds::empty(),
        is_unsafe: false,
        methods: vec!(
            MethodDef {
                name: "rand",
                is_unsafe: false,
                generics: LifetimeBounds {
                    lifetimes: Vec::new(),
                    bounds: vec!(("R",
                                  vec!( Path::new(vec!("rand", "Rng")) )))
                },
                explicit_self: None,
                args: vec!(
                    Ptr(Box::new(Literal(Path::new_local("R"))),
                        Borrowed(None, ast::MutMutable))
                ),
                ret_ty: Self_,
                attributes: Vec::new(),
                combine_substructure: combine_substructure(Box::new(|a, b, c| {
                    rand_substructure(a, b, c)
                }))
            }
        ),
        associated_types: Vec::new(),
    };
    trait_def.expand(cx, mitem, &item, &mut |i| push(i))
}

fn rand_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
    let rng = if substr.nonself_args.len() == 1 {
        &substr.nonself_args[0]
    } else {
        cx.bug("Incorrect number of arguments to `rand` in `derive(Rand)`")
    };
    let rand_ident = vec!(
        cx.ident_of("rand"),
        cx.ident_of("Rand"),
        cx.ident_of("rand")
    );
    let rand_call = |cx: &mut ExtCtxt, span| {
        cx.expr_call_global(span,
                            rand_ident.clone(),
                            vec!(rng.clone()))
    };

    return match *substr.fields {
        StaticStruct(_, ref summary) => {
            let path = cx.path_ident(trait_span, substr.type_ident);
            rand_thing(cx, trait_span, path, summary, rand_call)
        }
        StaticEnum(_, ref variants) => {
            if variants.is_empty() {
                cx.span_err(trait_span, "`Rand` cannot be derived for enums with no variants");
                // let compilation continue
                return cx.expr_usize(trait_span, 0);
            }

            let variant_count = cx.expr_usize(trait_span, variants.len());

            let rand_name = cx.path_all(trait_span,
                                        true,
                                        rand_ident.clone(),
                                        Vec::new(),
                                        Vec::new(),
                                        Vec::new());
            let rand_name = cx.expr_path(rand_name);

            // ::rand::Rand::rand(rng)
            let rv_call = cx.expr_call(trait_span,
                                       rand_name,
                                       vec!(rng.clone()));

            // need to specify the usize-ness of the random number
            let usize_ty = cx.ty_ident(trait_span, cx.ident_of("usize"));
            let value_ident = cx.ident_of("__value");
            let let_statement = cx.stmt_let_typed(trait_span,
                                                  false,
                                                  value_ident,
                                                  usize_ty,
                                                  rv_call);

            // rand() % variants.len()
            let value_ref = cx.expr_ident(trait_span, value_ident);
            let rand_variant = cx.expr_binary(trait_span,
                                              ast::BiRem,
                                              value_ref,
                                              variant_count);

            let mut arms = variants.iter().enumerate().map(|(i, &(ident, v_span, ref summary))| {
                let i_expr = cx.expr_usize(v_span, i);
                let pat = cx.pat_lit(v_span, i_expr);

                let path = cx.path(v_span, vec![substr.type_ident, ident]);
                let thing = rand_thing(cx, v_span, path, summary, |cx, sp| rand_call(cx, sp));
                cx.arm(v_span, vec!( pat ), thing)
            }).collect::<Vec<ast::Arm> >();

            // _ => {} at the end. Should never occur
            arms.push(cx.arm_unreachable(trait_span));

            let match_expr = cx.expr_match(trait_span, rand_variant, arms);

            let block = cx.block(trait_span, vec!( let_statement ), Some(match_expr));
            cx.expr_block(block)
        }
        _ => cx.bug("Non-static method in `derive(Rand)`")
    };

    fn rand_thing<F>(cx: &mut ExtCtxt,
                     trait_span: Span,
                     ctor_path: ast::Path,
                     summary: &StaticFields,
                     mut rand_call: F)
                     -> P<Expr> where
        F: FnMut(&mut ExtCtxt, Span) -> P<Expr>,
    {
        let path = cx.expr_path(ctor_path.clone());
        match *summary {
            Unnamed(ref fields) => {
                if fields.is_empty() {
                    path
                } else {
                    let exprs = fields.iter().map(|span| rand_call(cx, *span)).collect();
                    cx.expr_call(trait_span, path, exprs)
                }
            }
            Named(ref fields) => {
                let rand_fields = fields.iter().map(|&(ident, span)| {
                    let e = rand_call(cx, span);
                    cx.field_imm(span, ident, e)
                }).collect();
                cx.expr_struct(trait_span, ctor_path, rand_fields)
            }
        }
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
    let v = vec![1, 2, 3, 4, 5];   // v: Vec<i32>
    // Vectors store their contents as contiguous arrays of T on the heap.
    // This means, they must know the <T> size at compile time.

    // To get the index of a vector, using '[ ]'
    // And the indices count from 0.
    // For example as below:
    println!("The third element of v is {}", v[2]);

    // The index type must be usize, not i32
    let i: usize = 0;
    let j: i32 = 0;

    // Works
    v[i];

    // Do not Works
    // v[j];

    // Access an index that does not exist, the current thread will panic
    // println!("Item 7 is {}", v[6]);

    // Handle out-of-bounds error without panicking, using the method like get or get_mut
    // which will return 'None' when given an invaild index.

    let v_out = vec![1, 2, 3];
    match v.get(7) {
        Some(x) => println!("Item 7 is {}", x),
        None => println!("Sorry, this vector is too short")

    }

    // Iterating an vector through its element with for.
    // There is three version.
    let mut v_iterating = vec![1, 2, 3, 4, 5];

    for i in &v_iterating {
        println!("Version 1, A reference to {}", i);
    }

    for i in &mut v_iterating {
        println!("Version 2, A mutable reference to {}", i);
    }

    for i in v_iterating {
        println!("Version 3, Taking ownership of the vector and its elemment {}", i);
    }

}
<commit_msg>add vectors<commit_after>fn main() {
    println!("Hello, world!");
    let v = vec![1, 2, 3, 4, 5];   // v: Vec<i32>
    // Vectors store their contents as contiguous arrays of T on the heap.
    // This means, they must know the <T> size at compile time.

    // To get the index of a vector, using '[ ]'
    // And the indices count from 0.
    // For example as below:
    println!("The third element of v is {}", v[2]);

    // The index type must be usize, not i32
    let i: usize = 0;
    let j: i32 = 0;

    // Works
    v[i];

    // Do not Works
    // v[j];

    // Access an index that does not exist, the current thread will panic
    // println!("Item 7 is {}", v[6]);

    // Handle out-of-bounds error without panicking, using the method like get or get_mut
    // which will return 'None' when given an invaild index.

    let v_out = vec![1, 2, 3];
    match v.get(7) {
        Some(x) => println("Item 7 is {}", x),
        None => println!("Sorry, this vector is too short")

    }

    // Iterating an vector through its element with for.
    // There is three version.
    let mut v_iterating = vec![1, 2, 3, 4, 5];

    for i in &v_iterating {
        println!("Version 1, A reference to {}", i);
    }

    for i in &mut v_iterating {
        println!("Version 2, A mutable reference to {}", i);
    }

    for i in v_iterating {
        println!("Version 3, Taking ownership of the vector and its elemment {}", i);
    }

}
<|endoftext|>


<commit_before>//!
//! Tests `DFS`
//!

use crate::mock_graph::{MockGraph, MockVertex, arbitrary::{ArbVertexIn, ArbConnectedGraph}, MockEdgeWeight};
use graphene::core::{ImplGraph, Graph, Constrainer, AddVertex, AddEdge, Directed};
use graphene::algo::DFS;
use std::collections::{ HashSet, HashMap };
use crate::mock_graph::arbitrary::ArbVerticesIn;

duplicate_for_directedness!{
	$directedness

	///
	/// Tests that all vertices in a connected component are produced exactly once.
	///
	#[quickcheck]
	fn visits_component_once(ArbVertexIn(mock, v): ArbVertexIn<ArbConnectedGraph<directedness>>)
			 -> bool
	{
		// Use a set to ensure we only count each vertex once
		let mut visited = HashSet::new();
		let mut visited_once = true;
		DFS::new(mock.graph(), v).for_each(|v|{ visited_once &= visited.insert(v); });

		// We ensure all vertices were visited, but only once
		visited.len() == mock.0.all_vertices().count() && visited_once
	}

	///
	/// Tests that no vertices outside a connected component are produced
	///
	#[quickcheck]
	fn visits_none_outside_component(ArbVertexIn(g1, v): ArbVertexIn<ArbConnectedGraph<directedness>>,
		g2: MockGraph<directedness>)
		 -> bool
	{
		// Our starting connected component
		let mut graph = g1.0.unconstrain();

		// First join the two graphs
		let mut v_map = graph.join(&g2);

		// Ensure that no visited vertex comes from outside the start component
		DFS::new(&graph, v).all(|visit| v_map.values().all(|&new_v| visit != new_v))
	}
}

///
/// Tests for directed graphs, even if an edge targets a connected component from a different
/// component, only the first component's vertices are produced.
///
/// This is different from `visits_none_outside_component` because in that case the components
/// are completely unconnected with no edges between them (incomming or outgoing).
/// This test therefore ensures edges aren't taken the wrong directed.
///
#[quickcheck]
fn directed_doesnt_visit_incomming_component(
	component: ArbVerticesIn<ArbVertexIn<ArbConnectedGraph<Directed>>>,
	rest: ArbVerticesIn<MockGraph<Directed>>, weight: MockEdgeWeight)
	-> bool
{
	let mut graph = ((component.0).0).0.unconstrain();
	let comp_set = component.1;
	let v = (component.0).1;
	let g2 = rest.0;
	let g2_set = rest.1;

	// First join the two graphs
	let mut v_map = graph.join(&g2);

	// Add edges from other components to the start component
	for (v1,v2) in comp_set.iter().zip(g2_set.iter()) {
		graph.add_edge_weighted((v_map[v2], *v1, weight.clone())).unwrap();
	}

	// Ensure that no visited vertex comes from outside the start component
	DFS::new(&graph, v).all(|visit| v_map.values().all(|&new_v| visit != new_v))
}
<commit_msg>Added test of DFS to ensure any component with an edge from the start edge is also visited in full.<commit_after>//!
//! Tests `DFS`
//!

use crate::mock_graph::{MockGraph, MockVertex, arbitrary::{ArbVertexIn, ArbConnectedGraph}, MockEdgeWeight};
use graphene::core::{ImplGraph, Graph, Constrainer, AddVertex, AddEdge, Directed};
use graphene::algo::DFS;
use std::collections::{ HashSet, HashMap };
use crate::mock_graph::arbitrary::ArbVerticesIn;

duplicate_for_directedness!{
	$directedness

	///
	/// Tests that all vertices in a connected component are produced exactly once.
	///
	#[quickcheck]
	fn visits_component_once(ArbVertexIn(mock, v): ArbVertexIn<ArbConnectedGraph<directedness>>)
			 -> bool
	{
		// Use a set to ensure we only count each vertex once
		let mut visited = HashSet::new();
		let mut visited_once = true;
		DFS::new(mock.graph(), v).for_each(|v|{ visited_once &= visited.insert(v); });

		// We ensure all vertices were visited, but only once
		visited.len() == mock.0.all_vertices().count() && visited_once
	}

	///
	/// Tests that no vertices outside a connected component are produced
	///
	#[quickcheck]
	fn visits_none_outside_component(ArbVertexIn(g1, v): ArbVertexIn<ArbConnectedGraph<directedness>>,
		g2: MockGraph<directedness>)
		 -> bool
	{
		// Our starting connected component
		let mut graph = g1.0.unconstrain();

		// First join the two graphs
		let mut v_map = graph.join(&g2);

		// Ensure that no visited vertex comes from outside the start component
		DFS::new(&graph, v).all(|visit| v_map.values().all(|&new_v| visit != new_v))
	}
}

///
/// Tests for directed graphs, even if an edge targets a connected component from a different
/// component, only the first component's vertices are produced.
///
/// This is different from `visits_none_outside_component` because in that case the components
/// are completely unconnected with no edges between them (incomming or outgoing).
/// This test therefore ensures edges aren't taken the wrong directed.
///
#[quickcheck]
fn directed_doesnt_visit_incomming_component(
	component: ArbVerticesIn<ArbVertexIn<ArbConnectedGraph<Directed>>>,
	rest: ArbVerticesIn<MockGraph<Directed>>, weight: MockEdgeWeight)
	-> bool
{
	let mut graph = ((component.0).0).0.unconstrain();
	let comp_set = component.1;
	let v = (component.0).1;
	let g2 = rest.0;
	let g2_set = rest.1;

	// First join the two graphs
	let mut v_map = graph.join(&g2);

	// Add edges from the other component to the start component
	for (v1,v2) in comp_set.iter().zip(g2_set.iter()) {
		graph.add_edge_weighted((v_map[v2], *v1, weight.clone())).unwrap();
	}

	// Ensure that no visited vertex comes from outside the start component
	DFS::new(&graph, v).all(|visit| v_map.values().all(|&new_v| visit != new_v))
}

///
/// Tests for directed graphs that any component with an edge to it from the start component
/// is also visited in full.
///
#[quickcheck]
fn directed_visits_outgoing_component(
	comp1: ArbVerticesIn<ArbVertexIn<ArbConnectedGraph<Directed>>>,
	comp2: ArbVerticesIn<ArbVertexIn<ArbConnectedGraph<Directed>>>, weight: MockEdgeWeight)
	-> bool
{
	let mut graph = ((comp1.0).0).0.unconstrain();
	let comp1_set = comp1.1;
	let v = (comp1.0).1;
	let g2 = ((comp2.0).0).0;
	let comp2_set = comp2.1;
	let v2 = (comp2.0).1;

	// First join the two graphs
	let mut v_map = graph.join(&g2);

	// Add edges from start component to the other component
	graph.add_edge_weighted((v, v_map[&v2], weight.clone())).unwrap();
	for (v1,v2) in comp1_set.iter().zip(comp2_set.iter()) {
		graph.add_edge_weighted((*v1, v_map[v2], weight.clone())).unwrap();
	}

	// Ensure that all vertices are visited
	DFS::new(&graph, v).count() == graph.all_vertices().count()
}
<|endoftext|>


<commit_before>use std::io::BufReader;
use std::io::BufRead;
use std::fs::File;
use std::io::Write;
use std::collections::btree_map::BTreeMap;
use std::collections::btree_set::BTreeSet;
use std::iter::Iterator;

use sbsqsort;

macro_rules! errorln(
    ($($arg:tt)*) => (
        match writeln!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(e) => panic!("Unable to write to stderr: {}", e),
        }
    )
);

pub struct Recommender {
  categories : BTreeMap<String, BTreeSet<String>>,
  pages : BTreeMap<String, BTreeSet<String>>,
}

impl Recommender {
  pub fn load_knowlege(path : String) -> Recommender  {
    let file = match File::open(path) {
        Ok(file) => file,
        Err(e)  => panic!("Error occured opening knowlege file: {} ", e),
    };

    let reader = BufReader::new(&file);

    let mut categories = BTreeMap::new();
    let mut pages      = BTreeMap::new();

    for line in reader.lines().filter_map(|result| result.ok()) {
      let data : Vec<&str> = line.split(" ").collect();
      match data.len()  {
        0 => {
          errorln!("empty line found");
          continue;
        },
        1 => {
          errorln!("{} contains no categories", data[0]);
          continue;
        }
        _ => {}
      }

      let key = data[0];

      let page = pages.entry(String::from(key))
                      .or_insert(BTreeSet::new());

      for &category in data[1..].iter() {
        let category = String::from(category);

        page.insert(category.clone());
        categories.entry(category.clone())
                  .or_insert(BTreeSet::new())
                  .insert(String::from(key));
      }
    }

    let ret = Recommender {
      categories: categories,
      pages: pages
    };

    return ret;
  }

  pub fn recommend(self, categories : Vec<String>) -> Vec<String> {
    let mut ranked_pages = BTreeMap::new();

    for category in categories.iter() {
      match self.categories.get(category) {
        Some(self_cat) => {
          for page in self_cat.iter() {
            match self.pages.get(page) {
              Some(pages) => {
                ranked_pages.entry(page.clone())
                            .or_insert(
                                Recommender::similarity(categories.iter(), pages.iter()));
              },
              _ => {}
            }
          }
        },
        _ => {}
      }
    }

    let mut keys : Vec<String> = ranked_pages.keys().cloned().collect();
    let mut values : Vec<u64> = ranked_pages.values().cloned().collect();
    sbsqsort::quicksort(&mut values, &mut keys);

    return keys;
  }

  fn similarity<'a, S: Iterator<Item = &'a String>, T: Clone + Iterator<Item = &'a String>>(a : S, b : T) -> u64 {
     let mut found_in_both = 0;
     let mut cnt_a = 0;
     let mut cnt_b = 0;

     for _ in b.clone() { cnt_b += 1; }
     for c in a {
      cnt_a += 1;
      for d in b.clone() {
        if c == d {
          found_in_both += 1;
          break;
        }
      }
     }

     return 1000 * ((2 * found_in_both) as u64 / (cnt_a + cnt_b)) as u64;
  }
}

<commit_msg>Comments<commit_after>use std::io::BufReader;
use std::io::BufRead;
use std::fs::File;
use std::io::Write;
use std::collections::btree_map::BTreeMap;
use std::collections::btree_set::BTreeSet;
use std::iter::Iterator;

use sbsqsort;

macro_rules! errorln(
    ($($arg:tt)*) => (
        match writeln!(&mut ::std::io::stderr(), $($arg)* ) {
            Ok(_) => {},
            Err(e) => panic!("Unable to write to stderr: {}", e),
        }
    )
);

/// Loads things and catgories those things belong the thing
/// and then let you figure out which thing best matches a set
/// of categories
pub struct Recommender {
  categories : BTreeMap<String, BTreeSet<String>>,
  pages : BTreeMap<String, BTreeSet<String>>,
}

impl Recommender {
  /// Loads the knowlege file and returns a filled-in Recommended
  /// File should be in the following format. Each value should
  /// contain no whitespace
  ///
  ///    <thing> <category> <category> <category> ...
  ///
  /// Example:
  ///
  ///     trains transportation ground things-people-model
  ///     cars transportation ground
  ///     plane transportation air
  pub fn load_knowlege(path : String) -> Recommender  {
    let file = match File::open(path) {
        Ok(file) => file,
        Err(e)  => panic!("Error occured opening knowlege file: {} ", e),
    };

    let reader = BufReader::new(&file);

    let mut categories = BTreeMap::new();
    let mut pages      = BTreeMap::new();

    for line in reader.lines().filter_map(|result| result.ok()) {
      let data : Vec<&str> = line.split(" ").collect();
      match data.len()  {
        0 => {
          errorln!("empty line found");
          continue;
        },
        1 => {
          errorln!("{} contains no categories", data[0]);
          continue;
        }
        _ => {}
      }

      let key = data[0];

      let page = pages.entry(String::from(key))
                      .or_insert(BTreeSet::new());

      for &category in data[1..].iter() {
        let category = String::from(category);

        page.insert(category.clone());
        categories.entry(category.clone())
                  .or_insert(BTreeSet::new())
                  .insert(String::from(key));
      }
    }

    let ret = Recommender {
      categories: categories,
      pages: pages
    };

    return ret;
  }

  /// Finds the most closely related values in the set
  pub fn recommend(self, categories : Vec<String>) -> Vec<String> {
    let mut ranked_pages = BTreeMap::new();

    // Gather all the pages belonging to each category
    // and see store its similarity against the list.
    //
    // This is only done once per page.
    for category in categories.iter() {
      match self.categories.get(category) {
        Some(self_cat) => {
          for page in self_cat.iter() {
            match self.pages.get(page) {
              Some(pages) => {
                ranked_pages.entry(page.clone())
                            .or_insert(
                                Recommender::similarity(categories.iter(), pages.iter()));
              },
              _ => {}
            }
          }
        },
        _ => {}
      }
    }

    // Sort the pages by their similarity
    let mut keys : Vec<String> = ranked_pages.keys().cloned().collect();
    let mut values : Vec<u64> = ranked_pages.values().cloned().collect();
    sbsqsort::quicksort(&mut values, &mut keys);

    return keys;
  }

  /// Uses a Jaccard Index to measure similarity between sets of categories
  fn similarity<'a,
                 S: Iterator<Item = &'a String>,
                 T: Clone + Iterator<Item = &'a String>>
               (a : S, b : T) -> u64 {
     let mut found_in_both = 0;
     let mut cnt_a = 0;
     let mut cnt_b = 0;

     for _ in b.clone() { cnt_b += 1; }
     for c in a {
      cnt_a += 1;
      for d in b.clone() {
        if c == d {
          found_in_both += 1;
          break;
        }
      }
     }

     return 1000 * ((2 * found_in_both) as u64 / (cnt_a + cnt_b - found_in_both)) as u64;
  }
}

<|endoftext|>


<commit_before>use checksum::Crc8Reader;
use error::{FlacError, FlacResult};

#[deriving(Copy)]
enum BlockingStrategy {
    Fixed,
    Variable
}

#[deriving(Copy)]
enum BlockTime {
    FrameNumber(u32),
    SampleNumber(u64)
}

#[deriving(Copy, Show)] // TODO: should not derive show.
enum ChannelMode {
    /// The channels are coded as-is.
    Raw,
    /// Channel 0 is the left channel, channel 1 is the side channel.
    LeftSideStereo,
    /// Channel 0 is the side channel, channel 1 is the right channel.
    RightSideStereo,
    /// Channel 0 is the mid channel, channel 1 is the side channel.
    MidSideStereo
}

#[deriving(Copy)]
struct FrameHeader {
    pub block_time: BlockTime,
    pub block_size: u16,
    pub sample_rate: Option<u32>,
    pub n_channels: u8,
    pub channel_mode: ChannelMode,
    pub bits_per_sample: Option<u8>
    // TODO: there is also a sample or frame number.
}

/// Reads a variable-length integer encoded as what is called "UTF-8" coding
/// in the specification. (It is not real UTF-8.) This function can read
/// integers encoded in this way up to 36-bit integers.
fn read_var_length_int(input: &mut Reader) -> FlacResult<u64> {
    use std::iter::range_step_inclusive;
    use std::io::stdio::flush;
    // The number of consecutive 1s followed by a 0 is the number of additional
    // bytes to read.
    let first = try!(input.read_byte());
    let mut read_additional = 0u;
    let mut mask_data = 0b0111_1111u8;
    let mut mask_mark = 0b1000_0000u8;

    // Determine the number of leading 1s.
    while first & mask_mark != 0 {
        read_additional = read_additional + 1;
        mask_data = mask_data >> 1;
        mask_mark = mask_mark >> 1;
    }

    // A single leading 1 is a follow-up byte and thus invalid.
    if read_additional > 0 {
        if read_additional == 1 {
            return Err(FlacError::InvalidVarLengthInt);
        } else {
            // The number of 1s (if > 1) is the total number of bytes, not the
            // number of additional bytes.
            read_additional = read_additional - 1;
        }
    }

    // Each additional byte will yield 6 extra bits, so shift the most
    // significant bits into the correct position.
    let mut result = (first & mask_data) as u64 << (6 * read_additional);
    for i in range_step_inclusive(read_additional as int - 1, 0, -1) {
        let byte = try!(input.read_byte());

        // The two most significant bits _must_ be 10.
        if byte & 0b1100_0000 != 0b1000_0000 {
            return Err(FlacError::InvalidVarLengthInt);
        }

        result = result | ((byte & 0b0011_1111) as u64 << (6 * i as uint));
    }

    Ok(result)
}

#[test]
fn verify_read_var_length_int() {
    use std::io::MemReader;

    let mut reader = MemReader::new(vec!(0x24, 0xc2, 0xa2, 0xe2, 0x82, 0xac,
                                         0xf0, 0x90, 0x8d, 0x88, 0xc2, 0x00,
                                         0x80));
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x24);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0xa2);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x20ac);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x010348);
    // Two-byte integer with invalid continuation byte should fail.
    assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
               FlacError::InvalidVarLengthInt);
    // Continuation byte can never be the first byte.
    assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
               FlacError::InvalidVarLengthInt);
}

fn read_frame_header(input: &mut Reader) -> FlacResult<FrameHeader> {
    // The frame header includes a CRC-8 at the end. It can be computed
    // automatically while reading, by wrapping the input reader in a reader
    // that computes the CRC.
    let mut crc_input = Crc8Reader::new(input);

    // First are 14 bits frame sync code, a reserved bit, and blocking stategy.
    let sync_res_block = try!(crc_input.read_be_u16());

    // The first 14 bits must be 11111111111110.
    let sync_code = sync_res_block & 0b1111_1111_1111_1100;
    if sync_code != 0b1111_1111_1111_1000 {
        return Err(FlacError::MissingFrameSyncCode);
    }

    // The next bit has a mandatory value of 0 (at the moment of writing, if
    // the bit has a different value, it could be a future stream that we
    // cannot read).
    if sync_res_block & 0b0000_0000_0000_0010 != 0 {
        return Err(FlacError::InvalidFrameHeader);
    }

    // The final bit determines the blocking strategy.
    let blocking_strategy = if sync_res_block & 0b0000_0000_0000_0001 == 0 {
        BlockingStrategy::Fixed
    } else {
        BlockingStrategy::Variable
    };

    // Next are 4 bits block size and 4 bits sample rate.
    let bs_sr = try!(crc_input.read_byte());
    let mut block_size = 0u16;
    let mut read_8bit_bs = false;
    let mut read_16bit_bs = false;

    // There are some pre-defined bit patterns. Some mean 'get from end of
    // header instead'.
    match bs_sr >> 4 {
        // The value 0000 is reserved.
        0b0000 => return Err(FlacError::InvalidFrameHeader),
        0b0001 => block_size = 192,
        n if 0b0010 <= n && n <= 0b0101 => block_size = 576 * (1 << (n - 2) as uint),
        0b0110 => read_8bit_bs = true,
        0b0111 => read_16bit_bs = true,
        n => block_size = 256 * (1 << (n - 8) as uint)
    }

    // For the sample rate there is a number of pre-defined bit patterns as
    // well. Again, some mean 'get from end of header instead'.
    let mut sample_rate = None;
    let mut read_8bit_sr = false;
    let mut read_16bit_sr = false;
    let mut read_16bit_sr_ten = false;

    match bs_sr & 0b0000_1111 {
        0b0000 => sample_rate = None, // 0000 means 'get from streaminfo block'.
        0b0001 => sample_rate = Some( 88_200),
        0b0010 => sample_rate = Some(176_400),
        0b0011 => sample_rate = Some(192_000),
        0b0100 => sample_rate = Some(  8_000),
        0b0101 => sample_rate = Some( 16_000),
        0b0110 => sample_rate = Some( 22_050),
        0b0111 => sample_rate = Some( 24_000),
        0b1000 => sample_rate = Some( 32_000),
        0b1001 => sample_rate = Some( 44_100),
        0b1010 => sample_rate = Some( 48_000),
        0b1011 => sample_rate = Some( 96_000),
        0b1100 => read_8bit_sr = true, // Read Hz from end of header.
        0b1101 => read_16bit_sr = true, // Read Hz from end of header.
        0b1110 => read_16bit_sr_ten = true, // Read tens of Hz from end of header.
        // 1111 is invalid to prevent sync-fooling.
        // Other values are impossible at this point.
        _ => return Err(FlacError::InvalidFrameHeader)
    }

    // Next are 4 bits channel assignment, 3 bits sample size, and 1 reserved bit.
    let chan_bps_res = try!(crc_input.read_byte());

    // The most significant 4 bits determine channel assignment.
    let (n_channels, channel_mode) = match chan_bps_res >> 4 {
        // Values 0 through 7 indicate n + 1 channels without mixing.
        n if n < 8 => (n + 1, ChannelMode::Raw),
        0b1000 => (2, ChannelMode::LeftSideStereo),
        0b1001 => (2, ChannelMode::RightSideStereo),
        0b1010 => (2, ChannelMode::MidSideStereo),
        // Values 1011 through 1111 are reserved and thus invalid.
        _ => return Err(FlacError::InvalidFrameHeader)
    };

    // The next three bits indicate bits per sample.
    let bits_per_sample = match (chan_bps_res & 0b0000_1110) >> 1 {
        0b000 => None, // 000 means 'get from streaminfo block'.
        0b001 => Some(8),
        0b010 => Some(12),
        0b100 => Some(16),
        0b101 => Some(20),
        0b110 => Some(24),
        // Values 011 and 111 are reserved. Other values are impossible.
        _ => return Err(FlacError::InvalidFrameHeader)
    };

    // The final bit has a mandatory value of 0.
    if chan_bps_res & 0b0000_0001 != 0 {
        return Err(FlacError::InvalidFrameHeader);
    }

    let block_time = match blocking_strategy {
        BlockingStrategy::Variable => {
            // The sample number is encoded in 8-56 bits, at most a 36-bit int.
            let sample = try!(read_var_length_int(&mut crc_input));
            BlockTime::SampleNumber(sample)
        },
        BlockingStrategy::Fixed => {
            // The frame number is encoded in 8-48 bits, at most a 31-bit int.
            let frame = try!(read_var_length_int(&mut crc_input));
            // A frame number larger than 31 bits is therefore invalid.
            if frame > 0x7fffffff {
                return Err(FlacError::InvalidFrameHeader);
            }
            BlockTime::FrameNumber(frame as u32)
        }
    };

    if read_8bit_bs {
        // 8 bit block size - 1 is stored.
        let bs = try!(crc_input.read_byte());
        block_size = bs as u16 + 1;
    }
    if read_16bit_bs {
        // 16-bit block size - 1 is stored. Note that the max block size that
        // can be indicated in the streaminfo block is a 16-bit number, so a
        // value of 0xffff would be invalid because it exceeds the max block
        // size, though this is not mentioned explicitly in the specification.
        let bs = try!(crc_input.read_be_u16());
        if bs == 0xffff { return Err(FlacError::InvalidBlockSize); }
        block_size = bs + 1;
    }

    if read_8bit_sr {
        let sr = try!(crc_input.read_byte());
        sample_rate = Some(sr as u32);
    }
    if read_16bit_sr {
        let sr = try!(crc_input.read_be_u16());
        sample_rate = Some(sr as u32);
    }
    if read_16bit_sr_ten {
        let sr_ten = try!(crc_input.read_be_u16());
        sample_rate = Some(sr_ten as u32 * 10);
    }

    // Next is an 8-bit CRC that is computed over the entire header so far.
    let computed_crc = crc_input.crc();
    let presumed_crc = try!(crc_input.read_byte());

    if computed_crc != presumed_crc {
        return Err(FlacError::FrameHeaderCrcMismatch);
    }

    let frame_header = FrameHeader {
       block_time: block_time,
       block_size: block_size,
       sample_rate: sample_rate,
       n_channels: n_channels,
       channel_mode: channel_mode,
       bits_per_sample: bits_per_sample
    };
    Ok(frame_header)
}

/// Reads frames from a stream and exposes them as an iterator.
///
/// TODO: for now, it is assumes that the reader starts at a frame header;
/// no searching for a sync code is performed at the moment.
pub struct FrameReader<'r> {
    input: &'r mut (Reader + 'r),
}

/// TODO
struct Frame;

/// Either a `Frame` or a `FlacError`.
pub type FrameResult = FlacResult<Frame>;

impl<'r> FrameReader<'r> {

    /// Creates a new frame reader that will yield at least one element.
    pub fn new(input: &'r mut Reader) -> FrameReader<'r> {
        FrameReader { input: input }
    }

    fn read_next(&mut self) -> FrameResult {
        let header = try!(read_frame_header(self.input));

        // TODO: remove this print.
        println!("Frame: bs = {}, sr = {}, n_ch = {}, cm = {}, bps = {}",
                 header.block_size,
                 header.sample_rate,
                 header.n_channels,
                 header.channel_mode,
                 header.bits_per_sample);

        // TODO: read the subframes and padding
        // TODO: read frame footer

        Ok(Frame)
    }
}

impl<'r> Iterator<FrameResult> for FrameReader<'r> {
    fn next(&mut self) -> Option<FrameResult> {
        // TODO: there needs to be a way to determine whether stream has ended.
        // In that case, we need to know the stream lengh, so we need to know
        // the streaminfo (which we might need anyway) ...
        Some(self.read_next())
    }

    // TODO: it would be possible to give quite an accurate size hint.
}
<commit_msg>remove redundant use statement<commit_after>use checksum::Crc8Reader;
use error::{FlacError, FlacResult};

#[deriving(Copy)]
enum BlockingStrategy {
    Fixed,
    Variable
}

#[deriving(Copy)]
enum BlockTime {
    FrameNumber(u32),
    SampleNumber(u64)
}

#[deriving(Copy, Show)] // TODO: should not derive show.
enum ChannelMode {
    /// The channels are coded as-is.
    Raw,
    /// Channel 0 is the left channel, channel 1 is the side channel.
    LeftSideStereo,
    /// Channel 0 is the side channel, channel 1 is the right channel.
    RightSideStereo,
    /// Channel 0 is the mid channel, channel 1 is the side channel.
    MidSideStereo
}

#[deriving(Copy)]
struct FrameHeader {
    pub block_time: BlockTime,
    pub block_size: u16,
    pub sample_rate: Option<u32>,
    pub n_channels: u8,
    pub channel_mode: ChannelMode,
    pub bits_per_sample: Option<u8>
    // TODO: there is also a sample or frame number.
}

/// Reads a variable-length integer encoded as what is called "UTF-8" coding
/// in the specification. (It is not real UTF-8.) This function can read
/// integers encoded in this way up to 36-bit integers.
fn read_var_length_int(input: &mut Reader) -> FlacResult<u64> {
    use std::iter::range_step_inclusive;
    // The number of consecutive 1s followed by a 0 is the number of additional
    // bytes to read.
    let first = try!(input.read_byte());
    let mut read_additional = 0u;
    let mut mask_data = 0b0111_1111u8;
    let mut mask_mark = 0b1000_0000u8;

    // Determine the number of leading 1s.
    while first & mask_mark != 0 {
        read_additional = read_additional + 1;
        mask_data = mask_data >> 1;
        mask_mark = mask_mark >> 1;
    }

    // A single leading 1 is a follow-up byte and thus invalid.
    if read_additional > 0 {
        if read_additional == 1 {
            return Err(FlacError::InvalidVarLengthInt);
        } else {
            // The number of 1s (if > 1) is the total number of bytes, not the
            // number of additional bytes.
            read_additional = read_additional - 1;
        }
    }

    // Each additional byte will yield 6 extra bits, so shift the most
    // significant bits into the correct position.
    let mut result = (first & mask_data) as u64 << (6 * read_additional);
    for i in range_step_inclusive(read_additional as int - 1, 0, -1) {
        let byte = try!(input.read_byte());

        // The two most significant bits _must_ be 10.
        if byte & 0b1100_0000 != 0b1000_0000 {
            return Err(FlacError::InvalidVarLengthInt);
        }

        result = result | ((byte & 0b0011_1111) as u64 << (6 * i as uint));
    }

    Ok(result)
}

#[test]
fn verify_read_var_length_int() {
    use std::io::MemReader;

    let mut reader = MemReader::new(vec!(0x24, 0xc2, 0xa2, 0xe2, 0x82, 0xac,
                                         0xf0, 0x90, 0x8d, 0x88, 0xc2, 0x00,
                                         0x80));
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x24);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0xa2);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x20ac);
    assert_eq!(read_var_length_int(&mut reader).unwrap(), 0x010348);
    // Two-byte integer with invalid continuation byte should fail.
    assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
               FlacError::InvalidVarLengthInt);
    // Continuation byte can never be the first byte.
    assert_eq!(read_var_length_int(&mut reader).err().unwrap(),
               FlacError::InvalidVarLengthInt);
}

fn read_frame_header(input: &mut Reader) -> FlacResult<FrameHeader> {
    // The frame header includes a CRC-8 at the end. It can be computed
    // automatically while reading, by wrapping the input reader in a reader
    // that computes the CRC.
    let mut crc_input = Crc8Reader::new(input);

    // First are 14 bits frame sync code, a reserved bit, and blocking stategy.
    let sync_res_block = try!(crc_input.read_be_u16());

    // The first 14 bits must be 11111111111110.
    let sync_code = sync_res_block & 0b1111_1111_1111_1100;
    if sync_code != 0b1111_1111_1111_1000 {
        return Err(FlacError::MissingFrameSyncCode);
    }

    // The next bit has a mandatory value of 0 (at the moment of writing, if
    // the bit has a different value, it could be a future stream that we
    // cannot read).
    if sync_res_block & 0b0000_0000_0000_0010 != 0 {
        return Err(FlacError::InvalidFrameHeader);
    }

    // The final bit determines the blocking strategy.
    let blocking_strategy = if sync_res_block & 0b0000_0000_0000_0001 == 0 {
        BlockingStrategy::Fixed
    } else {
        BlockingStrategy::Variable
    };

    // Next are 4 bits block size and 4 bits sample rate.
    let bs_sr = try!(crc_input.read_byte());
    let mut block_size = 0u16;
    let mut read_8bit_bs = false;
    let mut read_16bit_bs = false;

    // There are some pre-defined bit patterns. Some mean 'get from end of
    // header instead'.
    match bs_sr >> 4 {
        // The value 0000 is reserved.
        0b0000 => return Err(FlacError::InvalidFrameHeader),
        0b0001 => block_size = 192,
        n if 0b0010 <= n && n <= 0b0101 => block_size = 576 * (1 << (n - 2) as uint),
        0b0110 => read_8bit_bs = true,
        0b0111 => read_16bit_bs = true,
        n => block_size = 256 * (1 << (n - 8) as uint)
    }

    // For the sample rate there is a number of pre-defined bit patterns as
    // well. Again, some mean 'get from end of header instead'.
    let mut sample_rate = None;
    let mut read_8bit_sr = false;
    let mut read_16bit_sr = false;
    let mut read_16bit_sr_ten = false;

    match bs_sr & 0b0000_1111 {
        0b0000 => sample_rate = None, // 0000 means 'get from streaminfo block'.
        0b0001 => sample_rate = Some( 88_200),
        0b0010 => sample_rate = Some(176_400),
        0b0011 => sample_rate = Some(192_000),
        0b0100 => sample_rate = Some(  8_000),
        0b0101 => sample_rate = Some( 16_000),
        0b0110 => sample_rate = Some( 22_050),
        0b0111 => sample_rate = Some( 24_000),
        0b1000 => sample_rate = Some( 32_000),
        0b1001 => sample_rate = Some( 44_100),
        0b1010 => sample_rate = Some( 48_000),
        0b1011 => sample_rate = Some( 96_000),
        0b1100 => read_8bit_sr = true, // Read Hz from end of header.
        0b1101 => read_16bit_sr = true, // Read Hz from end of header.
        0b1110 => read_16bit_sr_ten = true, // Read tens of Hz from end of header.
        // 1111 is invalid to prevent sync-fooling.
        // Other values are impossible at this point.
        _ => return Err(FlacError::InvalidFrameHeader)
    }

    // Next are 4 bits channel assignment, 3 bits sample size, and 1 reserved bit.
    let chan_bps_res = try!(crc_input.read_byte());

    // The most significant 4 bits determine channel assignment.
    let (n_channels, channel_mode) = match chan_bps_res >> 4 {
        // Values 0 through 7 indicate n + 1 channels without mixing.
        n if n < 8 => (n + 1, ChannelMode::Raw),
        0b1000 => (2, ChannelMode::LeftSideStereo),
        0b1001 => (2, ChannelMode::RightSideStereo),
        0b1010 => (2, ChannelMode::MidSideStereo),
        // Values 1011 through 1111 are reserved and thus invalid.
        _ => return Err(FlacError::InvalidFrameHeader)
    };

    // The next three bits indicate bits per sample.
    let bits_per_sample = match (chan_bps_res & 0b0000_1110) >> 1 {
        0b000 => None, // 000 means 'get from streaminfo block'.
        0b001 => Some(8),
        0b010 => Some(12),
        0b100 => Some(16),
        0b101 => Some(20),
        0b110 => Some(24),
        // Values 011 and 111 are reserved. Other values are impossible.
        _ => return Err(FlacError::InvalidFrameHeader)
    };

    // The final bit has a mandatory value of 0.
    if chan_bps_res & 0b0000_0001 != 0 {
        return Err(FlacError::InvalidFrameHeader);
    }

    let block_time = match blocking_strategy {
        BlockingStrategy::Variable => {
            // The sample number is encoded in 8-56 bits, at most a 36-bit int.
            let sample = try!(read_var_length_int(&mut crc_input));
            BlockTime::SampleNumber(sample)
        },
        BlockingStrategy::Fixed => {
            // The frame number is encoded in 8-48 bits, at most a 31-bit int.
            let frame = try!(read_var_length_int(&mut crc_input));
            // A frame number larger than 31 bits is therefore invalid.
            if frame > 0x7fffffff {
                return Err(FlacError::InvalidFrameHeader);
            }
            BlockTime::FrameNumber(frame as u32)
        }
    };

    if read_8bit_bs {
        // 8 bit block size - 1 is stored.
        let bs = try!(crc_input.read_byte());
        block_size = bs as u16 + 1;
    }
    if read_16bit_bs {
        // 16-bit block size - 1 is stored. Note that the max block size that
        // can be indicated in the streaminfo block is a 16-bit number, so a
        // value of 0xffff would be invalid because it exceeds the max block
        // size, though this is not mentioned explicitly in the specification.
        let bs = try!(crc_input.read_be_u16());
        if bs == 0xffff { return Err(FlacError::InvalidBlockSize); }
        block_size = bs + 1;
    }

    if read_8bit_sr {
        let sr = try!(crc_input.read_byte());
        sample_rate = Some(sr as u32);
    }
    if read_16bit_sr {
        let sr = try!(crc_input.read_be_u16());
        sample_rate = Some(sr as u32);
    }
    if read_16bit_sr_ten {
        let sr_ten = try!(crc_input.read_be_u16());
        sample_rate = Some(sr_ten as u32 * 10);
    }

    // Next is an 8-bit CRC that is computed over the entire header so far.
    let computed_crc = crc_input.crc();
    let presumed_crc = try!(crc_input.read_byte());

    if computed_crc != presumed_crc {
        return Err(FlacError::FrameHeaderCrcMismatch);
    }

    let frame_header = FrameHeader {
       block_time: block_time,
       block_size: block_size,
       sample_rate: sample_rate,
       n_channels: n_channels,
       channel_mode: channel_mode,
       bits_per_sample: bits_per_sample
    };
    Ok(frame_header)
}

/// Reads frames from a stream and exposes them as an iterator.
///
/// TODO: for now, it is assumes that the reader starts at a frame header;
/// no searching for a sync code is performed at the moment.
pub struct FrameReader<'r> {
    input: &'r mut (Reader + 'r),
}

/// TODO
struct Frame;

/// Either a `Frame` or a `FlacError`.
pub type FrameResult = FlacResult<Frame>;

impl<'r> FrameReader<'r> {

    /// Creates a new frame reader that will yield at least one element.
    pub fn new(input: &'r mut Reader) -> FrameReader<'r> {
        FrameReader { input: input }
    }

    fn read_next(&mut self) -> FrameResult {
        let header = try!(read_frame_header(self.input));

        // TODO: remove this print.
        println!("Frame: bs = {}, sr = {}, n_ch = {}, cm = {}, bps = {}",
                 header.block_size,
                 header.sample_rate,
                 header.n_channels,
                 header.channel_mode,
                 header.bits_per_sample);

        // TODO: read the subframes and padding
        // TODO: read frame footer

        Ok(Frame)
    }
}

impl<'r> Iterator<FrameResult> for FrameReader<'r> {
    fn next(&mut self) -> Option<FrameResult> {
        // TODO: there needs to be a way to determine whether stream has ended.
        // In that case, we need to know the stream lengh, so we need to know
        // the streaminfo (which we might need anyway) ...
        Some(self.read_next())
    }

    // TODO: it would be possible to give quite an accurate size hint.
}
<|endoftext|>


<commit_before>#[cfg(any(feature = "alloc", feature = "std", test))]
use crate::engine::DecodeEstimate;
use crate::engine::Engine;
#[cfg(any(feature = "alloc", feature = "std", test))]
use crate::engine::DEFAULT_ENGINE;
#[cfg(any(feature = "alloc", feature = "std", test))]
use alloc::vec::Vec;
use core::fmt;
#[cfg(any(feature = "std", test))]
use std::error;

/// Errors that can occur while decoding.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DecodeError {
    /// An invalid byte was found in the input. The offset and offending byte are provided.
    InvalidByte(usize, u8),
    /// The length of the input is invalid.
    /// A typical cause of this is stray trailing whitespace or other separator bytes.
    /// In the case where excess trailing bytes have produced an invalid length *and* the last byte
    /// is also an invalid base64 symbol (as would be the case for whitespace, etc), `InvalidByte`
    /// will be emitted instead of `InvalidLength` to make the issue easier to debug.
    InvalidLength,
    /// The last non-padding input symbol's encoded 6 bits have nonzero bits that will be discarded.
    /// This is indicative of corrupted or truncated Base64.
    /// Unlike InvalidByte, which reports symbols that aren't in the alphabet, this error is for
    /// symbols that are in the alphabet but represent nonsensical encodings.
    InvalidLastSymbol(usize, u8),
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Self::InvalidByte(index, byte) => write!(f, "Invalid byte {}, offset {}.", byte, index),
            Self::InvalidLength => write!(f, "Encoded text cannot have a 6-bit remainder."),
            Self::InvalidLastSymbol(index, byte) => {
                write!(f, "Invalid last symbol {}, offset {}.", byte, index)
            }
        }
    }
}

#[cfg(any(feature = "std", test))]
impl error::Error for DecodeError {
    fn description(&self) -> &str {
        match *self {
            Self::InvalidByte(_, _) => "invalid byte",
            Self::InvalidLength => "invalid length",
            Self::InvalidLastSymbol(_, _) => "invalid last symbol",
        }
    }

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

///Decode base64 using the [default engine](DEFAULT_ENGINE).
///Returns a `Result` containing a `Vec<u8>`.
///
///# Example
///
///```rust
/// let bytes = base64::decode("aGVsbG8gd29ybGQ=").unwrap();
/// println!("{:?}", bytes);
///```
#[cfg(any(feature = "alloc", feature = "std", test))]
pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<Vec<u8>, DecodeError> {
    decode_engine(input, &DEFAULT_ENGINE)
}

///Decode from string reference as octets using the specified [Engine].
///Returns a `Result` containing a `Vec<u8>`.
///
///# Example
///
///```rust
///    let bytes = base64::decode_engine(
///        "aGVsbG8gd29ybGR+Cg==",
///        &base64::engine::DEFAULT_ENGINE,
///    ).unwrap();
///    println!("{:?}", bytes);
///
///    // custom engine setup
///    let bytes_url = base64::decode_engine(
///        "aGVsbG8gaW50ZXJuZXR-Cg",
///        &base64::engine::fast_portable::FastPortable::from(
///            &base64::alphabet::URL_SAFE,
///            base64::engine::fast_portable::NO_PAD),
///
///    ).unwrap();
///    println!("{:?}", bytes_url);
///```
#[cfg(any(feature = "alloc", feature = "std", test))]
pub fn decode_engine<E: Engine, T: AsRef<[u8]>>(
    input: T,
    engine: &E,
) -> Result<Vec<u8>, DecodeError> {
    let mut buffer = Vec::<u8>::with_capacity(input.as_ref().len() * 4 / 3);

    decode_engine_vec(input, &mut buffer, engine).map(|_| buffer)
}

///Decode from string reference as octets.
///Writes into the supplied `Vec`, which may allocate if its internal buffer isn't big enough.
///Returns a `Result` containing an empty tuple, aka `()`.
///
///# Example
///
///```rust
///const URL_SAFE_ENGINE: base64::engine::fast_portable::FastPortable =
///    base64::engine::fast_portable::FastPortable::from(
///        &base64::alphabet::URL_SAFE,
///        base64::engine::fast_portable::PAD);
///
///fn main() {
///    let mut buffer = Vec::<u8>::new();
///    // with the default engine
///    base64::decode_engine_vec(
///        "aGVsbG8gd29ybGR+Cg==",
///        &mut buffer,
///        &base64::engine::DEFAULT_ENGINE
///    ).unwrap();
///    println!("{:?}", buffer);
///
///    buffer.clear();
///
///    // with a custom engine
///    base64::decode_engine_vec(
///        "aGVsbG8gaW50ZXJuZXR-Cg==",
///        &mut buffer,
///        &URL_SAFE_ENGINE
///    ).unwrap();
///    println!("{:?}", buffer);
///}
///```
#[cfg(any(feature = "alloc", feature = "std", test))]
pub fn decode_engine_vec<E: Engine, T: AsRef<[u8]>>(
    input: T,
    buffer: &mut Vec<u8>,
    engine: &E,
) -> Result<(), DecodeError> {
    let input_bytes = input.as_ref();

    let starting_output_len = buffer.len();

    let estimate = engine.decoded_length_estimate(input_bytes.len());
    let total_len_estimate = estimate
        .decoded_length_estimate()
        .checked_add(starting_output_len)
        .expect("Overflow when calculating output buffer length");
    buffer.resize(total_len_estimate, 0);

    let buffer_slice = &mut buffer.as_mut_slice()[starting_output_len..];
    let bytes_written = engine.decode(input_bytes, buffer_slice, estimate)?;

    buffer.truncate(starting_output_len + bytes_written);

    Ok(())
}

/// Decode the input into the provided output slice.
///
/// This will not write any bytes past exactly what is decoded (no stray garbage bytes at the end).
///
/// If you don't know ahead of time what the decoded length should be, size your buffer with a
/// conservative estimate for the decoded length of an input: 3 bytes of output for every 4 bytes of
/// input, rounded up, or in other words `(input_len + 3) / 4 * 3`.
///
/// # Panics
///
/// If the slice is not large enough, this will panic.
pub fn decode_engine_slice<E: Engine, T: AsRef<[u8]>>(
    input: T,
    output: &mut [u8],
    engine: &E,
) -> Result<usize, DecodeError> {
    let input_bytes = input.as_ref();

    engine.decode(
        input_bytes,
        output,
        engine.decoded_length_estimate(input_bytes.len()),
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{encode::encode_engine_string, tests::assert_encode_sanity};

    use crate::engine::Config;
    use crate::tests::random_engine;
    use rand::{
        distributions::{Distribution, Uniform},
        Rng, SeedableRng,
    };

    #[test]
    fn decode_into_nonempty_vec_doesnt_clobber_existing_prefix() {
        let mut orig_data = Vec::new();
        let mut encoded_data = String::new();
        let mut decoded_with_prefix = Vec::new();
        let mut decoded_without_prefix = Vec::new();
        let mut prefix = Vec::new();

        let prefix_len_range = Uniform::new(0, 1000);
        let input_len_range = Uniform::new(0, 1000);

        let mut rng = rand::rngs::SmallRng::from_entropy();

        for _ in 0..10_000 {
            orig_data.clear();
            encoded_data.clear();
            decoded_with_prefix.clear();
            decoded_without_prefix.clear();
            prefix.clear();

            let input_len = input_len_range.sample(&mut rng);

            for _ in 0..input_len {
                orig_data.push(rng.gen());
            }

            let engine = random_engine(&mut rng);
            encode_engine_string(&orig_data, &mut encoded_data, &engine);
            assert_encode_sanity(&encoded_data, engine.config().encode_padding(), input_len);

            let prefix_len = prefix_len_range.sample(&mut rng);

            // fill the buf with a prefix
            for _ in 0..prefix_len {
                prefix.push(rng.gen());
            }

            decoded_with_prefix.resize(prefix_len, 0);
            decoded_with_prefix.copy_from_slice(&prefix);

            // decode into the non-empty buf
            decode_engine_vec(&encoded_data, &mut decoded_with_prefix, &engine).unwrap();
            // also decode into the empty buf
            decode_engine_vec(&encoded_data, &mut decoded_without_prefix, &engine).unwrap();

            assert_eq!(
                prefix_len + decoded_without_prefix.len(),
                decoded_with_prefix.len()
            );
            assert_eq!(orig_data, decoded_without_prefix);

            // append plain decode onto prefix
            prefix.append(&mut decoded_without_prefix);

            assert_eq!(prefix, decoded_with_prefix);
        }
    }

    #[test]
    fn decode_into_slice_doesnt_clobber_existing_prefix_or_suffix() {
        let mut orig_data = Vec::new();
        let mut encoded_data = String::new();
        let mut decode_buf = Vec::new();
        let mut decode_buf_copy: Vec<u8> = Vec::new();

        let input_len_range = Uniform::new(0, 1000);

        let mut rng = rand::rngs::SmallRng::from_entropy();

        for _ in 0..10_000 {
            orig_data.clear();
            encoded_data.clear();
            decode_buf.clear();
            decode_buf_copy.clear();

            let input_len = input_len_range.sample(&mut rng);

            for _ in 0..input_len {
                orig_data.push(rng.gen());
            }

            let engine = random_engine(&mut rng);
            encode_engine_string(&orig_data, &mut encoded_data, &engine);
            assert_encode_sanity(&encoded_data, engine.config().encode_padding(), input_len);

            // fill the buffer with random garbage, long enough to have some room before and after
            for _ in 0..5000 {
                decode_buf.push(rng.gen());
            }

            // keep a copy for later comparison
            decode_buf_copy.extend(decode_buf.iter());

            let offset = 1000;

            // decode into the non-empty buf
            let decode_bytes_written =
                decode_engine_slice(&encoded_data, &mut decode_buf[offset..], &engine).unwrap();

            assert_eq!(orig_data.len(), decode_bytes_written);
            assert_eq!(
                orig_data,
                &decode_buf[offset..(offset + decode_bytes_written)]
            );
            assert_eq!(&decode_buf_copy[0..offset], &decode_buf[0..offset]);
            assert_eq!(
                &decode_buf_copy[offset + decode_bytes_written..],
                &decode_buf[offset + decode_bytes_written..]
            );
        }
    }

    #[test]
    fn decode_into_slice_fits_in_precisely_sized_slice() {
        let mut orig_data = Vec::new();
        let mut encoded_data = String::new();
        let mut decode_buf = Vec::new();

        let input_len_range = Uniform::new(0, 1000);
        let mut rng = rand::rngs::SmallRng::from_entropy();

        for _ in 0..10_000 {
            orig_data.clear();
            encoded_data.clear();
            decode_buf.clear();

            let input_len = input_len_range.sample(&mut rng);

            for _ in 0..input_len {
                orig_data.push(rng.gen());
            }

            let engine = random_engine(&mut rng);
            encode_engine_string(&orig_data, &mut encoded_data, &engine);
            assert_encode_sanity(&encoded_data, engine.config().encode_padding(), input_len);

            decode_buf.resize(input_len, 0);

            // decode into the non-empty buf
            let decode_bytes_written =
                decode_engine_slice(&encoded_data, &mut decode_buf[..], &engine).unwrap();

            assert_eq!(orig_data.len(), decode_bytes_written);
            assert_eq!(orig_data, decode_buf);
        }
    }
}
<commit_msg>decode vec size -- don't oversize the vector<commit_after>#[cfg(any(feature = "alloc", feature = "std", test))]
use crate::engine::DecodeEstimate;
use crate::engine::Engine;
#[cfg(any(feature = "alloc", feature = "std", test))]
use crate::engine::DEFAULT_ENGINE;
#[cfg(any(feature = "alloc", feature = "std", test))]
use alloc::vec::Vec;
use core::fmt;
#[cfg(any(feature = "std", test))]
use std::error;

/// Errors that can occur while decoding.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DecodeError {
    /// An invalid byte was found in the input. The offset and offending byte are provided.
    InvalidByte(usize, u8),
    /// The length of the input is invalid.
    /// A typical cause of this is stray trailing whitespace or other separator bytes.
    /// In the case where excess trailing bytes have produced an invalid length *and* the last byte
    /// is also an invalid base64 symbol (as would be the case for whitespace, etc), `InvalidByte`
    /// will be emitted instead of `InvalidLength` to make the issue easier to debug.
    InvalidLength,
    /// The last non-padding input symbol's encoded 6 bits have nonzero bits that will be discarded.
    /// This is indicative of corrupted or truncated Base64.
    /// Unlike InvalidByte, which reports symbols that aren't in the alphabet, this error is for
    /// symbols that are in the alphabet but represent nonsensical encodings.
    InvalidLastSymbol(usize, u8),
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Self::InvalidByte(index, byte) => write!(f, "Invalid byte {}, offset {}.", byte, index),
            Self::InvalidLength => write!(f, "Encoded text cannot have a 6-bit remainder."),
            Self::InvalidLastSymbol(index, byte) => {
                write!(f, "Invalid last symbol {}, offset {}.", byte, index)
            }
        }
    }
}

#[cfg(any(feature = "std", test))]
impl error::Error for DecodeError {
    fn description(&self) -> &str {
        match *self {
            Self::InvalidByte(_, _) => "invalid byte",
            Self::InvalidLength => "invalid length",
            Self::InvalidLastSymbol(_, _) => "invalid last symbol",
        }
    }

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

///Decode base64 using the [default engine](DEFAULT_ENGINE).
///Returns a `Result` containing a `Vec<u8>`.
///
///# Example
///
///```rust
/// let bytes = base64::decode("aGVsbG8gd29ybGQ=").unwrap();
/// println!("{:?}", bytes);
///```
#[cfg(any(feature = "alloc", feature = "std", test))]
pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<Vec<u8>, DecodeError> {
    decode_engine(input, &DEFAULT_ENGINE)
}

///Decode from string reference as octets using the specified [Engine].
///Returns a `Result` containing a `Vec<u8>`.
///
///# Example
///
///```rust
///    let bytes = base64::decode_engine(
///        "aGVsbG8gd29ybGR+Cg==",
///        &base64::engine::DEFAULT_ENGINE,
///    ).unwrap();
///    println!("{:?}", bytes);
///
///    // custom engine setup
///    let bytes_url = base64::decode_engine(
///        "aGVsbG8gaW50ZXJuZXR-Cg",
///        &base64::engine::fast_portable::FastPortable::from(
///            &base64::alphabet::URL_SAFE,
///            base64::engine::fast_portable::NO_PAD),
///
///    ).unwrap();
///    println!("{:?}", bytes_url);
///```
#[cfg(any(feature = "alloc", feature = "std", test))]
pub fn decode_engine<E: Engine, T: AsRef<[u8]>>(
    input: T,
    engine: &E,
) -> Result<Vec<u8>, DecodeError> {
    let mut buffer = Vec::<u8>::new();
    decode_engine_vec(input, &mut buffer, engine).map(|_| buffer)
}

///Decode from string reference as octets.
///Writes into the supplied `Vec`, which may allocate if its internal buffer isn't big enough.
///Returns a `Result` containing an empty tuple, aka `()`.
///
///# Example
///
///```rust
///const URL_SAFE_ENGINE: base64::engine::fast_portable::FastPortable =
///    base64::engine::fast_portable::FastPortable::from(
///        &base64::alphabet::URL_SAFE,
///        base64::engine::fast_portable::PAD);
///
///fn main() {
///    let mut buffer = Vec::<u8>::new();
///    // with the default engine
///    base64::decode_engine_vec(
///        "aGVsbG8gd29ybGR+Cg==",
///        &mut buffer,
///        &base64::engine::DEFAULT_ENGINE
///    ).unwrap();
///    println!("{:?}", buffer);
///
///    buffer.clear();
///
///    // with a custom engine
///    base64::decode_engine_vec(
///        "aGVsbG8gaW50ZXJuZXR-Cg==",
///        &mut buffer,
///        &URL_SAFE_ENGINE
///    ).unwrap();
///    println!("{:?}", buffer);
///}
///```
#[cfg(any(feature = "alloc", feature = "std", test))]
pub fn decode_engine_vec<E: Engine, T: AsRef<[u8]>>(
    input: T,
    buffer: &mut Vec<u8>,
    engine: &E,
) -> Result<(), DecodeError> {
    let input_bytes = input.as_ref();

    let starting_output_len = buffer.len();

    let estimate = engine.decoded_length_estimate(input_bytes.len());
    let total_len_estimate = estimate
        .decoded_length_estimate()
        .checked_add(starting_output_len)
        .expect("Overflow when calculating output buffer length");
    buffer.resize(total_len_estimate, 0);

    let buffer_slice = &mut buffer.as_mut_slice()[starting_output_len..];
    let bytes_written = engine.decode(input_bytes, buffer_slice, estimate)?;

    buffer.truncate(starting_output_len + bytes_written);

    Ok(())
}

/// Decode the input into the provided output slice.
///
/// This will not write any bytes past exactly what is decoded (no stray garbage bytes at the end).
///
/// If you don't know ahead of time what the decoded length should be, size your buffer with a
/// conservative estimate for the decoded length of an input: 3 bytes of output for every 4 bytes of
/// input, rounded up, or in other words `(input_len + 3) / 4 * 3`.
///
/// # Panics
///
/// If the slice is not large enough, this will panic.
pub fn decode_engine_slice<E: Engine, T: AsRef<[u8]>>(
    input: T,
    output: &mut [u8],
    engine: &E,
) -> Result<usize, DecodeError> {
    let input_bytes = input.as_ref();

    engine.decode(
        input_bytes,
        output,
        engine.decoded_length_estimate(input_bytes.len()),
    )
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::{encode::encode_engine_string, tests::assert_encode_sanity};

    use crate::engine::Config;
    use crate::tests::random_engine;
    use rand::{
        distributions::{Distribution, Uniform},
        Rng, SeedableRng,
    };

    #[test]
    fn decode_into_nonempty_vec_doesnt_clobber_existing_prefix() {
        let mut orig_data = Vec::new();
        let mut encoded_data = String::new();
        let mut decoded_with_prefix = Vec::new();
        let mut decoded_without_prefix = Vec::new();
        let mut prefix = Vec::new();

        let prefix_len_range = Uniform::new(0, 1000);
        let input_len_range = Uniform::new(0, 1000);

        let mut rng = rand::rngs::SmallRng::from_entropy();

        for _ in 0..10_000 {
            orig_data.clear();
            encoded_data.clear();
            decoded_with_prefix.clear();
            decoded_without_prefix.clear();
            prefix.clear();

            let input_len = input_len_range.sample(&mut rng);

            for _ in 0..input_len {
                orig_data.push(rng.gen());
            }

            let engine = random_engine(&mut rng);
            encode_engine_string(&orig_data, &mut encoded_data, &engine);
            assert_encode_sanity(&encoded_data, engine.config().encode_padding(), input_len);

            let prefix_len = prefix_len_range.sample(&mut rng);

            // fill the buf with a prefix
            for _ in 0..prefix_len {
                prefix.push(rng.gen());
            }

            decoded_with_prefix.resize(prefix_len, 0);
            decoded_with_prefix.copy_from_slice(&prefix);

            // decode into the non-empty buf
            decode_engine_vec(&encoded_data, &mut decoded_with_prefix, &engine).unwrap();
            // also decode into the empty buf
            decode_engine_vec(&encoded_data, &mut decoded_without_prefix, &engine).unwrap();

            assert_eq!(
                prefix_len + decoded_without_prefix.len(),
                decoded_with_prefix.len()
            );
            assert_eq!(orig_data, decoded_without_prefix);

            // append plain decode onto prefix
            prefix.append(&mut decoded_without_prefix);

            assert_eq!(prefix, decoded_with_prefix);
        }
    }

    #[test]
    fn decode_into_slice_doesnt_clobber_existing_prefix_or_suffix() {
        let mut orig_data = Vec::new();
        let mut encoded_data = String::new();
        let mut decode_buf = Vec::new();
        let mut decode_buf_copy: Vec<u8> = Vec::new();

        let input_len_range = Uniform::new(0, 1000);

        let mut rng = rand::rngs::SmallRng::from_entropy();

        for _ in 0..10_000 {
            orig_data.clear();
            encoded_data.clear();
            decode_buf.clear();
            decode_buf_copy.clear();

            let input_len = input_len_range.sample(&mut rng);

            for _ in 0..input_len {
                orig_data.push(rng.gen());
            }

            let engine = random_engine(&mut rng);
            encode_engine_string(&orig_data, &mut encoded_data, &engine);
            assert_encode_sanity(&encoded_data, engine.config().encode_padding(), input_len);

            // fill the buffer with random garbage, long enough to have some room before and after
            for _ in 0..5000 {
                decode_buf.push(rng.gen());
            }

            // keep a copy for later comparison
            decode_buf_copy.extend(decode_buf.iter());

            let offset = 1000;

            // decode into the non-empty buf
            let decode_bytes_written =
                decode_engine_slice(&encoded_data, &mut decode_buf[offset..], &engine).unwrap();

            assert_eq!(orig_data.len(), decode_bytes_written);
            assert_eq!(
                orig_data,
                &decode_buf[offset..(offset + decode_bytes_written)]
            );
            assert_eq!(&decode_buf_copy[0..offset], &decode_buf[0..offset]);
            assert_eq!(
                &decode_buf_copy[offset + decode_bytes_written..],
                &decode_buf[offset + decode_bytes_written..]
            );
        }
    }

    #[test]
    fn decode_into_slice_fits_in_precisely_sized_slice() {
        let mut orig_data = Vec::new();
        let mut encoded_data = String::new();
        let mut decode_buf = Vec::new();

        let input_len_range = Uniform::new(0, 1000);
        let mut rng = rand::rngs::SmallRng::from_entropy();

        for _ in 0..10_000 {
            orig_data.clear();
            encoded_data.clear();
            decode_buf.clear();

            let input_len = input_len_range.sample(&mut rng);

            for _ in 0..input_len {
                orig_data.push(rng.gen());
            }

            let engine = random_engine(&mut rng);
            encode_engine_string(&orig_data, &mut encoded_data, &engine);
            assert_encode_sanity(&encoded_data, engine.config().encode_padding(), input_len);

            decode_buf.resize(input_len, 0);

            // decode into the non-empty buf
            let decode_bytes_written =
                decode_engine_slice(&encoded_data, &mut decode_buf[..], &engine).unwrap();

            assert_eq!(orig_data.len(), decode_bytes_written);
            assert_eq!(orig_data, decode_buf);
        }
    }
}
<|endoftext|>