<commit_before>use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use snowflake::ProcessUniqueId;

#[derive(Debug,Clone,Copy,Eq,PartialEq,Hash)]
pub struct Subscription(ProcessUniqueId);

impl Subscription {
    fn new() -> Subscription {
        Subscription(ProcessUniqueId::new())
    }
}

type ListenerMap<T> = HashMap<Subscription, Box<Fn(T) + Send + 'static>>;

#[derive(Clone)]
pub struct ListenerSet<T>
    where T: Send
{
    listeners: Arc<Mutex<ListenerMap<T>>>,
}

impl<T> ListenerSet<T> where T: Send + Clone
{
    pub fn new() -> Self {
        ListenerSet { listeners: Arc::new(Mutex::new(ListenerMap::new())) }
    }

    pub fn subscribe<Listener: Fn(T) + Send + 'static>(&self, listener: Listener) -> Subscription {
        let mut acquired_listeners = self.listeners.lock().unwrap();

        let subscription = Subscription::new();
        acquired_listeners.insert(subscription, Box::new(listener));

        subscription
    }

    pub fn unsubscribe(&self, sub: Subscription) {
        let mut acquired_listeners = self.listeners.lock().unwrap();

        // channel will be close here automatically
        acquired_listeners.remove(&sub);
    }

    pub fn notify(&self, payload: &T) {
        let listeners = self.listeners.lock().unwrap();

        for listener in listeners.values() {
            listener(payload.clone())
        }
    }

    #[allow(dead_code)]
    pub fn len(&self) -> usize {
        self.listeners.lock().unwrap().len()
    }
}

#[cfg(test)]
mod tests {
    use super::{ListenerSet};
    use std::sync::mpsc;

    #[test]
    fn test_new_listener_set() {
        let ls = ListenerSet::<()>::new();
        assert_eq!(ls.len(), 0);
    }

    #[test]
    fn test_new_listener_for_chan() {
        let ls = ListenerSet::<bool>::new();

        ls.subscribe(|_e| {});
        assert_eq!(ls.len(), 1);
    }

    #[test]
    fn test_add_listener_to_set() {
        let (tx, rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        ls.subscribe(move |e| tx.send(e).unwrap());
        assert_eq!(ls.len(), 1);

        ls.notify(&true);
        assert_eq!(rx.recv().is_ok(), true);
    }

    #[test]
    fn test_remove_listener_from_set() {
        let (tx, rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        let sub = ls.subscribe(move |e| tx.send(e).unwrap());
        ls.unsubscribe(sub);
        assert_eq!(ls.len(), 0);

        ls.notify(&true);
        assert_eq!(rx.recv().is_err(), true);
    }
}
<commit_msg>Add docs for Subscription<commit_after>use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use snowflake::ProcessUniqueId;

/// A unique identifier returned by `ZooKeeper::add_listener`.
///
/// It can be used to remove a listener with `ZooKeeper::remove_listener`.
#[derive(Debug,Clone,Copy,Eq,PartialEq,Hash)]
pub struct Subscription(ProcessUniqueId);

impl Subscription {
    fn new() -> Subscription {
        Subscription(ProcessUniqueId::new())
    }
}

type ListenerMap<T> = HashMap<Subscription, Box<Fn(T) + Send + 'static>>;

#[derive(Clone)]
pub struct ListenerSet<T>
    where T: Send
{
    listeners: Arc<Mutex<ListenerMap<T>>>,
}

impl<T> ListenerSet<T> where T: Send + Clone
{
    pub fn new() -> Self {
        ListenerSet { listeners: Arc::new(Mutex::new(ListenerMap::new())) }
    }

    pub fn subscribe<Listener: Fn(T) + Send + 'static>(&self, listener: Listener) -> Subscription {
        let mut acquired_listeners = self.listeners.lock().unwrap();

        let subscription = Subscription::new();
        acquired_listeners.insert(subscription, Box::new(listener));

        subscription
    }

    pub fn unsubscribe(&self, sub: Subscription) {
        let mut acquired_listeners = self.listeners.lock().unwrap();

        // channel will be close here automatically
        acquired_listeners.remove(&sub);
    }

    pub fn notify(&self, payload: &T) {
        let listeners = self.listeners.lock().unwrap();

        for listener in listeners.values() {
            listener(payload.clone())
        }
    }

    #[allow(dead_code)]
    pub fn len(&self) -> usize {
        self.listeners.lock().unwrap().len()
    }
}

#[cfg(test)]
mod tests {
    use super::{ListenerSet};
    use std::sync::mpsc;

    #[test]
    fn test_new_listener_set() {
        let ls = ListenerSet::<()>::new();
        assert_eq!(ls.len(), 0);
    }

    #[test]
    fn test_new_listener_for_chan() {
        let ls = ListenerSet::<bool>::new();

        ls.subscribe(|_e| {});
        assert_eq!(ls.len(), 1);
    }

    #[test]
    fn test_add_listener_to_set() {
        let (tx, rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        ls.subscribe(move |e| tx.send(e).unwrap());
        assert_eq!(ls.len(), 1);

        ls.notify(&true);
        assert_eq!(rx.recv().is_ok(), true);
    }

    #[test]
    fn test_remove_listener_from_set() {
        let (tx, rx) = mpsc::channel();
        let ls = ListenerSet::<bool>::new();

        let sub = ls.subscribe(move |e| tx.send(e).unwrap());
        ls.unsubscribe(sub);
        assert_eq!(ls.len(), 0);

        ls.notify(&true);
        assert_eq!(rx.recv().is_err(), true);
    }
}
<|endoftext|>


<commit_before>use time::{Tm, strptime};

use super::{HTTPLogRecord, LogProcessor, HTTPStatus};

pub struct NginxLogParser<B> {
    buffer: B
}

impl<B: Buffer> NginxLogParser<B> {
    pub fn new(buffer: B) -> NginxLogParser<B> {
        NginxLogParser{buffer: buffer}
    }

    pub fn parse<P: LogProcessor>(&mut self, processor: &mut P) {
        for result in self.buffer.lines() {
            let line = result.unwrap();
            let record = create_log_record(line.as_slice());
            processor.process(record);
        }
    }
}

#[inline]
fn create_log_record<'r>(line: &'r str) -> HTTPLogRecord<'r> {
    // TODO: Line parser can be implemented as iterator with a line
    // specification as input
    let (remote_addr, tail) = get_field(line);
    let (user, tail) = get_field(tail);
    let (local_time, tail) = get_local_time(tail);
    let (host, mut tail) = get_field(tail);
    // Pipe
    tail = skip_field(tail);
    let (request_time, tail) = get_request_time(tail);
    let (method, path, tail) = get_method_path(tail);
    let (status, tail) = get_int(tail);
    let (sent_bytes, tail) = get_int(tail);
    let (referer, tail) = get_delimited_field(tail, '"', '"');
    let (user_agent, _) = get_delimited_field(tail, '"', '"');
    HTTPLogRecord{
        remote_addr: remote_addr,
        local_time: local_time,
        host: host,
        user: user,
        request_time: request_time,
        method: method,
        path: path,
        status: HTTPStatus{status: status as u16},
        sent_bytes: sent_bytes,
        referer: referer,
        user_agent: user_agent,
        }
}

#[inline]
fn get_field<'a>(line: &'a str) -> (&'a str, &'a str) {
    let slice = line.trim_left();
    match slice.find(' ') {
        Some(end) => (slice.slice_to(end), slice.slice_from(end + 1)),
        None => fail!("incomplete string: {}", line)
    }
}

#[inline]
fn get_field_or<'a>(line: &'a str, default: &'a str) -> (&'a str, &'a str) {
    let slice = line.trim_left();
    match slice.find(' ') {
        Some(end) => (slice.slice_to(end), slice.slice_from(end + 1)),
        None => (default, "")
    }
}

#[inline]
fn skip_field<'a>(line: &'a str) -> &'a str {
    let slice = line.trim_left();
    match slice.find(' ') {
        Some(end) => slice.slice_from(end + 1),
        None => fail!("incomplete string: {}", line)
    }
}

#[inline]
fn get_delimited_field<'a>(line: &'a str, start_c: char, end_c: char) ->
        (&'a str, &'a str) {
    match line.trim_left().slice_shift_char() {
        (Some(c), slice) if c == start_c =>
            // FIXME: Should we skip escaped end characters? But probably
            // not so important in this case
            match slice.find(end_c) {
                Some(end) => (slice.slice_to(end), slice.slice_from(end + 1)),
                None => fail!("incomplete string: {}", line)
            },
        _ => fail!("incomplete string: {}", line)
    }
}

#[inline]
fn get_local_time<'a>(line: &'a str) -> (Tm, &'a str) {
    let (slice, tail) = get_delimited_field(line, '[', ']');
    match strptime(slice, "%d/%b/%Y:%H:%M:%S %z") {
        Ok(local_time) => (local_time, tail),
        Err(err) => fail!("time parse error for {}: {}", line, err)
    }
}

#[inline]
fn get_request_time<'a>(line: &'a str) -> (u64, &'a str) {
    let (slice, tail) = get_field(line);
    match slice.find('.') {
        Some(pos) => {
            let sec: u64 = from_str(slice.slice_to(pos)).unwrap();
            let msec: u64 = from_str(slice.slice_from(pos + 1)).unwrap();
            (sec * 1000 + msec, tail)
        }
        None => fail!("invalid request time: {}", line)
    }
}

#[inline]
fn get_method_path<'a>(line: &'a str) -> (&'a str, &'a str, &'a str) {
    let (slice, tail) = get_delimited_field(line, '"', '"');
    let (method, req_tail) = get_field_or(slice, "");
    let (path, _) = get_field_or(req_tail, "");
    (method, path, tail)
}

#[inline]
fn get_int<'a>(line: &'a str) -> (u64, &'a str) {
    let (slice, tail) = get_field(line);
    (from_str(slice).unwrap(), tail)
}
<commit_msg>Rename lifetime parameters to 't<commit_after>use time::{Tm, strptime};

use super::{HTTPLogRecord, LogProcessor, HTTPStatus};

pub struct NginxLogParser<B> {
    buffer: B
}

impl<B: Buffer> NginxLogParser<B> {
    pub fn new(buffer: B) -> NginxLogParser<B> {
        NginxLogParser{buffer: buffer}
    }

    pub fn parse<P: LogProcessor>(&mut self, processor: &mut P) {
        for result in self.buffer.lines() {
            let line = result.unwrap();
            let record = create_log_record(line.as_slice());
            processor.process(record);
        }
    }
}

#[inline]
fn create_log_record<'t>(line: &'t str) -> HTTPLogRecord<'t> {
    // TODO: Line parser can be implemented as iterator with a line
    // specification as input
    let (remote_addr, tail) = get_field(line);
    let (user, tail) = get_field(tail);
    let (local_time, tail) = get_local_time(tail);
    let (host, mut tail) = get_field(tail);
    // Pipe
    tail = skip_field(tail);
    let (request_time, tail) = get_request_time(tail);
    let (method, path, tail) = get_method_path(tail);
    let (status, tail) = get_int(tail);
    let (sent_bytes, tail) = get_int(tail);
    let (referer, tail) = get_delimited_field(tail, '"', '"');
    let (user_agent, _) = get_delimited_field(tail, '"', '"');
    HTTPLogRecord{
        remote_addr: remote_addr,
        local_time: local_time,
        host: host,
        user: user,
        request_time: request_time,
        method: method,
        path: path,
        status: HTTPStatus{status: status as u16},
        sent_bytes: sent_bytes,
        referer: referer,
        user_agent: user_agent,
        }
}

#[inline]
fn get_field<'t>(line: &'t str) -> (&'t str, &'t str) {
    let slice = line.trim_left();
    match slice.find(' ') {
        Some(end) => (slice.slice_to(end), slice.slice_from(end + 1)),
        None => fail!("incomplete string: {}", line)
    }
}

#[inline]
fn get_field_or<'t>(line: &'t str, default: &'t str) -> (&'t str, &'t str) {
    let slice = line.trim_left();
    match slice.find(' ') {
        Some(end) => (slice.slice_to(end), slice.slice_from(end + 1)),
        None => (default, "")
    }
}

#[inline]
fn skip_field<'t>(line: &'t str) -> &'t str {
    let slice = line.trim_left();
    match slice.find(' ') {
        Some(end) => slice.slice_from(end + 1),
        None => fail!("incomplete string: {}", line)
    }
}

#[inline]
fn get_delimited_field<'t>(line: &'t str, start_c: char, end_c: char) ->
        (&'t str, &'t str) {
    match line.trim_left().slice_shift_char() {
        (Some(c), slice) if c == start_c =>
            // FIXME: Should we skip escaped end characters? But probably
            // not so important in this case
            match slice.find(end_c) {
                Some(end) => (slice.slice_to(end), slice.slice_from(end + 1)),
                None => fail!("incomplete string: {}", line)
            },
        _ => fail!("incomplete string: {}", line)
    }
}

#[inline]
fn get_local_time<'t>(line: &'t str) -> (Tm, &'t str) {
    let (slice, tail) = get_delimited_field(line, '[', ']');
    match strptime(slice, "%d/%b/%Y:%H:%M:%S %z") {
        Ok(local_time) => (local_time, tail),
        Err(err) => fail!("time parse error for {}: {}", line, err)
    }
}

#[inline]
fn get_request_time<'t>(line: &'t str) -> (u64, &'t str) {
    let (slice, tail) = get_field(line);
    match slice.find('.') {
        Some(pos) => {
            let sec: u64 = from_str(slice.slice_to(pos)).unwrap();
            let msec: u64 = from_str(slice.slice_from(pos + 1)).unwrap();
            (sec * 1000 + msec, tail)
        }
        None => fail!("invalid request time: {}", line)
    }
}

#[inline]
fn get_method_path<'t>(line: &'t str) -> (&'t str, &'t str, &'t str) {
    let (slice, tail) = get_delimited_field(line, '"', '"');
    let (method, req_tail) = get_field_or(slice, "");
    let (path, _) = get_field_or(req_tail, "");
    (method, path, tail)
}

#[inline]
fn get_int<'t>(line: &'t str) -> (u64, &'t str) {
    let (slice, tail) = get_field(line);
    (from_str(slice).unwrap(), tail)
}
<|endoftext|>


<commit_before>#![allow(unused)]

macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => {
        let _ = $target;
        let _ = log!($lvl, $($arg)+);
    }
    ($lvl:expr, $($arg:tt)+) => {
        let _ = $lvl;
        let _ = format_args!($($arg)+);
    }
}
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => { log!($target, $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
<commit_msg>Fix log args<commit_after>#![allow(unused)]

macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => {
        let _ = $target;
        let _ = log!($lvl, $($arg)+);
    }
    ($lvl:expr, $($arg:tt)+) => {
        let _ = $lvl;
        let _ = format_args!($($arg)+);
    }
}
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => { log!(target: $target, "", $($arg)*); }
    ($($arg:tt)*) => { log!("", $($arg)*); }
}
<|endoftext|>


<commit_before>use num::FromPrimitive;
use strum_macros::{Display};
use super::arch::{Arch, Arch32, rva_plus_usize};

// TODO: figure out how to use failure for error (or some other pattern)
#[derive(Debug)]
pub enum Error {
    Foo
}

#[derive(Display)]
pub enum DetectedArch {
    X32,
    X64
}

#[derive(Display)]
pub enum FileFormat {
    Raw,  // shellcode
    PE,
}

#[derive(Display)]
pub enum Platform {
    Windows,
}

struct Section<A: Arch> {
    addr: A::RVA,
    buf: Vec<u8>,
    // TODO
    perms: u8,
    name: String,
}

impl <A: Arch> Section<A> {
    pub fn contains(self: &Section<A>, rva: A::RVA) -> bool {
        if rva < self.addr {
            return false;
        }

        if let Some(max) = rva_plus_usize::<A>(self.addr, self.buf.len()) {
            if rva >= max {
                return false
            }
        } else {
            return false
        }

        true
    }
}

struct LoadedModule<A: Arch> {
    base_address: A::VA,
    sections: Vec<Section<A>>,
}

trait Loader {
    fn get_arch(&self) -> DetectedArch;
    fn get_plat(&self) -> Platform;
    fn get_file_format(&self) -> FileFormat;
    // TODO: compiler?

    fn get_name(&self) -> String {
        return format!("{}/{}/{}", self.get_plat(), self.get_arch(), self.get_file_format());
    }

    fn taste(&self, buf: &[u8]) -> bool;

    fn load32(&self, buf: &[u8]) -> Result<LoadedModule<Arch32>, Error>;
}

// TODO: implement loaders/x32/windows/shellcode
// TODO: implement loaders/x32/windows/pe
// TODO: implement loaders/x64/windows/shellcode
// TODO: implement loaders/x64/windows/pe

/*******

struct ShellcodeLoader {
    arch: Arch,
    plat: Platform,
    file_format: FileFormat,
}

impl ShellcodeLoader {
    pub fn new(arch: impl Arch, plat: Platform, file_format: FileFormat) -> ShellcodeLoader {
        ShellcodeLoader {
            arch,
            plat,
            file_format,
        }
    }
}

impl Loader for ShellcodeLoader {
    fn get_arch(&self) -> impl Arch {
        self.arch
    }

    fn get_plat(&self) -> Platform {
        self.plat
    }

    fn get_file_format(&self) -> FileFormat {
        self.file_format
    }

    fn taste(&self, buf: &[u8]) -> bool {
        true
    }

    /// ```
    /// use lancelot::arch::ARCH32;
    /// use lancelot::loader::{ShellcodeLoader, Platform, FileFormat};
    /// let loader = lancelot::loader::ShellcodeLoader::new(ARCH32, Platform::Windows, FileFormat::Raw);
    /// match loader.load32(b"MZ\x90\x00".as_bytes()) {
    ///   Ok(mod) => {
    ///     assert_eq!(mod.name, "raw");
    ///   },
    ///   Err(e) => panic!(e),
    /// };
    /// ```
    fn load32(&self, buf: &[u8]) -> Result<LoadedModule<Arch32>, Error> {
        if self.arch != ARCH32 {
            panic!("not a 32-bit loader")
        }

        Ok(LoadedModule::<Arch32>{
            base_address: 0x0,
            sections: vec![
                Section::<Arch32> {
                    addr: 0x0,
                    buf: buf.clone(),
                    perms: 0x0, // TODO
                    name: "raw".to_string(),
                }
            ]
        })
    }
}

fn taste(buf: &[u8]) -> Vec<Loader> {
    vec![
        ShellcodeLoader::new(ARCH32, Platform::Windows, FileFormat::Raw),
        ShellcodeLoader::new(ARCH64, Platform::Windows, FileFormat::Raw),
    ].iter()
        .filter(|loader| loader.taste(buf))
        .collect()
}

fn load(buf: &[u8]) -> Result<LoadedModule, Error> {
    Err(Error::Foo)
}

*********/
<commit_msg>loader: implement shellcode loader<commit_after>use num::FromPrimitive;
use strum_macros::{Display};
use super::arch::{Arch, Arch32, rva_plus_usize};

// TODO: figure out how to use failure for error (or some other pattern)
#[derive(Debug)]
pub enum Error {
    Foo
}

#[derive(Display, Clone, Copy)]
pub enum DetectedArch {
    X32,
    X64
}

#[derive(Display, Clone, Copy)]
pub enum FileFormat {
    Raw,  // shellcode
    PE,
}

#[derive(Display, Clone, Copy)]
pub enum Platform {
    Windows,
}

pub struct Section<A: Arch> {
    pub addr: A::RVA,
    pub buf: Vec<u8>,
    // TODO
    pub perms: u8,
    pub name: String,
}

impl <A: Arch> Section<A> {
    pub fn contains(self: &Section<A>, rva: A::RVA) -> bool {
        if rva < self.addr {
            return false;
        }

        if let Some(max) = rva_plus_usize::<A>(self.addr, self.buf.len()) {
            if rva >= max {
                return false
            }
        } else {
            return false
        }

        true
    }
}

pub struct LoadedModule<A: Arch> {
    pub base_address: A::VA,
    pub sections: Vec<Section<A>>,
}

pub trait Loader {
    fn get_arch(&self) -> DetectedArch;
    fn get_plat(&self) -> Platform;
    fn get_file_format(&self) -> FileFormat;

    fn get_name(&self) -> String {
        return format!("{}/{}/{}", self.get_plat(), self.get_arch(), self.get_file_format());
    }

    fn taste(&self, buf: &[u8]) -> bool;

    /// Load the given buffer as a 32-bit module.
    ///
    /// Panics if this isn't a loader that supports 32-bit modules.
    fn load32(&self, buf: &[u8]) -> Result<LoadedModule<Arch32>, Error>;
}

// TODO: implement loaders/x32/windows/pe
// TODO: implement loaders/x64/windows/pe

pub struct ShellcodeLoader {
    arch: DetectedArch,
    plat: Platform,
    file_format: FileFormat,
}

impl ShellcodeLoader {
    pub fn new(arch: DetectedArch, plat: Platform, file_format: FileFormat) -> ShellcodeLoader {
        ShellcodeLoader {
            arch,
            plat,
            file_format,
        }
    }
}

impl Loader for ShellcodeLoader {
    fn get_arch(&self) -> DetectedArch {
        self.arch
    }

    fn get_plat(&self) -> Platform {
        self.plat
    }

    fn get_file_format(&self) -> FileFormat {
        self.file_format
    }

    fn taste(&self, buf: &[u8]) -> bool {
        true
    }

    /// ```
    /// use lancelot::loader::*;
    ///
    /// let loader = lancelot::loader::ShellcodeLoader::new(DetectedArch::X32, Platform::Windows, FileFormat::Raw);
    /// loader.load32(b"MZ\x90\x00").map(|module| {
    ///   assert_eq!(module.base_address,     0x0);
    ///   assert_eq!(module.sections[0].name, "raw");
    /// }).map_err(|e| panic!(e));
    /// ```
    fn load32(&self, buf: &[u8]) -> Result<LoadedModule<Arch32>, Error> {
        if let DetectedArch::X32 = self.arch {
            Ok(LoadedModule::<Arch32>{
                base_address: 0x0,
                sections: vec![
                    Section::<Arch32> {
                        addr: 0x0,
                        buf: buf.to_vec(),
                        perms: 0x0, // TODO
                        name: "raw".to_string(),
                    }
                ]
            })
        } else {
            panic!("not a 32-bit loader")
        }
    }
}

fn taste(buf: &[u8]) -> Vec<Box<dyn Loader>> {
    let mut loaders: Vec<Box<dyn Loader>> = vec![];
    loaders.push(Box::new(ShellcodeLoader::new(DetectedArch::X32, Platform::Windows, FileFormat::Raw)));
    loaders.push(Box::new(ShellcodeLoader::new(DetectedArch::X64, Platform::Windows, FileFormat::Raw)));

    loaders.into_iter()
        .filter(|loader| loader.taste(buf))
        .collect()
}

fn load32(buf: &[u8]) -> Result<LoadedModule<Arch32>, Error> {
    Err(Error::Foo)
}
<|endoftext|>


<commit_before>use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_hir::LangItem;
use rustc_middle::ty::subst::GenericArg;
use rustc_middle::ty::AssocKind;
use rustc_session::config::EntryFnType;
use rustc_span::symbol::Ident;

use crate::prelude::*;

/// Create the `main` function which will initialize the rust runtime and call
/// users main function.
pub(crate) fn maybe_create_entry_wrapper(
    tcx: TyCtxt<'_>,
    module: &mut impl Module,
    unwind_context: &mut UnwindContext,
    is_jit: bool,
) {
    let (main_def_id, is_main_fn) = match tcx.entry_fn(LOCAL_CRATE) {
        Some((def_id, entry_ty)) => (
            def_id.to_def_id(),
            match entry_ty {
                EntryFnType::Main => true,
                EntryFnType::Start => false,
            },
        ),
        None => return,
    };

    let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx);
    if !is_jit && module.get_name(&*tcx.symbol_name(instance).name).is_none() {
        return;
    }

    create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn);

    fn create_entry_fn(
        tcx: TyCtxt<'_>,
        m: &mut impl Module,
        unwind_context: &mut UnwindContext,
        rust_main_def_id: DefId,
        ignore_lang_start_wrapper: bool,
        is_main_fn: bool,
    ) {
        let main_ret_ty = tcx.fn_sig(rust_main_def_id).output();
        // Given that `main()` has no arguments,
        // then its return type cannot have
        // late-bound regions, since late-bound
        // regions must appear in the argument
        // listing.
        let main_ret_ty = tcx.erase_regions(main_ret_ty.no_bound_vars().unwrap());

        let cmain_sig = Signature {
            params: vec![
                AbiParam::new(m.target_config().pointer_type()),
                AbiParam::new(m.target_config().pointer_type()),
            ],
            returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
            call_conv: CallConv::triple_default(m.isa().triple()),
        };

        let cmain_func_id = m.declare_function("main", Linkage::Export, &cmain_sig).unwrap();

        let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);

        let main_name = tcx.symbol_name(instance).name;
        let main_sig = get_function_sig(tcx, m.isa().triple(), instance);
        let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();

        let mut ctx = Context::new();
        ctx.func = Function::with_name_signature(ExternalName::user(0, 0), cmain_sig);
        {
            let mut func_ctx = FunctionBuilderContext::new();
            let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);

            let block = bcx.create_block();
            bcx.switch_to_block(block);
            let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type());
            let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type());

            let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);

            let result = if is_main_fn && ignore_lang_start_wrapper {
                // regular main fn, but ignoring #[lang = "start"] as we are running in the jit
                // FIXME set program arguments somehow
                let call_inst = bcx.ins().call(main_func_ref, &[]);
                let call_results = bcx.func.dfg.inst_results(call_inst).to_owned();

                let termination_trait = tcx.require_lang_item(LangItem::Termination, None);
                let report = tcx
                    .associated_items(termination_trait)
                    .find_by_name_and_kind(
                        tcx,
                        Ident::from_str("report"),
                        AssocKind::Fn,
                        termination_trait,
                    )
                    .unwrap();
                let report = Instance::resolve(
                    tcx,
                    ParamEnv::reveal_all(),
                    report.def_id,
                    tcx.mk_substs([GenericArg::from(main_ret_ty)].iter()),
                )
                .unwrap()
                .unwrap();

                let report_name = tcx.symbol_name(report).name;
                let report_sig = get_function_sig(tcx, m.isa().triple(), report);
                let report_func_id =
                    m.declare_function(report_name, Linkage::Import, &report_sig).unwrap();
                let report_func_ref = m.declare_func_in_func(report_func_id, &mut bcx.func);

                // FIXME do proper abi handling instead of expecting the pass mode to be identical
                // for returns and arguments.
                let report_call_inst = bcx.ins().call(report_func_ref, &call_results);
                bcx.func.dfg.inst_results(report_call_inst)[0]
            } else if is_main_fn {
                let start_def_id = tcx.require_lang_item(LangItem::Start, None);
                let start_instance = Instance::resolve(
                    tcx,
                    ParamEnv::reveal_all(),
                    start_def_id,
                    tcx.intern_substs(&[main_ret_ty.into()]),
                )
                .unwrap()
                .unwrap()
                .polymorphize(tcx);
                let start_func_id = import_function(tcx, m, start_instance);

                let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref);

                let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func);
                let call_inst = bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv]);
                bcx.inst_results(call_inst)[0]
            } else {
                // using user-defined start fn
                let call_inst = bcx.ins().call(main_func_ref, &[arg_argc, arg_argv]);
                bcx.inst_results(call_inst)[0]
            };

            bcx.ins().return_(&[result]);
            bcx.seal_all_blocks();
            bcx.finalize();
        }
        m.define_function(cmain_func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
            .unwrap();
        unwind_context.add_function(cmain_func_id, &ctx, m.isa());
    }
}
<commit_msg>Extend Termination::report return value as necessary<commit_after>use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_hir::LangItem;
use rustc_middle::ty::subst::GenericArg;
use rustc_middle::ty::AssocKind;
use rustc_session::config::EntryFnType;
use rustc_span::symbol::Ident;

use crate::prelude::*;

/// Create the `main` function which will initialize the rust runtime and call
/// users main function.
pub(crate) fn maybe_create_entry_wrapper(
    tcx: TyCtxt<'_>,
    module: &mut impl Module,
    unwind_context: &mut UnwindContext,
    is_jit: bool,
) {
    let (main_def_id, is_main_fn) = match tcx.entry_fn(LOCAL_CRATE) {
        Some((def_id, entry_ty)) => (
            def_id.to_def_id(),
            match entry_ty {
                EntryFnType::Main => true,
                EntryFnType::Start => false,
            },
        ),
        None => return,
    };

    let instance = Instance::mono(tcx, main_def_id).polymorphize(tcx);
    if !is_jit && module.get_name(&*tcx.symbol_name(instance).name).is_none() {
        return;
    }

    create_entry_fn(tcx, module, unwind_context, main_def_id, is_jit, is_main_fn);

    fn create_entry_fn(
        tcx: TyCtxt<'_>,
        m: &mut impl Module,
        unwind_context: &mut UnwindContext,
        rust_main_def_id: DefId,
        ignore_lang_start_wrapper: bool,
        is_main_fn: bool,
    ) {
        let main_ret_ty = tcx.fn_sig(rust_main_def_id).output();
        // Given that `main()` has no arguments,
        // then its return type cannot have
        // late-bound regions, since late-bound
        // regions must appear in the argument
        // listing.
        let main_ret_ty = tcx.erase_regions(main_ret_ty.no_bound_vars().unwrap());

        let cmain_sig = Signature {
            params: vec![
                AbiParam::new(m.target_config().pointer_type()),
                AbiParam::new(m.target_config().pointer_type()),
            ],
            returns: vec![AbiParam::new(m.target_config().pointer_type() /*isize*/)],
            call_conv: CallConv::triple_default(m.isa().triple()),
        };

        let cmain_func_id = m.declare_function("main", Linkage::Export, &cmain_sig).unwrap();

        let instance = Instance::mono(tcx, rust_main_def_id).polymorphize(tcx);

        let main_name = tcx.symbol_name(instance).name;
        let main_sig = get_function_sig(tcx, m.isa().triple(), instance);
        let main_func_id = m.declare_function(main_name, Linkage::Import, &main_sig).unwrap();

        let mut ctx = Context::new();
        ctx.func = Function::with_name_signature(ExternalName::user(0, 0), cmain_sig);
        {
            let mut func_ctx = FunctionBuilderContext::new();
            let mut bcx = FunctionBuilder::new(&mut ctx.func, &mut func_ctx);

            let block = bcx.create_block();
            bcx.switch_to_block(block);
            let arg_argc = bcx.append_block_param(block, m.target_config().pointer_type());
            let arg_argv = bcx.append_block_param(block, m.target_config().pointer_type());

            let main_func_ref = m.declare_func_in_func(main_func_id, &mut bcx.func);

            let result = if is_main_fn && ignore_lang_start_wrapper {
                // regular main fn, but ignoring #[lang = "start"] as we are running in the jit
                // FIXME set program arguments somehow
                let call_inst = bcx.ins().call(main_func_ref, &[]);
                let call_results = bcx.func.dfg.inst_results(call_inst).to_owned();

                let termination_trait = tcx.require_lang_item(LangItem::Termination, None);
                let report = tcx
                    .associated_items(termination_trait)
                    .find_by_name_and_kind(
                        tcx,
                        Ident::from_str("report"),
                        AssocKind::Fn,
                        termination_trait,
                    )
                    .unwrap();
                let report = Instance::resolve(
                    tcx,
                    ParamEnv::reveal_all(),
                    report.def_id,
                    tcx.mk_substs([GenericArg::from(main_ret_ty)].iter()),
                )
                .unwrap()
                .unwrap();

                let report_name = tcx.symbol_name(report).name;
                let report_sig = get_function_sig(tcx, m.isa().triple(), report);
                let report_func_id =
                    m.declare_function(report_name, Linkage::Import, &report_sig).unwrap();
                let report_func_ref = m.declare_func_in_func(report_func_id, &mut bcx.func);

                // FIXME do proper abi handling instead of expecting the pass mode to be identical
                // for returns and arguments.
                let report_call_inst = bcx.ins().call(report_func_ref, &call_results);
                let res = bcx.func.dfg.inst_results(report_call_inst)[0];
                match m.target_config().pointer_type() {
                    types::I32 => res,
                    types::I64 => bcx.ins().sextend(types::I64, res),
                    _ => unimplemented!("16bit systems are not yet supported"),
                }
            } else if is_main_fn {
                let start_def_id = tcx.require_lang_item(LangItem::Start, None);
                let start_instance = Instance::resolve(
                    tcx,
                    ParamEnv::reveal_all(),
                    start_def_id,
                    tcx.intern_substs(&[main_ret_ty.into()]),
                )
                .unwrap()
                .unwrap()
                .polymorphize(tcx);
                let start_func_id = import_function(tcx, m, start_instance);

                let main_val = bcx.ins().func_addr(m.target_config().pointer_type(), main_func_ref);

                let func_ref = m.declare_func_in_func(start_func_id, &mut bcx.func);
                let call_inst = bcx.ins().call(func_ref, &[main_val, arg_argc, arg_argv]);
                bcx.inst_results(call_inst)[0]
            } else {
                // using user-defined start fn
                let call_inst = bcx.ins().call(main_func_ref, &[arg_argc, arg_argv]);
                bcx.inst_results(call_inst)[0]
            };

            bcx.ins().return_(&[result]);
            bcx.seal_all_blocks();
            bcx.finalize();
        }
        m.define_function(cmain_func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
            .unwrap();
        unwind_context.add_function(cmain_func_id, &ctx, m.isa());
    }
}
<|endoftext|>


<commit_before>use crate::de::{Event, Input};
use crate::error::{self, Result};
use crate::libyaml::error::Mark;
use crate::libyaml::parser::{Event as YamlEvent, Parser};
use std::borrow::Cow;
use std::collections::BTreeMap;

pub(crate) struct Loader {
    events: Vec<(Event, Mark)>,
    /// Map from alias id to index in events.
    aliases: BTreeMap<usize, usize>,
    /// Map from start index to number of events.
    document_lengths: BTreeMap<usize, usize>,
}

impl Loader {
    pub fn new(input: Input) -> Result<Self> {
        let mut buffer;
        let input = match input {
            Input::Str(s) => s.as_bytes(),
            Input::Slice(bytes) => bytes,
            Input::Read(mut rdr) => {
                buffer = Vec::new();
                rdr.read_to_end(&mut buffer).map_err(error::io)?;
                &buffer
            }
            Input::Iterable(_) | Input::Document(_) => unreachable!(),
            Input::Fail(err) => return Err(error::shared(err)),
        };

        let mut parser = Parser::new(Cow::Borrowed(input));
        let mut current_document_start = 0;
        let mut anchors = BTreeMap::new();
        let mut loader = Loader {
            events: Vec::new(),
            aliases: BTreeMap::new(),
            document_lengths: BTreeMap::new(),
        };

        loop {
            let (event, mark) = parser.next()?;
            let event = match event {
                YamlEvent::StreamStart => continue,
                YamlEvent::StreamEnd => break,
                YamlEvent::DocumentStart => {
                    current_document_start = loader.events.len();
                    continue;
                }
                YamlEvent::DocumentEnd => {
                    let len = loader.events.len() - current_document_start;
                    loader.document_lengths.insert(current_document_start, len);
                    current_document_start = loader.events.len();
                    continue;
                }
                YamlEvent::Alias(alias) => match anchors.get(&alias) {
                    Some(id) => Event::Alias(*id),
                    None => return Err(error::unknown_anchor(mark)),
                },
                YamlEvent::Scalar(scalar) => {
                    if let Some(anchor) = scalar.anchor {
                        let id = anchors.len();
                        anchors.insert(anchor, id);
                        loader.aliases.insert(id, loader.events.len());
                    }
                    Event::Scalar(scalar.value, scalar.style, scalar.tag)
                }
                YamlEvent::SequenceStart(sequence_start) => {
                    if let Some(anchor) = sequence_start.anchor {
                        let id = anchors.len();
                        anchors.insert(anchor, id);
                        loader.aliases.insert(id, loader.events.len());
                    }
                    Event::SequenceStart
                }
                YamlEvent::SequenceEnd => Event::SequenceEnd,
                YamlEvent::MappingStart(mapping_start) => {
                    if let Some(anchor) = mapping_start.anchor {
                        let id = anchors.len();
                        anchors.insert(anchor, id);
                        loader.aliases.insert(id, loader.events.len());
                    }
                    Event::MappingStart
                }
                YamlEvent::MappingEnd => Event::MappingEnd,
            };
            loader.events.push((event, mark));
        }

        Ok(loader)
    }

    pub fn event(&self, pos: usize) -> Option<(&Event, Mark)> {
        self.events.get(pos).map(|(event, mark)| (event, *mark))
    }

    pub fn alias(&self, id: usize) -> Option<usize> {
        self.aliases.get(&id).copied()
    }

    pub fn document_len(&self, start: usize) -> usize {
        *self.document_lengths.get(&start).unwrap_or(&0)
    }
}
<commit_msg>Store buffer read from reader as Vec in parser<commit_after>use crate::de::{Event, Input};
use crate::error::{self, Result};
use crate::libyaml::error::Mark;
use crate::libyaml::parser::{Event as YamlEvent, Parser};
use std::borrow::Cow;
use std::collections::BTreeMap;

pub(crate) struct Loader {
    events: Vec<(Event, Mark)>,
    /// Map from alias id to index in events.
    aliases: BTreeMap<usize, usize>,
    /// Map from start index to number of events.
    document_lengths: BTreeMap<usize, usize>,
}

impl Loader {
    pub fn new(input: Input) -> Result<Self> {
        let input = match input {
            Input::Str(s) => Cow::Borrowed(s.as_bytes()),
            Input::Slice(bytes) => Cow::Borrowed(bytes),
            Input::Read(mut rdr) => {
                let mut buffer = Vec::new();
                rdr.read_to_end(&mut buffer).map_err(error::io)?;
                Cow::Owned(buffer)
            }
            Input::Iterable(_) | Input::Document(_) => unreachable!(),
            Input::Fail(err) => return Err(error::shared(err)),
        };

        let mut parser = Parser::new(input);
        let mut current_document_start = 0;
        let mut anchors = BTreeMap::new();
        let mut loader = Loader {
            events: Vec::new(),
            aliases: BTreeMap::new(),
            document_lengths: BTreeMap::new(),
        };

        loop {
            let (event, mark) = parser.next()?;
            let event = match event {
                YamlEvent::StreamStart => continue,
                YamlEvent::StreamEnd => break,
                YamlEvent::DocumentStart => {
                    current_document_start = loader.events.len();
                    continue;
                }
                YamlEvent::DocumentEnd => {
                    let len = loader.events.len() - current_document_start;
                    loader.document_lengths.insert(current_document_start, len);
                    current_document_start = loader.events.len();
                    continue;
                }
                YamlEvent::Alias(alias) => match anchors.get(&alias) {
                    Some(id) => Event::Alias(*id),
                    None => return Err(error::unknown_anchor(mark)),
                },
                YamlEvent::Scalar(scalar) => {
                    if let Some(anchor) = scalar.anchor {
                        let id = anchors.len();
                        anchors.insert(anchor, id);
                        loader.aliases.insert(id, loader.events.len());
                    }
                    Event::Scalar(scalar.value, scalar.style, scalar.tag)
                }
                YamlEvent::SequenceStart(sequence_start) => {
                    if let Some(anchor) = sequence_start.anchor {
                        let id = anchors.len();
                        anchors.insert(anchor, id);
                        loader.aliases.insert(id, loader.events.len());
                    }
                    Event::SequenceStart
                }
                YamlEvent::SequenceEnd => Event::SequenceEnd,
                YamlEvent::MappingStart(mapping_start) => {
                    if let Some(anchor) = mapping_start.anchor {
                        let id = anchors.len();
                        anchors.insert(anchor, id);
                        loader.aliases.insert(id, loader.events.len());
                    }
                    Event::MappingStart
                }
                YamlEvent::MappingEnd => Event::MappingEnd,
            };
            loader.events.push((event, mark));
        }

        Ok(loader)
    }

    pub fn event(&self, pos: usize) -> Option<(&Event, Mark)> {
        self.events.get(pos).map(|(event, mark)| (event, *mark))
    }

    pub fn alias(&self, id: usize) -> Option<usize> {
        self.aliases.get(&id).copied()
    }

    pub fn document_len(&self, start: usize) -> usize {
        *self.document_lengths.get(&start).unwrap_or(&0)
    }
}
<|endoftext|>


<commit_before>macro_rules! jump_take(
    (@unwrap $tape:ident, $position:ident, $offset:expr) => ({
        $tape.jump($position + $offset as u64)?;
        $tape.take()?
    });
    (@unwrap $tape:ident, $position:ident, $count:expr, $offsets:expr) => (
        jump_take!(@unwrap $tape, $position, $count, i => $offsets[i])
    );
    (@unwrap $tape:ident, $position:ident, $count:expr, $i:ident => $iterator:expr) => ({
        let mut values = Vec::with_capacity($count as usize);
        for $i in 0..($count as usize) {
            $tape.jump($position + $iterator as u64)?;
            values.push($tape.take()?);
        }
        values
    });
    ($tape:ident, $position:ident, $offset:expr) => (
        Ok(jump_take!(@unwrap $tape, $position, $offset))
    );
    ($tape:ident, $position:ident, $count:expr, $offsets:expr) => (
        Ok(jump_take!(@unwrap $tape, $position, $count, i => $offsets[i]))
    );
    ($tape:ident, $position:ident, $count:expr, $i:ident => $iterator:expr) => (
        Ok(jump_take!(@unwrap $tape, $position, $count, $i => $iterator))
    );
);

macro_rules! jump_take_given(
    (@unwrap $tape:ident, $position:ident, $offset:expr, $parameter:expr) => ({
        $tape.jump($position + $offset as u64)?;
        $tape.take_given($parameter)?
    });
    (@unwrap $tape:ident, $position:ident, $count:expr, $offsets:expr, $parameter:expr) => (
        jump_take_given!(@unwrap $tape, $position, $count, i => $offsets[i], $parameter)
    );
    (@unwrap $tape:ident, $position:ident, $count:expr, $i:ident => $iterator:expr,
     $parameter:expr) => ({
        let mut values = Vec::with_capacity($count as usize);
        for $i in 0..($count as usize) {
            $tape.jump($position + $iterator as u64)?;
            values.push($tape.take_given($parameter)?);
        }
        values
    });
    ($tape:ident, $position:ident, $offset:expr, $parameter:expr) => (
        Ok(jump_take_given!(@unwrap $tape, $position, $offset, $parameter))
    );
    ($tape:ident, $position:ident, $count:expr, $offsets:expr, $parameter:expr) => (
        Ok(jump_take_given!(@unwrap $tape, $position, $count, i => $offsets[i], $parameter))
    );
);

macro_rules! jump_take_maybe(
    (@unwrap $tape:ident, $position:ident, $offset:expr) => (
        if $offset > 0 {
            $tape.jump($position + $offset as u64)?;
            Some($tape.take()?)
        } else {
            None
        }
    );
    (@unwrap $tape:ident, $position:ident, $count:expr, $i:ident => $iterator:expr) => ({
        let mut values = Vec::with_capacity($count as usize);
        for $i in 0..($count as usize) {
            if $iterator > 0 {
                $tape.jump($position + $iterator as u64)?;
                values.push(Some($tape.take()?));
            } else {
                values.push(None);
            }
        }
        values
    });
    ($tape:ident, $position:ident, $offset:expr) => (
        Ok(jump_take_maybe!(@unwrap $tape, $position, $offset))
    );
    ($tape:ident, $position:ident, $count:expr, $offsets:expr) => (
        Ok(jump_take_maybe!(@unwrap $tape, $position, $count, i => $offsets[i]))
    );
);

macro_rules! raise(
    ($message:expr) => (return Err(::truetype::Error::new(::std::io::ErrorKind::Other, $message)));
);

macro_rules! table {
    ($(#[$attribute:meta])* pub $name:ident {
        $($field:ident ($($kind:tt)+) $(= $value:block)* $(|$($argument:tt),+| $body:block)*,)*
    }) => (
        table! { @define $(#[$attribute])* pub $name { $($field ($($kind)+),)* } }
        table! {
            @implement
            pub $name { $($field ($($kind)+) [$($value)*] $(|$($argument),+| $body)*,)* }
        }
    );
    (@position $(#[$attribute:meta])* pub $name:ident {
        $($field:ident ($($kind:tt)+) $(= $value:block)* $(|$($argument:tt),+| $body:block)*,)*
    }) => (
        table! { @define $(#[$attribute])* pub $name { $($field ($($kind)+),)* } }
        table! {
            @implement @position
            pub $name { $($field ($($kind)+) [$($value)*] $(|$($argument),+| $body)*,)* }
        }
    );
    (@define $(#[$attribute:meta])* pub $name:ident { $($field:ident ($kind:ty),)* }) => (
        $(#[$attribute])*
        #[derive(Clone, Debug)]
        pub struct $name { $(pub $field: $kind,)* }
    );
    (@implement pub $name:ident {
        $($field:ident ($($kind:tt)+) [$($value:block)*] $(|$($argument:tt),+| $body:block)*,)*
    }) => (
        impl ::truetype::Value for $name {
            fn read<T: ::truetype::Tape>(tape: &mut T) -> ::truetype::Result<Self> {
                let mut table: $name = unsafe { ::std::mem::zeroed() };
                $({
                    let value = table!(@read $name, table, tape [] [$($kind)+] [$($value)*]
                                       $(|$($argument),+| $body)*);
                    ::std::mem::forget(::std::mem::replace(&mut table.$field, value));
                })*
                Ok(table)
            }
        }
    );
    (@implement @position pub $name:ident {
        $($field:ident ($($kind:tt)+) [$($value:block)*] $(|$($argument:tt),+| $body:block)*,)*
    }) => (
        impl ::truetype::Value for $name {
            fn read<T: ::truetype::Tape>(tape: &mut T) -> ::truetype::Result<Self> {
                let position = tape.position()?;
                let mut table: $name = unsafe { ::std::mem::zeroed() };
                $({
                    let value = table!(@read $name, table, tape [position] [$($kind)+] [$($value)*]
                                       $(|$($argument),+| $body)*);
                    ::std::mem::forget(::std::mem::replace(&mut table.$field, value));
                })*
                Ok(table)
            }
        }
    );
    (@read $name:ident, $this:ident, $tape:ident [$($position:tt)*] [$kind:ty] []) => (
        $tape.take()?
    );
    (@read $name:ident, $this:ident, $tape:ident [$($position:tt)*] [$kind:ty]
     [$value:block]) => ({
        let value = $tape.take()?;
        if value != $value {
            raise!("found a malformed or unsupported table");
        }
        value
    });
    (@read $name:ident, $this:ident, $tape:ident [] [$kind:ty] []
     |$this_:pat, $tape_:pat| $body:block) => ({
        #[inline(always)]
        fn read<T: ::truetype::Tape>($this_: &$name, $tape_: &mut T)
                                     -> ::truetype::Result<$kind> $body

        read(&$this, $tape)?
    });
    (@read $name:ident, $this:ident, $tape:ident [$position:ident] [$kind:ty] []
     |$this_:pat, $tape_:pat, $position_:pat| $body:block) => ({
        #[inline(always)]
        fn read<T: ::truetype::Tape>($this_: &$name, $tape_: &mut T, $position_: u64)
                                     -> ::truetype::Result<$kind> $body
        read(&$this, $tape, $position)?
    });
}
<commit_msg>Consistently use “unknown” instead of “unsupported”<commit_after>macro_rules! jump_take(
    (@unwrap $tape:ident, $position:ident, $offset:expr) => ({
        $tape.jump($position + $offset as u64)?;
        $tape.take()?
    });
    (@unwrap $tape:ident, $position:ident, $count:expr, $offsets:expr) => (
        jump_take!(@unwrap $tape, $position, $count, i => $offsets[i])
    );
    (@unwrap $tape:ident, $position:ident, $count:expr, $i:ident => $iterator:expr) => ({
        let mut values = Vec::with_capacity($count as usize);
        for $i in 0..($count as usize) {
            $tape.jump($position + $iterator as u64)?;
            values.push($tape.take()?);
        }
        values
    });
    ($tape:ident, $position:ident, $offset:expr) => (
        Ok(jump_take!(@unwrap $tape, $position, $offset))
    );
    ($tape:ident, $position:ident, $count:expr, $offsets:expr) => (
        Ok(jump_take!(@unwrap $tape, $position, $count, i => $offsets[i]))
    );
    ($tape:ident, $position:ident, $count:expr, $i:ident => $iterator:expr) => (
        Ok(jump_take!(@unwrap $tape, $position, $count, $i => $iterator))
    );
);

macro_rules! jump_take_given(
    (@unwrap $tape:ident, $position:ident, $offset:expr, $parameter:expr) => ({
        $tape.jump($position + $offset as u64)?;
        $tape.take_given($parameter)?
    });
    (@unwrap $tape:ident, $position:ident, $count:expr, $offsets:expr, $parameter:expr) => (
        jump_take_given!(@unwrap $tape, $position, $count, i => $offsets[i], $parameter)
    );
    (@unwrap $tape:ident, $position:ident, $count:expr, $i:ident => $iterator:expr,
     $parameter:expr) => ({
        let mut values = Vec::with_capacity($count as usize);
        for $i in 0..($count as usize) {
            $tape.jump($position + $iterator as u64)?;
            values.push($tape.take_given($parameter)?);
        }
        values
    });
    ($tape:ident, $position:ident, $offset:expr, $parameter:expr) => (
        Ok(jump_take_given!(@unwrap $tape, $position, $offset, $parameter))
    );
    ($tape:ident, $position:ident, $count:expr, $offsets:expr, $parameter:expr) => (
        Ok(jump_take_given!(@unwrap $tape, $position, $count, i => $offsets[i], $parameter))
    );
);

macro_rules! jump_take_maybe(
    (@unwrap $tape:ident, $position:ident, $offset:expr) => (
        if $offset > 0 {
            $tape.jump($position + $offset as u64)?;
            Some($tape.take()?)
        } else {
            None
        }
    );
    (@unwrap $tape:ident, $position:ident, $count:expr, $i:ident => $iterator:expr) => ({
        let mut values = Vec::with_capacity($count as usize);
        for $i in 0..($count as usize) {
            if $iterator > 0 {
                $tape.jump($position + $iterator as u64)?;
                values.push(Some($tape.take()?));
            } else {
                values.push(None);
            }
        }
        values
    });
    ($tape:ident, $position:ident, $offset:expr) => (
        Ok(jump_take_maybe!(@unwrap $tape, $position, $offset))
    );
    ($tape:ident, $position:ident, $count:expr, $offsets:expr) => (
        Ok(jump_take_maybe!(@unwrap $tape, $position, $count, i => $offsets[i]))
    );
);

macro_rules! raise(
    ($message:expr) => (return Err(::truetype::Error::new(::std::io::ErrorKind::Other, $message)));
);

macro_rules! table {
    ($(#[$attribute:meta])* pub $name:ident {
        $($field:ident ($($kind:tt)+) $(= $value:block)* $(|$($argument:tt),+| $body:block)*,)*
    }) => (
        table! { @define $(#[$attribute])* pub $name { $($field ($($kind)+),)* } }
        table! {
            @implement
            pub $name { $($field ($($kind)+) [$($value)*] $(|$($argument),+| $body)*,)* }
        }
    );
    (@position $(#[$attribute:meta])* pub $name:ident {
        $($field:ident ($($kind:tt)+) $(= $value:block)* $(|$($argument:tt),+| $body:block)*,)*
    }) => (
        table! { @define $(#[$attribute])* pub $name { $($field ($($kind)+),)* } }
        table! {
            @implement @position
            pub $name { $($field ($($kind)+) [$($value)*] $(|$($argument),+| $body)*,)* }
        }
    );
    (@define $(#[$attribute:meta])* pub $name:ident { $($field:ident ($kind:ty),)* }) => (
        $(#[$attribute])*
        #[derive(Clone, Debug)]
        pub struct $name { $(pub $field: $kind,)* }
    );
    (@implement pub $name:ident {
        $($field:ident ($($kind:tt)+) [$($value:block)*] $(|$($argument:tt),+| $body:block)*,)*
    }) => (
        impl ::truetype::Value for $name {
            fn read<T: ::truetype::Tape>(tape: &mut T) -> ::truetype::Result<Self> {
                let mut table: $name = unsafe { ::std::mem::zeroed() };
                $({
                    let value = table!(@read $name, table, tape [] [$($kind)+] [$($value)*]
                                       $(|$($argument),+| $body)*);
                    ::std::mem::forget(::std::mem::replace(&mut table.$field, value));
                })*
                Ok(table)
            }
        }
    );
    (@implement @position pub $name:ident {
        $($field:ident ($($kind:tt)+) [$($value:block)*] $(|$($argument:tt),+| $body:block)*,)*
    }) => (
        impl ::truetype::Value for $name {
            fn read<T: ::truetype::Tape>(tape: &mut T) -> ::truetype::Result<Self> {
                let position = tape.position()?;
                let mut table: $name = unsafe { ::std::mem::zeroed() };
                $({
                    let value = table!(@read $name, table, tape [position] [$($kind)+] [$($value)*]
                                       $(|$($argument),+| $body)*);
                    ::std::mem::forget(::std::mem::replace(&mut table.$field, value));
                })*
                Ok(table)
            }
        }
    );
    (@read $name:ident, $this:ident, $tape:ident [$($position:tt)*] [$kind:ty] []) => (
        $tape.take()?
    );
    (@read $name:ident, $this:ident, $tape:ident [$($position:tt)*] [$kind:ty]
     [$value:block]) => ({
        let value = $tape.take()?;
        if value != $value {
            raise!("found a malformed or unknown table");
        }
        value
    });
    (@read $name:ident, $this:ident, $tape:ident [] [$kind:ty] []
     |$this_:pat, $tape_:pat| $body:block) => ({
        #[inline(always)]
        fn read<T: ::truetype::Tape>($this_: &$name, $tape_: &mut T)
                                     -> ::truetype::Result<$kind> $body

        read(&$this, $tape)?
    });
    (@read $name:ident, $this:ident, $tape:ident [$position:ident] [$kind:ty] []
     |$this_:pat, $tape_:pat, $position_:pat| $body:block) => ({
        #[inline(always)]
        fn read<T: ::truetype::Tape>($this_: &$name, $tape_: &mut T, $position_: u64)
                                     -> ::truetype::Result<$kind> $body
        read(&$this, $tape, $position)?
    });
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// The standard logging macro.
///
/// This macro will generically log with the specified `LogLevel` and `format!`
/// based argument list.
///
/// The `log_level` cfg can be used to statically disable logging at various
/// levels.
#[macro_export]
macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
        static LOC: $crate::LogLocation = $crate::LogLocation {
            __line: line!(),
            __file: file!(),
            __module_path: module_path!(),
        };
        let lvl = $lvl;
        if !cfg!(log_level = "off") &&
                (lvl <= $crate::LogLevel::Error || !cfg!(log_level = "error")) &&
                (lvl <= $crate::LogLevel::Warn || !cfg!(log_level = "warn")) &&
                (lvl <= $crate::LogLevel::Debug || !cfg!(log_level = "debug")) &&
                (lvl <= $crate::LogLevel::Info || !cfg!(log_level = "info")) &&
                lvl <= $crate::max_log_level() {
            $crate::__log(lvl, $target, &LOC, format_args!($($arg)+))
        }
    });
    ($lvl:expr, $($arg:tt)+) => (log!(target: module_path!(), $lvl, $($arg)+))
}

/// Logs a message at the error level.
///
/// Logging at this level is disabled if the `log_level = "off"` cfg is
/// present.
#[macro_export]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Error, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Error, $($arg)*);
    )
}

/// Logs a message at the warn level.
///
/// Logging at this level is disabled if any of the following cfgs are present:
/// `log_level = "off"` or `log_level = "error"`.
#[macro_export]
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Warn, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Warn, $($arg)*);
    )
}

/// Logs a message at the info level.
///
/// Logging at this level is disabled if any of the following cfgs are present:
/// `log_level = "off"`, `log_level = "error"`, or
/// `log_level = "warn"`.
#[macro_export]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Info, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Info, $($arg)*);
    )
}

/// Logs a message at the debug level.
///
/// Logging at this level is disabled if any of the following cfgs are present:
/// `log_level = "off"`, `log_level = "error"`, `log_level = "warn"`,
/// or `log_level = "info"`.
#[macro_export]
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Debug, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Debug, $($arg)*);
    )
}

/// Logs a message at the trace level.
///
/// Logging at this level is disabled if any of the following cfgs are present:
/// `log_level = "off"`, `log_level = "error"`, `log_level = "warn"`,
/// `log_level = "info"`, or `log_level = "debug"`.
#[macro_export]
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Trace, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Trace, $($arg)*);
    )
}

/// Determines if a message logged at the specified level in that module will
/// be logged.
///
/// This can be used to avoid expensive computation of log message arguments if
/// the message would be ignored anyway.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::LogLevel::Debug;
///
/// # fn foo() {
/// if log_enabled!(Debug) {
///     debug!("expensive debug data: {}", expensive_call());
/// }
/// # }
/// # fn expensive_call() -> u32 { 0 }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! log_enabled {
    (target: $target:expr, $lvl:expr) => ({
        let lvl = $lvl;
        !cfg!(log_level = "off") &&
            (lvl <= $crate::LogLevel::Error || !cfg!(log_level = "error")) &&
            (lvl <= $crate::LogLevel::Warn || !cfg!(log_level = "warn")) &&
            (lvl <= $crate::LogLevel::Debug || !cfg!(log_level = "debug")) &&
            (lvl <= $crate::LogLevel::Info || !cfg!(log_level = "info")) &&
            lvl <= $crate::max_log_level() &&
            $crate::__enabled(lvl, $target)
    });
    ($lvl:expr) => (log_enabled!(target: module_path!(), $lvl))
}
<commit_msg>Disable dead code warnings for LOC static<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// The standard logging macro.
///
/// This macro will generically log with the specified `LogLevel` and `format!`
/// based argument list.
///
/// The `log_level` cfg can be used to statically disable logging at various
/// levels.
#[macro_export]
macro_rules! log {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({
        static _LOC: $crate::LogLocation = $crate::LogLocation {
            __line: line!(),
            __file: file!(),
            __module_path: module_path!(),
        };
        let lvl = $lvl;
        if !cfg!(log_level = "off") &&
                (lvl <= $crate::LogLevel::Error || !cfg!(log_level = "error")) &&
                (lvl <= $crate::LogLevel::Warn || !cfg!(log_level = "warn")) &&
                (lvl <= $crate::LogLevel::Debug || !cfg!(log_level = "debug")) &&
                (lvl <= $crate::LogLevel::Info || !cfg!(log_level = "info")) &&
                lvl <= $crate::max_log_level() {
            $crate::__log(lvl, $target, &_LOC, format_args!($($arg)+))
        }
    });
    ($lvl:expr, $($arg:tt)+) => (log!(target: module_path!(), $lvl, $($arg)+))
}

/// Logs a message at the error level.
///
/// Logging at this level is disabled if the `log_level = "off"` cfg is
/// present.
#[macro_export]
macro_rules! error {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Error, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Error, $($arg)*);
    )
}

/// Logs a message at the warn level.
///
/// Logging at this level is disabled if any of the following cfgs are present:
/// `log_level = "off"` or `log_level = "error"`.
#[macro_export]
macro_rules! warn {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Warn, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Warn, $($arg)*);
    )
}

/// Logs a message at the info level.
///
/// Logging at this level is disabled if any of the following cfgs are present:
/// `log_level = "off"`, `log_level = "error"`, or
/// `log_level = "warn"`.
#[macro_export]
macro_rules! info {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Info, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Info, $($arg)*);
    )
}

/// Logs a message at the debug level.
///
/// Logging at this level is disabled if any of the following cfgs are present:
/// `log_level = "off"`, `log_level = "error"`, `log_level = "warn"`,
/// or `log_level = "info"`.
#[macro_export]
macro_rules! debug {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Debug, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Debug, $($arg)*);
    )
}

/// Logs a message at the trace level.
///
/// Logging at this level is disabled if any of the following cfgs are present:
/// `log_level = "off"`, `log_level = "error"`, `log_level = "warn"`,
/// `log_level = "info"`, or `log_level = "debug"`.
#[macro_export]
macro_rules! trace {
    (target: $target:expr, $($arg:tt)*) => (
        log!(target: $target, $crate::LogLevel::Trace, $($arg)*);
    );
    ($($arg:tt)*) => (
        log!($crate::LogLevel::Trace, $($arg)*);
    )
}

/// Determines if a message logged at the specified level in that module will
/// be logged.
///
/// This can be used to avoid expensive computation of log message arguments if
/// the message would be ignored anyway.
///
/// # Examples
///
/// ```rust
/// # #[macro_use]
/// # extern crate log;
/// use log::LogLevel::Debug;
///
/// # fn foo() {
/// if log_enabled!(Debug) {
///     debug!("expensive debug data: {}", expensive_call());
/// }
/// # }
/// # fn expensive_call() -> u32 { 0 }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! log_enabled {
    (target: $target:expr, $lvl:expr) => ({
        let lvl = $lvl;
        !cfg!(log_level = "off") &&
            (lvl <= $crate::LogLevel::Error || !cfg!(log_level = "error")) &&
            (lvl <= $crate::LogLevel::Warn || !cfg!(log_level = "warn")) &&
            (lvl <= $crate::LogLevel::Debug || !cfg!(log_level = "debug")) &&
            (lvl <= $crate::LogLevel::Info || !cfg!(log_level = "info")) &&
            lvl <= $crate::max_log_level() &&
            $crate::__enabled(lvl, $target)
    });
    ($lvl:expr) => (log_enabled!(target: module_path!(), $lvl))
}
<|endoftext|>


<commit_before>#![cfg_attr(test, allow(dead_code))]
#![allow(dead_code)]

mod attacks;
mod byte_conversion;
mod byte_manipulation;
mod byte_utilities;
mod english_scoring;
mod general_utilities;
mod key;

fn problem_3() {
	// http://cryptopals.com/sets/1/challenges/3/
	use byte_conversion::*;
	let encoded = hex_to_bytes("1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736");

	let (top_score, top_decode, top_x) = attacks::guess_single_xor_char_decode(&encoded);

	println!("Best guess: `{}`, with a score of {}, using character {}.", bytes_to_readable_text(&top_decode), top_score, top_x);
}

fn problem_4() {
	// http://cryptopals.com/sets/1/challenges/4/

	use byte_conversion::*;

	let s = general_utilities::read_file("C:\\Users\\Topher\\Dropbox\\Public\\Programming\\Matasano\\matasano-crypto-challenges\\res\\4.txt");

	let mut top_score = 0;
	let mut top_decode = vec![];
    for line in s.split("\n") {
    	let (score, decoded, _) = attacks::guess_single_xor_char_decode(&hex_to_bytes(line));

		if score > top_score {
			top_score = score;
			top_decode = decoded.clone();
		}

    }

    println!("\n\n\n{} -      `{}`", top_score, bytes_to_readable_text(&top_decode));
}

fn problem_6() {
	// http://cryptopals.com/sets/1/challenges/6/

	use byte_conversion::*;
	use byte_manipulation::*;
	use byte_utilities::*;
	use english_scoring::*;
	use general_utilities::*;
	use key::*;

	let file_data = general_utilities::read_file("C:\\Users\\Topher\\Dropbox\\Public\\Programming\\Matasano\\matasano-crypto-challenges\\res\\6.txt");
	let data_bytes = base64_to_bytes(&file_data);

	// For each KEYSIZE, take the first KEYSIZE worth of bytes, and the second KEYSIZE worth of bytes,
	// and find the edit distance between them. Normalize this result by dividing by KEYSIZE.
	// The KEYSIZE with the smallest normalized edit distance is probably the key.
	//  You could proceed perhaps with the smallest 2-3 KEYSIZE values. Or take 4 KEYSIZE blocks instead of 2 and average the distances.
	let mut keysize_points = Vec::new();
	for keysize in 2..41 {
		if data_bytes.len() < keysize * 4 {
			continue;
		}

		let chunks: Vec<Vec<u8>> = data_bytes.chunks(keysize).map(|x| slice_to_vec(x)).collect();
		assert!(chunks.len() >= 4);

		let distance1 = hamming_distance(&chunks[0], &chunks[1]);
		let distance2 = hamming_distance(&chunks[1], &chunks[2]);
		let distance3 = hamming_distance(&chunks[2], &chunks[3]);
		let distance4 = hamming_distance(&chunks[3], &chunks[4]);
		let avg_distance: f32 = (distance1 + distance2 + distance3 + distance4) as f32 / 4.0;
		let normalized_distance = avg_distance / keysize as f32;

		let pair = (keysize, normalized_distance);
		keysize_points.push(pair);
	}

	// Find the 4 best keysize values
	keysize_points.sort_by(|a, b| {
		use std::cmp::Ordering::*;

		let (_, x): (_, f32) = *a;
		let (_, y): (_, f32) = *b;

		// f32s require partial cmp
		x.partial_cmp(&y).unwrap_or(Equal)
	});

	println!("{:?}", keysize_points);

	for y in 0..10 {
		let (best_keysize, _) = keysize_points[11-y];
		println!("{:?}", best_keysize);

		// Now that you probably know the KEYSIZE: break the ciphertext into blocks of KEYSIZE length.
		let blocks: Vec<Vec<u8>> = data_bytes
			.chunks(best_keysize)
			.map(|x| slice_to_vec(x))
			.collect();

		// Now transpose the blocks: make a block that is the first byte of every block, and a block that is the second byte of every block, and so on.
		let transposed_blocks: Vec<Vec<u8>> = transpose_chunks(&blocks);

		// Solve each block as if it was single-character XOR. You already have code to do this.
		//: Vec<(u16, String, u8)>
		let solved_key: Vec<_> = transposed_blocks.iter()
			.map(|x| {
				let (_, _, guess) = attacks::guess_single_xor_char_decode(x);
				guess
			})
			.collect();

		// For each block, the single-byte XOR key that produces the best looking histogram is the repeating-key XOR key byte for that block.
		// Put them together and you have the key.
		//let final_blocks: Vec<Vec<u8>> = transpose_chunks(&solved_blocks);

		println!("{:?}, {:?}", solved_key, bytes_to_readable_text(&solved_key));

		let mut rk = RepeatingKey::new_bytes(solved_key);
		let dec = rk.encrypt_bytes(&data_bytes);

		println!("\n\n{}\n\n{:?}", 11-y, bytes_to_readable_text(&dec));
	}
}

fn main() {
	println!("\n\n\n\n=====\nRunning.\n\n");

	problem_3();
}<commit_msg>Problem 6 automates<commit_after>#![cfg_attr(test, allow(dead_code))]
#![allow(dead_code)]

mod attacks;
mod byte_conversion;
mod byte_manipulation;
mod byte_utilities;
mod english_scoring;
mod general_utilities;
mod key;

fn problem_3() {
	// http://cryptopals.com/sets/1/challenges/3/
	use byte_conversion::*;
	let encoded = hex_to_bytes("1b37373331363f78151b7f2b783431333d78397828372d363c78373e783a393b3736");

	let (top_score, top_decode, top_x) = attacks::guess_single_xor_char_decode(&encoded);

	println!("Best guess: `{}`, with a score of {}, using character {}.", bytes_to_readable_text(&top_decode), top_score, top_x);
}

fn problem_4() {
	// http://cryptopals.com/sets/1/challenges/4/

	use byte_conversion::*;

	let s = general_utilities::read_file("C:\\Users\\Topher\\Dropbox\\Public\\Programming\\Matasano\\matasano-crypto-challenges\\res\\4.txt");

	let mut top_score = 0;
	let mut top_decode = vec![];
    for line in s.split("\n") {
    	let (score, decoded, _) = attacks::guess_single_xor_char_decode(&hex_to_bytes(line));

		if score > top_score {
			top_score = score;
			top_decode = decoded.clone();
		}

    }

    println!("\n\n\n{} -      `{}`", top_score, bytes_to_readable_text(&top_decode));
}

fn problem_6() {
	// http://cryptopals.com/sets/1/challenges/6/

	use byte_conversion::*;
	use byte_manipulation::*;
	use byte_utilities::*;
	use english_scoring::*;
	use general_utilities::*;
	use key::*;

	let file_data = general_utilities::read_file("C:\\Users\\Topher\\Dropbox\\Public\\Programming\\Matasano\\matasano-crypto-challenges\\res\\6.txt");
	let data_bytes = base64_to_bytes(&file_data);

	// For each KEYSIZE, take the first KEYSIZE worth of bytes, and the second KEYSIZE worth of bytes,
	// and find the edit distance between them. Normalize this result by dividing by KEYSIZE.
	// The KEYSIZE with the smallest normalized edit distance is probably the key.
	//  You could proceed perhaps with the smallest 2-3 KEYSIZE values. Or take 4 KEYSIZE blocks instead of 2 and average the distances.
	let mut keysize_points = Vec::new();
	for keysize in 2..41 {
		if data_bytes.len() < keysize * 4 {
			continue;
		}

		let chunks: Vec<Vec<u8>> = data_bytes.chunks(keysize).map(|x| slice_to_vec(x)).collect();
		assert!(chunks.len() >= 4);

		let distance1 = hamming_distance(&chunks[0], &chunks[1]);
		let distance2 = hamming_distance(&chunks[1], &chunks[2]);
		let distance3 = hamming_distance(&chunks[2], &chunks[3]);
		let distance4 = hamming_distance(&chunks[3], &chunks[4]);
		let avg_distance: f32 = (distance1 + distance2 + distance3 + distance4) as f32 / 4.0;
		let normalized_distance = avg_distance / keysize as f32;

		let pair = (keysize, normalized_distance);
		keysize_points.push(pair);
	}

	// Find the 4 best keysize values
	keysize_points.sort_by(|a, b| {
		use std::cmp::Ordering::*;

		let (_, x): (_, f32) = *a;
		let (_, y): (_, f32) = *b;

		// f32s require partial cmp
		x.partial_cmp(&y).unwrap_or(Equal)
	});

	//println!("{:?}", keysize_points);

	let mut top_score = 0;
	let mut top_decode: Vec<u8> = Vec::new();
	let mut top_key: Vec<u8> = Vec::new();

	for y in 0..10 {
		let (best_keysize, _) = keysize_points[11-y];
		//println!("{:?}", best_keysize);

		// Now that you probably know the KEYSIZE: break the ciphertext into blocks of KEYSIZE length.
		let blocks: Vec<Vec<u8>> = data_bytes
			.chunks(best_keysize)
			.map(|x| slice_to_vec(x))
			.collect();

		// Now transpose the blocks: make a block that is the first byte of every block, and a block that is the second byte of every block, and so on.
		let transposed_blocks: Vec<Vec<u8>> = transpose_chunks(&blocks);

		// Solve each block as if it was single-character XOR. You already have code to do this.
		//: Vec<(u16, String, u8)>
		let solved_key: Vec<_> = transposed_blocks.iter()
			.map(|x| {
				let (_, _, guess) = attacks::guess_single_xor_char_decode(x);
				guess
			})
			.collect();

		// For each block, the single-byte XOR key that produces the best looking histogram is the repeating-key XOR key byte for that block.
		// Put them together and you have the key.
		//let final_blocks: Vec<Vec<u8>> = transpose_chunks(&solved_blocks);

		//println!("{:?}, {:?}", solved_key, bytes_to_readable_text(&solved_key));

		let mut rk = RepeatingKey::new_bytes(&solved_key);
		let dec = rk.encrypt_bytes(&data_bytes);

		//println!("\n\n{}\n\n{:?}", 11-y, bytes_to_readable_text(&dec));

		let score = english_scoring::score_combined(&dec);
		if score > top_score {
			top_score = score;
			top_decode = dec;
			top_key = solved_key;
		}
	}

	println!("{}, {}, \n{:?}", bytes_to_readable_text(&top_key), top_score, bytes_to_readable_text(&top_decode));
}

fn main() {
	println!("\n\n\n\n=====\nRunning.\n\n");

	problem_6();
}<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

use nom::{HexDisplay,IResult,FlatMap,FlatMapOpt,Functor,Producer,ProducerState,FileProducer};
use nom::IResult::*;

use std::str;

fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {

  take!(offset_parser 4);
  match offset_parser(input) {
    Done(i, offset_bytes) => {
      let offset:u32 = (offset_bytes[3] as u32) + (offset_bytes[2] as u32) * 0x100 + (offset_bytes[1] as u32) * 0x10000 + (offset_bytes[0] as u32) * 0x1000000;
      let sz: usize = offset as usize;
      //println!("box size: {} -> {} (input: {})", offset_bytes.to_hex(8), sz, i.len());
      if i.len() >= sz - 4 {
        return Done(&i[(sz-4)..], &i[0..(sz-4)])
      } else {
        return Incomplete(1234)
      }
    },
    e => e
  }
}

#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
  major_brand:         &'a str,
  major_brand_version: &'a [u8],
  compatible_brands:   Vec<&'a str>
}

#[derive(PartialEq,Eq,Debug)]
pub struct Mvhd1 {
  version:       u8,
  flags:         u32,
  created_date:  u32,
  modified_date: u32
}

#[derive(PartialEq,Eq,Debug)]
pub struct Mvhd2 {
  created_date:  u64,
  modified_date: u64,
  scale:         u32,
  duration:      u32
}

/*
#[derive(PartialEq,Eq,Debug)]
struct Mvhd3 {
  duration:      u64,
  speed:         f32,
  volume:        f32, // 2 bytes
*/
  /* 10 bytes reserved */
/*  scaleA:        f32,
  rotateB:       f32,
  angleU:        f32,
  rotateC:       f32,
  scaleD:        f32,
  angleV:        f32,
  positionX:     f32,
  positionY:     f32,
  scaleW:        f32,
  preview:       u64,
  poster:        u32,
  selection:     u64,
  current_time:  u32,
  track_id:      u32
}*/

#[derive(PartialEq,Eq,Debug)]
pub enum MvhdBox {
  M1(Mvhd1),
  M2(Mvhd2),
  M3
  /*M3(Mvhd3)*/
}

#[derive(PartialEq,Eq,Debug)]
pub enum MoovBox {
  Mdra,
  Dref,
  Cmov,
  Rmra,
  Iods,
  Mvhd,
  Clip,
  Trak,
  Udta
}

#[derive(PartialEq,Eq,Debug)]
enum MP4Box<'a> {
  Ftyp(FileType<'a>),
  Moov(Vec<MoovBox>),
  Mdat,
  Free,
  Skip,
  Wide,
  Unknown
}

take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn brand_name(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);
many0!(compatible_brands<&[u8], &str> brand_name);

fn filetype_parser<'a>(input: &'a[u8]) -> IResult<&'a [u8], FileType<'a> > {
  chaining_parser!(input,
    m: brand_name          ~
    v: major_brand_version ~
    c: compatible_brands   ,
    ||{FileType{major_brand: m, major_brand_version:v, compatible_brands: c}})
}

o!(filetype <&[u8], FileType>  ftyp ~ [ filetype_parser ]);

fn filetype_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match filetype(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      Done(i, MP4Box::Ftyp(o))
    }
  }
}

tag!(moov_tag "moov".as_bytes());

tag!(mdra    "mdra".as_bytes());
fn moov_mdra(input:&[u8]) -> IResult<&[u8], MoovBox> {
  mdra(input).map(|_| MoovBox::Mdra)
}

tag!(dref    "dref".as_bytes());
fn moov_dref(input:&[u8]) -> IResult<&[u8], MoovBox> {
  dref(input).map(|_| MoovBox::Dref)
}

tag!(cmov    "cmov".as_bytes());
fn moov_cmov(input:&[u8]) -> IResult<&[u8], MoovBox> {
  cmov(input).map(|_| MoovBox::Cmov)
}

tag!(rmra    "rmra".as_bytes());
fn moov_rmra(input:&[u8]) -> IResult<&[u8], MoovBox> {
  rmra(input).map(|_| MoovBox::Rmra)
}

tag!(iods    "iods".as_bytes());
fn moov_iods(input:&[u8]) -> IResult<&[u8], MoovBox> {
  iods(input).map(|_| MoovBox::Iods)
}

tag!(mvhd    "mvhd".as_bytes());
fn moov_mvhd(input:&[u8]) -> IResult<&[u8], MoovBox> {
  mvhd(input).map(|_| MoovBox::Mvhd)
  /*let res = mvhd(input).map(|o| MoovBox::Mvhd);
  match res {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      println!("MVHD box content:\n{}", i.to_hex(8));
      Done(i,o)
    }
  }*/
}

tag!(clip    "clip".as_bytes());
fn moov_clip(input:&[u8]) -> IResult<&[u8], MoovBox> {
  clip(input).map(|_| MoovBox::Clip)
}

tag!(trak    "trak".as_bytes());
fn moov_trak(input:&[u8]) -> IResult<&[u8], MoovBox> {
  trak(input).map(|_| MoovBox::Trak)
}

tag!(udta   "udta".as_bytes());
fn moov_udta(input:&[u8]) -> IResult<&[u8], MoovBox> {
  udta(input).map(|_| MoovBox::Udta)
}

alt!(moov_internal<&[u8], MoovBox>, moov_mdra | moov_dref | moov_cmov |
     moov_rmra | moov_iods | moov_mvhd | moov_clip | moov_trak | moov_udta);

fn moov(input:&[u8]) -> IResult<&[u8], MoovBox> {
  match mp4_box(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      match moov_internal(o) {
        Error(a)      => Error(a),
        Incomplete(a) => Incomplete(a),
        Done(i2, o2)  => {
          Done(i, o2)
        }

      }
    }
  }
}

many0!(moov_many<&[u8],MoovBox> moov);

o!(moov_box_internal <&[u8], Vec<MoovBox> >  moov_tag ~ [ moov_many ]);

fn moov_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match moov_box_internal(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)  => {
      Done(i, MP4Box::Moov(o))
    }
  }
}

tag!(mdat    "mdat".as_bytes());
fn mdat_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  mdat(input).map(|_| MP4Box::Mdat)
}
tag!(free    "free".as_bytes());
fn free_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  free(input).map(|_| MP4Box::Free)
}

tag!(skip    "skip".as_bytes());
fn skip_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  skip(input).map(|_| MP4Box::Skip)
}

tag!(wide    "wide".as_bytes());
fn wide_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  wide(input).map(|_| MP4Box::Wide)
}

fn unknown_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  println!("calling UNKNOWN");
  Done(input, MP4Box::Unknown)
}

alt!(box_parser_internal<&[u8], MP4Box>, filetype_box | moov_box | mdat_box | free_box | skip_box | wide_box | unknown_box);
fn box_parser(input:&[u8]) -> IResult<&[u8], MP4Box> {
  mp4_box(input).flat_map(box_parser_internal)
}

fn data_interpreter(bytes:&[u8]) -> IResult<&[u8], ()> {
  //println!("bytes:\n{}", bytes.to_hex(8));
  match box_parser(bytes) {
    Done(i, o) => {
      match o {
        MP4Box::Ftyp(f) => println!("-> FTYP: {:?}", f),
        MP4Box::Moov(m) => {println!("-> MOOV: {:?}", m); println!("remaining:\n{}", i.to_hex(8))},
        MP4Box::Mdat    => println!("-> MDAT"),
        MP4Box::Free    => println!("-> FREE"),
        MP4Box::Skip    => println!("-> SKIP"),
        MP4Box::Wide    => println!("-> WIDE"),
        MP4Box::Unknown => println!("-> UNKNOWN")
      }
      //println!("remaining:\n{}", i.to_hex(8));
      Done(i,())
    },
    Error(a) => {
      println!("mp4 parsing error: {:?}", a);
      assert!(false);
      Error(a)
    },
    Incomplete(a) => {
      println!("incomplete: {:?}", a);
      Incomplete(a)
    }
  }
}

fn multiple_data_interpreter(bytes:&[u8]) -> IResult<&[u8], ()> {
  match data_interpreter(bytes) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, ())   => {
      println!("NEXT BOX");
      match data_interpreter(i) {
        Error(a)      => Error(a),
        Incomplete(a) => Incomplete(a),
        Done(i2,())   => {
          println!("NEXT BOX 2");
          match data_interpreter(i2) {
            Error(a)      => Error(a),
            Incomplete(a) => Incomplete(a),
            Done(i3,())   => {
              println!("NEXT BOX 3");
              match data_interpreter(i3) {
                Error(a)      => Error(a),
                Incomplete(a) => Incomplete(a),
                Done(i4,())   => {
                  println!("NEXT BOX 4");
                  let res = data_interpreter(i4);
                  println!("res4: {:?}", res);
                  res
                }
              }
            }
          }
        }
      }
    },
  }
}

many0!(full_data_interpreter<&[u8],()> data_interpreter);

fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 40000).map(|producer: FileProducer| {
    let mut p = producer;
    match p.produce() {
      ProducerState::Data(bytes) => {
        multiple_data_interpreter(bytes);
      },
      _ => println!("got error")
    }
    /*
    pusher!(ps, full_data_interpreter);
    ps(&mut p);
    */
    //assert!(false);
  });

}
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}
<commit_msg>remove useless code<commit_after>#[macro_use]
extern crate nom;

use nom::{HexDisplay,IResult,FlatMap,FlatMapOpt,Functor,Producer,ProducerState,FileProducer};
use nom::IResult::*;

use std::str;

fn mp4_box(input:&[u8]) -> IResult<&[u8], &[u8]> {

  take!(offset_parser 4);
  match offset_parser(input) {
    Done(i, offset_bytes) => {
      let offset:u32 = (offset_bytes[3] as u32) + (offset_bytes[2] as u32) * 0x100 + (offset_bytes[1] as u32) * 0x10000 + (offset_bytes[0] as u32) * 0x1000000;
      let sz: usize = offset as usize;
      //println!("box size: {} -> {} (input: {})", offset_bytes.to_hex(8), sz, i.len());
      if i.len() >= sz - 4 {
        return Done(&i[(sz-4)..], &i[0..(sz-4)])
      } else {
        return Incomplete(1234)
      }
    },
    e => e
  }
}

#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
  major_brand:         &'a str,
  major_brand_version: &'a [u8],
  compatible_brands:   Vec<&'a str>
}

#[derive(PartialEq,Eq,Debug)]
pub struct Mvhd1 {
  version:       u8,
  flags:         u32,
  created_date:  u32,
  modified_date: u32
}

#[derive(PartialEq,Eq,Debug)]
pub struct Mvhd2 {
  created_date:  u64,
  modified_date: u64,
  scale:         u32,
  duration:      u32
}

/*
#[derive(PartialEq,Eq,Debug)]
struct Mvhd3 {
  duration:      u64,
  speed:         f32,
  volume:        f32, // 2 bytes
*/
  /* 10 bytes reserved */
/*  scaleA:        f32,
  rotateB:       f32,
  angleU:        f32,
  rotateC:       f32,
  scaleD:        f32,
  angleV:        f32,
  positionX:     f32,
  positionY:     f32,
  scaleW:        f32,
  preview:       u64,
  poster:        u32,
  selection:     u64,
  current_time:  u32,
  track_id:      u32
}*/

#[derive(PartialEq,Eq,Debug)]
pub enum MvhdBox {
  M1(Mvhd1),
  M2(Mvhd2),
  M3
  /*M3(Mvhd3)*/
}

#[derive(PartialEq,Eq,Debug)]
pub enum MoovBox {
  Mdra,
  Dref,
  Cmov,
  Rmra,
  Iods,
  Mvhd,
  Clip,
  Trak,
  Udta
}

#[derive(PartialEq,Eq,Debug)]
enum MP4Box<'a> {
  Ftyp(FileType<'a>),
  Moov(Vec<MoovBox>),
  Mdat,
  Free,
  Skip,
  Wide,
  Unknown
}

take!(offset 4);
tag!(ftyp    "ftyp".as_bytes());

fn brand_name(input:&[u8]) -> IResult<&[u8],&str> {
  take!(major_brand_bytes 4);
  major_brand_bytes(input).map_res(str::from_utf8)
}
take!(major_brand_version 4);
many0!(compatible_brands<&[u8], &str> brand_name);

fn filetype_parser<'a>(input: &'a[u8]) -> IResult<&'a [u8], FileType<'a> > {
  chaining_parser!(input,
    m: brand_name          ~
    v: major_brand_version ~
    c: compatible_brands   ,
    ||{FileType{major_brand: m, major_brand_version:v, compatible_brands: c}})
}

o!(filetype <&[u8], FileType>  ftyp ~ [ filetype_parser ]);

fn filetype_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match filetype(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      Done(i, MP4Box::Ftyp(o))
    }
  }
}

tag!(moov_tag "moov".as_bytes());

tag!(mdra    "mdra".as_bytes());
fn moov_mdra(input:&[u8]) -> IResult<&[u8], MoovBox> {
  mdra(input).map(|_| MoovBox::Mdra)
}

tag!(dref    "dref".as_bytes());
fn moov_dref(input:&[u8]) -> IResult<&[u8], MoovBox> {
  dref(input).map(|_| MoovBox::Dref)
}

tag!(cmov    "cmov".as_bytes());
fn moov_cmov(input:&[u8]) -> IResult<&[u8], MoovBox> {
  cmov(input).map(|_| MoovBox::Cmov)
}

tag!(rmra    "rmra".as_bytes());
fn moov_rmra(input:&[u8]) -> IResult<&[u8], MoovBox> {
  rmra(input).map(|_| MoovBox::Rmra)
}

tag!(iods    "iods".as_bytes());
fn moov_iods(input:&[u8]) -> IResult<&[u8], MoovBox> {
  iods(input).map(|_| MoovBox::Iods)
}

tag!(mvhd    "mvhd".as_bytes());
fn moov_mvhd(input:&[u8]) -> IResult<&[u8], MoovBox> {
  mvhd(input).map(|_| MoovBox::Mvhd)
  /*let res = mvhd(input).map(|o| MoovBox::Mvhd);
  match res {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      println!("MVHD box content:\n{}", i.to_hex(8));
      Done(i,o)
    }
  }*/
}

tag!(clip    "clip".as_bytes());
fn moov_clip(input:&[u8]) -> IResult<&[u8], MoovBox> {
  clip(input).map(|_| MoovBox::Clip)
}

tag!(trak    "trak".as_bytes());
fn moov_trak(input:&[u8]) -> IResult<&[u8], MoovBox> {
  trak(input).map(|_| MoovBox::Trak)
}

tag!(udta   "udta".as_bytes());
fn moov_udta(input:&[u8]) -> IResult<&[u8], MoovBox> {
  udta(input).map(|_| MoovBox::Udta)
}

alt!(moov_internal<&[u8], MoovBox>, moov_mdra | moov_dref | moov_cmov |
     moov_rmra | moov_iods | moov_mvhd | moov_clip | moov_trak | moov_udta);

fn moov(input:&[u8]) -> IResult<&[u8], MoovBox> {
  match mp4_box(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)    => {
      match moov_internal(o) {
        Error(a)      => Error(a),
        Incomplete(a) => Incomplete(a),
        Done(i2, o2)  => {
          Done(i, o2)
        }

      }
    }
  }
}

many0!(moov_many<&[u8],MoovBox> moov);

o!(moov_box_internal <&[u8], Vec<MoovBox> >  moov_tag ~ [ moov_many ]);

fn moov_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  match moov_box_internal(input) {
    Error(a)      => Error(a),
    Incomplete(a) => Incomplete(a),
    Done(i, o)  => {
      Done(i, MP4Box::Moov(o))
    }
  }
}

tag!(mdat    "mdat".as_bytes());
fn mdat_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  mdat(input).map(|_| MP4Box::Mdat)
}
tag!(free    "free".as_bytes());
fn free_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  free(input).map(|_| MP4Box::Free)
}

tag!(skip    "skip".as_bytes());
fn skip_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  skip(input).map(|_| MP4Box::Skip)
}

tag!(wide    "wide".as_bytes());
fn wide_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  wide(input).map(|_| MP4Box::Wide)
}

fn unknown_box(input:&[u8]) -> IResult<&[u8], MP4Box> {
  println!("calling UNKNOWN");
  Done(input, MP4Box::Unknown)
}

alt!(box_parser_internal<&[u8], MP4Box>, filetype_box | moov_box | mdat_box | free_box | skip_box | wide_box | unknown_box);
fn box_parser(input:&[u8]) -> IResult<&[u8], MP4Box> {
  mp4_box(input).flat_map(box_parser_internal)
}

fn data_interpreter(bytes:&[u8]) -> IResult<&[u8], ()> {
  //println!("bytes:\n{}", bytes.to_hex(8));
  match box_parser(bytes) {
    Done(i, o) => {
      match o {
        MP4Box::Ftyp(f) => println!("-> FTYP: {:?}", f),
        MP4Box::Moov(m) => {println!("-> MOOV: {:?}", m); println!("remaining:\n{}", i.to_hex(8))},
        MP4Box::Mdat    => println!("-> MDAT"),
        MP4Box::Free    => println!("-> FREE"),
        MP4Box::Skip    => println!("-> SKIP"),
        MP4Box::Wide    => println!("-> WIDE"),
        MP4Box::Unknown => println!("-> UNKNOWN")
      }
      //println!("remaining:\n{}", i.to_hex(8));
      Done(i,())
    },
    Error(a) => {
      println!("mp4 parsing error: {:?}", a);
      assert!(false);
      Error(a)
    },
    Incomplete(a) => {
      println!("incomplete: {:?}", a);
      Incomplete(a)
    }
  }
}

many0!(full_data_interpreter<&[u8],()> data_interpreter);

fn parse_mp4_file(filename: &str) {
  FileProducer::new(filename, 400000).map(|producer: FileProducer| {
    let mut p = producer;
    pusher!(ps, full_data_interpreter);
    ps(&mut p);

    //assert!(false);
  });

}

/*
#[test]
fn file_test() {
  parse_mp4_file("small.mp4");
}
*/

#[test]
fn bunny_test() {
  parse_mp4_file("bigbuckbunny.mp4");
}

<|endoftext|>