<commit_before>// Aligned to two bytes
const DATA: [u16; 2] = [u16::from_ne_bytes([0x01, 0x23]), u16::from_ne_bytes([0x45, 0x67])];

const fn unaligned_ptr() -> *const u16 {
    // Since DATA.as_ptr() is aligned to two bytes, adding 1 byte to that produces an unaligned *const u16
    unsafe { (DATA.as_ptr() as *const u8).add(1) as *const u16 }
}

#[test]
fn read() {
    use core::ptr;

    const FOO: i32 = unsafe { ptr::read(&42 as *const i32) };
    assert_eq!(FOO, 42);

    const ALIGNED: i32 = unsafe { ptr::read_unaligned(&42 as *const i32) };
    assert_eq!(ALIGNED, 42);

    const UNALIGNED_PTR: *const u16 = unaligned_ptr();

    const UNALIGNED: u16 = unsafe { ptr::read_unaligned(UNALIGNED_PTR) };
    assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
}

#[test]
fn const_ptr_read() {
    const FOO: i32 = unsafe { (&42 as *const i32).read() };
    assert_eq!(FOO, 42);

    const ALIGNED: i32 = unsafe { (&42 as *const i32).read_unaligned() };
    assert_eq!(ALIGNED, 42);

    const UNALIGNED_PTR: *const u16 = unaligned_ptr();

    const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() };
    assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
}

#[test]
fn mut_ptr_read() {
    const FOO: i32 = unsafe { (&42 as *const i32 as *mut i32).read() };
    assert_eq!(FOO, 42);

    const ALIGNED: i32 = unsafe { (&42 as *const i32 as *mut i32).read_unaligned() };
    assert_eq!(ALIGNED, 42);

    const UNALIGNED_PTR: *mut u16 = unaligned_ptr() as *mut u16;

    const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() };
    assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
}

#[test]
fn write() {
    use core::ptr;

    const fn write_aligned() -> i32 {
        let mut res = 0;
        unsafe {
            ptr::write(&mut res as *mut _, 42);
        }
        res
    }
    const ALIGNED: i32 = write_aligned();
    assert_eq!(ALIGNED, 42);

    const fn write_unaligned() -> [u16; 2] {
        let mut two_aligned = [0u16; 2];
        unsafe {
            let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
            ptr::write_unaligned(unaligned_ptr, u16::from_ne_bytes([0x23, 0x45]));
        }
        two_aligned
    }
    const UNALIGNED: [u16; 2] = write_unaligned();
    assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
}

#[test]
fn mut_ptr_write() {
    const fn aligned() -> i32 {
        let mut res = 0;
        unsafe {
            (&mut res as *mut i32).write(42);
        }
        res
    }
    const ALIGNED: i32 = aligned();
    assert_eq!(ALIGNED, 42);

    const fn write_unaligned() -> [u16; 2] {
        let mut two_aligned = [0u16; 2];
        unsafe {
            let unaligned_ptr = (two_aligned.as_mut_ptr() as *mut u8).add(1) as *mut u16;
            unaligned_ptr.write_unaligned(u16::from_ne_bytes([0x23, 0x45]));
        }
        two_aligned
    }
    const UNALIGNED: [u16; 2] = write_unaligned();
    assert_eq!(UNALIGNED, [u16::from_ne_bytes([0x00, 0x23]), u16::from_ne_bytes([0x45, 0x00])]);
}
<commit_msg>Revert tests added by PR 81167.<commit_after>// Aligned to two bytes
const DATA: [u16; 2] = [u16::from_ne_bytes([0x01, 0x23]), u16::from_ne_bytes([0x45, 0x67])];

const fn unaligned_ptr() -> *const u16 {
    // Since DATA.as_ptr() is aligned to two bytes, adding 1 byte to that produces an unaligned *const u16
    unsafe { (DATA.as_ptr() as *const u8).add(1) as *const u16 }
}

#[test]
fn read() {
    use core::ptr;

    const FOO: i32 = unsafe { ptr::read(&42 as *const i32) };
    assert_eq!(FOO, 42);

    const ALIGNED: i32 = unsafe { ptr::read_unaligned(&42 as *const i32) };
    assert_eq!(ALIGNED, 42);

    const UNALIGNED_PTR: *const u16 = unaligned_ptr();

    const UNALIGNED: u16 = unsafe { ptr::read_unaligned(UNALIGNED_PTR) };
    assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
}

#[test]
fn const_ptr_read() {
    const FOO: i32 = unsafe { (&42 as *const i32).read() };
    assert_eq!(FOO, 42);

    const ALIGNED: i32 = unsafe { (&42 as *const i32).read_unaligned() };
    assert_eq!(ALIGNED, 42);

    const UNALIGNED_PTR: *const u16 = unaligned_ptr();

    const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() };
    assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
}

#[test]
fn mut_ptr_read() {
    const FOO: i32 = unsafe { (&42 as *const i32 as *mut i32).read() };
    assert_eq!(FOO, 42);

    const ALIGNED: i32 = unsafe { (&42 as *const i32 as *mut i32).read_unaligned() };
    assert_eq!(ALIGNED, 42);

    const UNALIGNED_PTR: *mut u16 = unaligned_ptr() as *mut u16;

    const UNALIGNED: u16 = unsafe { UNALIGNED_PTR.read_unaligned() };
    assert_eq!(UNALIGNED, u16::from_ne_bytes([0x23, 0x45]));
}
<|endoftext|>


<commit_before>extern crate walkdir;
extern crate chrono;

use std::path;
use self::walkdir::{WalkDir, DirEntry, Error as WalkDirError};
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use self::chrono::{DateTime, UTC};
use std::error::Error;
use std::str::FromStr;

pub struct ELBLogEntry {
    timestamp: DateTime<UTC>,
    elb_name: String,
    client_address: String,
    backend_address: String,
    request_processing_time: f32,
    backend_processing_time: String,
    response_processing_time: String,
    elb_status_code: String,
    backend_status_code: String,
    received_bytes: String,
    sent_bytes: String,
    request_method: String,
    request_url: String,
    request_http_version: String
}

pub fn file_list(dir: &path::Path, filenames: &mut Vec<DirEntry>) -> Result<usize, WalkDirError> {
    for entry in WalkDir::new(dir).min_depth(1) {
        match entry {
            Err(err) => return Err(err),
            Ok(entry) => filenames.push(entry),
        }
    }
    Ok(filenames.len())
}

pub fn process_files(runtime_context: &::RuntimeContext, filenames: Vec<walkdir::DirEntry>) -> usize {
    let debug = runtime_context.debug;
    let mut record_count = 0;
    for filename in filenames {
        debug!(debug, "Processing file {}.", filename.path().display());
        match File::open(filename.path()) {
            Ok(file) => {
                let buffered_file = BufReader::new(&file);
                let recs: Vec<_> = buffered_file.lines()
                    .map(|x| {
                        parse_line(&(x.unwrap()))
                    })
                    .collect();
                record_count += recs.len();
                debug!(debug, "Found {} records in file {}.", recs.len(), filename.path().display());
            },
            Err(e) => {
                println!("ERROR: {}", e);
            }
        }
    }

    record_count
}

#[derive(Debug)]
pub struct ParsingError{
    property: &'static str,
    inner_description: Box<Error>,
}

#[derive(Debug)]
pub struct ParsingErrors {
    record: String,
    errors: Vec<ParsingError>,
}

const TIMESTAMP: &'static str = "timestamp";
const REQUEST_PROCESSING_TIME: &'static str = "request processing time";

pub fn parse_line(line: &String) -> Result<Box<ELBLogEntry>, Box<ParsingErrors>> {
    let split_line: Vec<_> = line.split(" ").collect();
    let mut errors: Vec<ParsingError> = Vec::new();

    let ts = parse_property::<DateTime<UTC>>(split_line[0], TIMESTAMP, &mut errors);
    let req_proc_time = parse_property::<f32>(split_line[4], REQUEST_PROCESSING_TIME, &mut errors);

    if errors.is_empty() {
        Ok(Box::new(
            ELBLogEntry {
                timestamp: ts.unwrap(),
                elb_name: split_line[1].to_string(),
                client_address: split_line[2].to_string(),
                backend_address: split_line[3].to_string(),
                request_processing_time: req_proc_time.unwrap(),
                backend_processing_time: split_line[5].to_string(),
                response_processing_time: split_line[6].to_string(),
                elb_status_code: split_line[7].to_string(),
                backend_status_code: split_line[8].to_string(),
                received_bytes: split_line[9].to_string(),
                sent_bytes: split_line[10].to_string(),
                request_method: split_line[11].trim_matches('"').to_string(),
                request_url: split_line[12].to_string(),
                request_http_version: split_line[13].trim_matches('"').to_string()
            }
        ))
    } else {
        Err(Box::new(
            ParsingErrors {
                record: line.clone(),
                errors: errors
            }
        ))
    }
}

fn parse_property<T>(raw_prop: &str, prop_name: &'static str, errors: &mut Vec<ParsingError>) -> Option<T>
    where T: FromStr,
    T::Err: Error + 'static,
{
    match raw_prop.parse::<T>() {
        Ok(parsed) => Some(parsed),

        Err(e) => {
            errors.push(
                ParsingError {
                    property: prop_name,
                    inner_description: Box::new(e),
                }
            );
            None
        }
    }
}

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

    const TEST_LINE: &'static str = "2015-08-15T23:43:05.302180Z elb-name 172.16.1.6:54814 \
    172.16.1.5:9000 0.000039 0.145507 0.00003 200 200 0 7582 \
    \"GET http://some.domain.com:80/path0/path1?param0=p0&param1=p1 HTTP/1.1\" \
    ";

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_http_version() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_http_version, "HTTP/1.1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_url() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_url, "http://some.domain.com:80/path0/path1?param0=p0&param1=p1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_method() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_method, "GET")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_sent_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.sent_bytes, "7582")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_received_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.received_bytes, "0")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_response_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.response_processing_time, "0.00003")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_processing_time, "0.145507")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_processing_time, 0.000039)
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_address, "172.16.1.5:9000")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_client_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.client_address, "172.16.1.6:54814")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_timestamp() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(format!("{:?}", elb_log_entry.timestamp), "2015-08-15T23:43:05.302180Z")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_name() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_name, "elb-name")
	}
}
<commit_msg>Converted the processing times to f32.<commit_after>extern crate walkdir;
extern crate chrono;

use std::path;
use self::walkdir::{WalkDir, DirEntry, Error as WalkDirError};
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use self::chrono::{DateTime, UTC};
use std::error::Error;
use std::str::FromStr;

pub struct ELBLogEntry {
    timestamp: DateTime<UTC>,
    elb_name: String,
    client_address: String,
    backend_address: String,
    request_processing_time: f32,
    backend_processing_time: f32,
    response_processing_time: f32,
    elb_status_code: String,
    backend_status_code: String,
    received_bytes: String,
    sent_bytes: String,
    request_method: String,
    request_url: String,
    request_http_version: String
}

pub fn file_list(dir: &path::Path, filenames: &mut Vec<DirEntry>) -> Result<usize, WalkDirError> {
    for entry in WalkDir::new(dir).min_depth(1) {
        match entry {
            Err(err) => return Err(err),
            Ok(entry) => filenames.push(entry),
        }
    }
    Ok(filenames.len())
}

pub fn process_files(runtime_context: &::RuntimeContext, filenames: Vec<walkdir::DirEntry>) -> usize {
    let debug = runtime_context.debug;
    let mut record_count = 0;
    for filename in filenames {
        debug!(debug, "Processing file {}.", filename.path().display());
        match File::open(filename.path()) {
            Ok(file) => {
                let buffered_file = BufReader::new(&file);
                let recs: Vec<_> = buffered_file.lines()
                    .map(|x| {
                        parse_line(&(x.unwrap()))
                    })
                    .collect();
                record_count += recs.len();
                debug!(debug, "Found {} records in file {}.", recs.len(), filename.path().display());
            },
            Err(e) => {
                println!("ERROR: {}", e);
            }
        }
    }

    record_count
}

#[derive(Debug)]
pub struct ParsingError{
    property: &'static str,
    inner_description: Box<Error>,
}

#[derive(Debug)]
pub struct ParsingErrors {
    record: String,
    errors: Vec<ParsingError>,
}

const TIMESTAMP: &'static str = "timestamp";
const REQUEST_PROCESSING_TIME: &'static str = "request processing time";
const BACKEND_PROCESSING_TIME: &'static str = "backend processing time";
const RESPONSE_PROCESSING_TIME: &'static str = "response processing time";

pub fn parse_line(line: &String) -> Result<Box<ELBLogEntry>, Box<ParsingErrors>> {
    let split_line: Vec<_> = line.split(" ").collect();
    let mut errors: Vec<ParsingError> = Vec::new();

    let ts = parse_property::<DateTime<UTC>>(split_line[0], TIMESTAMP, &mut errors);
    let req_proc_time = parse_property::<f32>(split_line[4], REQUEST_PROCESSING_TIME, &mut errors);
    let be_proc_time = parse_property::<f32>(split_line[5], BACKEND_PROCESSING_TIME, &mut errors);
    let res_proc_time = parse_property::<f32>(split_line[6], RESPONSE_PROCESSING_TIME, &mut errors);

    if errors.is_empty() {
        Ok(Box::new(
            ELBLogEntry {
                timestamp: ts.unwrap(),
                elb_name: split_line[1].to_string(),
                client_address: split_line[2].to_string(),
                backend_address: split_line[3].to_string(),
                request_processing_time: req_proc_time.unwrap(),
                backend_processing_time: be_proc_time.unwrap(),
                response_processing_time: res_proc_time.unwrap(),
                elb_status_code: split_line[7].to_string(),
                backend_status_code: split_line[8].to_string(),
                received_bytes: split_line[9].to_string(),
                sent_bytes: split_line[10].to_string(),
                request_method: split_line[11].trim_matches('"').to_string(),
                request_url: split_line[12].to_string(),
                request_http_version: split_line[13].trim_matches('"').to_string()
            }
        ))
    } else {
        Err(Box::new(
            ParsingErrors {
                record: line.clone(),
                errors: errors
            }
        ))
    }
}

fn parse_property<T>(raw_prop: &str, prop_name: &'static str, errors: &mut Vec<ParsingError>) -> Option<T>
    where T: FromStr,
    T::Err: Error + 'static,
{
    match raw_prop.parse::<T>() {
        Ok(parsed) => Some(parsed),

        Err(e) => {
            errors.push(
                ParsingError {
                    property: prop_name,
                    inner_description: Box::new(e),
                }
            );
            None
        }
    }
}

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

    const TEST_LINE: &'static str = "2015-08-15T23:43:05.302180Z elb-name 172.16.1.6:54814 \
    172.16.1.5:9000 0.000039 0.145507 0.00003 200 200 0 7582 \
    \"GET http://some.domain.com:80/path0/path1?param0=p0&param1=p1 HTTP/1.1\" \
    ";

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_http_version() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_http_version, "HTTP/1.1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_url() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_url, "http://some.domain.com:80/path0/path1?param0=p0&param1=p1")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_method() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_method, "GET")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_sent_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.sent_bytes, "7582")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_received_bytes() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.received_bytes, "0")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_status_code() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_status_code, "200")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_response_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.response_processing_time, 0.00003)
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_processing_time, 0.145507)
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_request_processing_time() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.request_processing_time, 0.000039)
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_backend_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.backend_address, "172.16.1.5:9000")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_client_address() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.client_address, "172.16.1.6:54814")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_timestamp() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(format!("{:?}", elb_log_entry.timestamp), "2015-08-15T23:43:05.302180Z")
	}

    #[test]
	fn parse_line_returns_a_log_entry_with_the_elb_name() {
        let elb_log_entry = parse_line(&TEST_LINE.to_string()).unwrap();

		assert_eq!(elb_log_entry.elb_name, "elb-name")
	}
}
<|endoftext|>


<commit_before>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

extern crate glob;
extern crate serde;
extern crate serde_json;

use self::glob::glob;
use self::serde::{Serialize, Deserialize};

use std::io::{Read, Write};
use std::fs::File;
use std::vec::Vec;

/*===============================================================================================*/
/*------CONFIG STRUCT----------------------------------------------------------------------------*/
/*===============================================================================================*/

#[derive (Clone)]
pub struct Config {

    // Public
    /// The name of the config file.
    pub name: String,
    /// The path to the config file.
    pub path: String
}

/*===============================================================================================*/
/*------CONFIGMANAGER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the application config.
///
/// It is resposible for loading the app config, and allowing other modules easy access to that data.
/// It is also used for saving the app config.
#[derive (Clone, Default)]
pub struct ConfigManager {

    // Public
    /// The path to the config directory.
    pub config_dir: String,

    // Private
    _config_list: Vec<Config>
}

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC METHODS-------------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigManager {

    /// Queries the config directory, and stores a list of configs.
    pub fn query_config_dir (&mut self) {

        // Clear the old config list
        self._config_list.clear ();

        info! ("Searching for config files...");

        // Recurse through all items in the config directory
        for path in glob (&format! ("{}/*{}", &self.config_dir, ".json")).unwrap ().filter_map (Result::ok) {

            self._config_list.push (Config {name: path.file_stem ().unwrap ().to_str ().unwrap ().to_string (),
                                            path: path.to_str ().unwrap ().to_string ()});

            info! ("Found: {:?}", &path.file_name ().unwrap ());
        }

        // If list is empty, print empty
        // Otherwise, print searching complete
        if self._config_list.is_empty () {
            info! ("No config files found.");
        }

        else {
            info! ("Config searching complete.");
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Creates a new config with given name.
    pub fn create_config<T: Serialize + Deserialize + Default> (&mut self, config_name: &str) {

        debug! ("Creating config file with name: '{}'", config_name);

        let mut f = File::create (format! ("{}/{}.json", &self.config_dir, config_name)).unwrap ();
        f.write (serde_json::to_string_pretty (&T::default ()).unwrap ().as_bytes ()).unwrap ();

        self._config_list.push (Config {name: config_name.to_string (),
                                        path: format! ("{}/{}.json", &self.config_dir, config_name)});
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Loads a config of a given name.
    ///
    /// The config file is then converted into the type `T`. `T` must derive both the
    /// [`Serialize`] (http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html) and
    /// [`Deserialize`] (http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html) traits.
    ///
    /// If this fails, an [`Err`] (https://doc.rust-lang.org/std/result/) is returned.
    ///
    /// # Return value
    /// A result containing the config struct `T`.
    pub fn load_config<T: Serialize + Deserialize> (&self, config_name: &str) -> Result<T, ()> {

        debug! ("Loading config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::open (&item.path).unwrap ();
                let mut s = String::new ();

                f.read_to_string (&mut s).unwrap ();
                return Ok (serde_json::from_str::<T> (&s).unwrap ());
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves a config of a given name.
    pub fn save_config<T: Serialize + Deserialize> (&self, config_name: &str, data: &T) -> Result<(), ()> {

        debug! ("Saving config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::create (&item.path).unwrap ();
                f.write (serde_json::to_string_pretty (&data).unwrap ().as_bytes ()).unwrap ();
                return Ok (())
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Check if a config file exists.
    pub fn config_exists (&self, config_name: &str) -> bool {

        for item in &self._config_list {

            if item.name == config_name {
                return true;
            }
        }

        false
    }

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC STATIC METHODS------------------------------------------------------*/
/*===============================================================================================*/

    /// Returns a new instance of the config manager.
    ///
    /// # Default values
    /// * `config_dir` - "config".to_string ()
    ///
    /// # Return value
    /// A new config manager instance.
    pub fn new () -> ConfigManager {

        ConfigManager {config_dir: "config".to_string (),
                       _config_list: Vec::new ()}
    }
}
<commit_msg>Added check into query_config_dir to ensure directory is valid<commit_after>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

extern crate glob;
extern crate serde;
extern crate serde_json;

use self::glob::glob;
use self::serde::{Serialize, Deserialize};

use std::io::{Read, Write};
use std::fs;
use std::fs::File;
use std::vec::Vec;

/*===============================================================================================*/
/*------CONFIG STRUCT----------------------------------------------------------------------------*/
/*===============================================================================================*/

#[derive (Clone)]
pub struct Config {

    // Public
    /// The name of the config file.
    pub name: String,
    /// The path to the config file.
    pub path: String
}

/*===============================================================================================*/
/*------CONFIGMANAGER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the application config.
///
/// It is resposible for loading the app config, and allowing other modules easy access to that data.
/// It is also used for saving the app config.
#[derive (Clone, Default)]
pub struct ConfigManager {

    // Public
    /// The path to the config directory.
    pub config_dir: String,

    // Private
    _config_list: Vec<Config>
}

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC METHODS-------------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigManager {

    /// Queries the config directory, and stores a list of configs.
    pub fn query_config_dir (&mut self) {

        // Clear the old config list
        self._config_list.clear ();

        info! ("Searching for config files...");

        // Make sure the config directoy already exists
        if fs::metadata (&self.config_dir).is_err () {

            info! ("Config directory does not exist. Creating one now.");

            // Create new directory and check for errors
            match fs::create_dir (&self.config_dir) {

                Ok  (_) => {

                    info! ("Directory creation successful.");
                    info! ("No config files found.");
                    return;
                },

                Err (e) => {

                    error! ("Failed to create config directory: {}", e);
                    panic! ();
                }
            }
        }

        // Recurse through all items in the config directory
        for path in glob (&format! ("{}/*{}", &self.config_dir, ".json")).unwrap ().filter_map (Result::ok) {

            self._config_list.push (Config {name: path.file_stem ().unwrap ().to_str ().unwrap ().to_string (),
                                            path: path.to_str ().unwrap ().to_string ()});

            info! ("Found: {:?}", &path.file_name ().unwrap ());
        }

        // If list is empty, print empty
        // Otherwise, print searching complete
        if self._config_list.is_empty () {
            info! ("No config files found.");
        }

        else {
            info! ("Config searching complete.");
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Creates a new config with given name.
    pub fn create_config<T: Serialize + Deserialize + Default> (&mut self, config_name: &str) {

        debug! ("Creating config file with name: '{}'", config_name);

        let mut f = File::create (format! ("{}/{}.json", &self.config_dir, config_name)).unwrap ();
        f.write (serde_json::to_string_pretty (&T::default ()).unwrap ().as_bytes ()).unwrap ();

        self._config_list.push (Config {name: config_name.to_string (),
                                        path: format! ("{}/{}.json", &self.config_dir, config_name)});
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Loads a config of a given name.
    ///
    /// The config file is then converted into the type `T`. `T` must derive both the
    /// [`Serialize`] (http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html) and
    /// [`Deserialize`] (http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html) traits.
    ///
    /// If this fails, an [`Err`] (https://doc.rust-lang.org/std/result/) is returned.
    ///
    /// # Return value
    /// A result containing the config struct `T`.
    pub fn load_config<T: Serialize + Deserialize> (&self, config_name: &str) -> Result<T, ()> {

        debug! ("Loading config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::open (&item.path).unwrap ();
                let mut s = String::new ();

                f.read_to_string (&mut s).unwrap ();
                return Ok (serde_json::from_str::<T> (&s).unwrap ());
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves a config of a given name.
    pub fn save_config<T: Serialize + Deserialize> (&self, config_name: &str, data: &T) -> Result<(), ()> {

        debug! ("Saving config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::create (&item.path).unwrap ();
                f.write (serde_json::to_string_pretty (&data).unwrap ().as_bytes ()).unwrap ();
                return Ok (())
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Check if a config file exists.
    pub fn config_exists (&self, config_name: &str) -> bool {

        for item in &self._config_list {

            if item.name == config_name {
                return true;
            }
        }

        false
    }

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC STATIC METHODS------------------------------------------------------*/
/*===============================================================================================*/

    /// Returns a new instance of the config manager.
    ///
    /// # Default values
    /// * `config_dir` - "config".to_string ()
    ///
    /// # Return value
    /// A new config manager instance.
    pub fn new () -> ConfigManager {

        ConfigManager {config_dir: "config".to_string (),
                       _config_list: Vec::new ()}
    }
}
<|endoftext|>


<commit_before>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

extern crate glob;
extern crate serde;
extern crate serde_json;

use self::glob::glob;
use self::serde::{Serialize, Deserialize};

use std::io::{Read, Write};
use std::fs::File;
use std::vec::Vec;

/*===============================================================================================*/
/*------CONFIG STRUCT----------------------------------------------------------------------------*/
/*===============================================================================================*/

#[derive (Clone)]
pub struct Config {

    // Public
    /// The name of the config file.
    pub name: String,
    /// The path to the config file.
    pub path: String
}

/*===============================================================================================*/
/*------CONFIGMANAGER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the application config.
///
/// It is resposible for loading the app config, and allowing other modules easy access to that data.
/// It is also used for saving the app config.
#[derive (Clone, Default)]
pub struct ConfigManager {

    // Public
    /// The path to the config directory.
    pub config_dir: String,

    // Private
    _config_list: Vec<Config>
}

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC METHODS-------------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigManager {

    /// Queries the config directory, and stores a list of configs.
    pub fn query_config_dir (&mut self) {

        // Clear the old config list
        self._config_list.clear ();

        info! ("Searching for config files...");

        // Recurse through all items in the config directory
        for path in glob (&format! ("{}/*{}", &self.config_dir, ".json")).unwrap ().filter_map (Result::ok) {

            self._config_list.push (Config {name: path.file_stem ().unwrap ().to_str ().unwrap ().to_string (),
                                            path: path.to_str ().unwrap ().to_string ()});

            info! ("Found: {:?}", &path.file_name ().unwrap ());
        }

        // If list is empty, print empty
        // Otherwise, print searching complete
        if self._config_list.is_empty () {
            info! ("No config files found.");
        }

        else {
            info! ("Config searching complete.");
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Loads a config of a given name.
    ///
    /// The config file is then converted into the type `T`. `T` must derive both the
    /// [`Serialize`] (http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html) and
    /// [`Deserialize`] (http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html) traits.
    ///
    /// If this fails, an [`Err`] (https://doc.rust-lang.org/std/result/) is returned.
    ///
    /// # Return value
    /// A result containing the config struct `T`.
    pub fn load_config<T: Serialize + Deserialize> (&self, config_name: &str) -> Result<T, ()> {

        debug! ("Loading config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::open (&item.path).unwrap ();
                let mut s = String::new ();

                f.read_to_string (&mut s).unwrap ();
                return Ok (serde_json::from_str::<T> (&s).unwrap ());
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves a config of a given name.
    pub fn save_config<T: Serialize + Deserialize> (&self, config_name: &str, data: &T) -> Result<(), ()> {

        debug! ("Saving config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::create (&item.path).unwrap ();
                f.write (serde_json::to_string_pretty (&data).unwrap ().as_bytes ()).unwrap ();
                return Ok (())
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC STATIC METHODS------------------------------------------------------*/
/*===============================================================================================*/

    /// Returns a new instance of the config manager.
    ///
    /// # Default values
    /// * `config_dir` - "config".to_string ()
    ///
    /// # Return value
    /// A new config manager instance.
    pub fn new () -> ConfigManager {

        ConfigManager {config_dir: "config".to_string (),
                       _config_list: Vec::new ()}
    }
}
<commit_msg>Added a method for checking if a config file exists<commit_after>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

extern crate glob;
extern crate serde;
extern crate serde_json;

use self::glob::glob;
use self::serde::{Serialize, Deserialize};

use std::io::{Read, Write};
use std::fs::File;
use std::vec::Vec;

/*===============================================================================================*/
/*------CONFIG STRUCT----------------------------------------------------------------------------*/
/*===============================================================================================*/

#[derive (Clone)]
pub struct Config {

    // Public
    /// The name of the config file.
    pub name: String,
    /// The path to the config file.
    pub path: String
}

/*===============================================================================================*/
/*------CONFIGMANAGER STRUCT---------------------------------------------------------------------*/
/*===============================================================================================*/

/// Handles the application config.
///
/// It is resposible for loading the app config, and allowing other modules easy access to that data.
/// It is also used for saving the app config.
#[derive (Clone, Default)]
pub struct ConfigManager {

    // Public
    /// The path to the config directory.
    pub config_dir: String,

    // Private
    _config_list: Vec<Config>
}

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC METHODS-------------------------------------------------------------*/
/*===============================================================================================*/

impl ConfigManager {

    /// Queries the config directory, and stores a list of configs.
    pub fn query_config_dir (&mut self) {

        // Clear the old config list
        self._config_list.clear ();

        info! ("Searching for config files...");

        // Recurse through all items in the config directory
        for path in glob (&format! ("{}/*{}", &self.config_dir, ".json")).unwrap ().filter_map (Result::ok) {

            self._config_list.push (Config {name: path.file_stem ().unwrap ().to_str ().unwrap ().to_string (),
                                            path: path.to_str ().unwrap ().to_string ()});

            info! ("Found: {:?}", &path.file_name ().unwrap ());
        }

        // If list is empty, print empty
        // Otherwise, print searching complete
        if self._config_list.is_empty () {
            info! ("No config files found.");
        }

        else {
            info! ("Config searching complete.");
        }
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Loads a config of a given name.
    ///
    /// The config file is then converted into the type `T`. `T` must derive both the
    /// [`Serialize`] (http://serde-rs.github.io/serde/serde/ser/trait.Serialize.html) and
    /// [`Deserialize`] (http://serde-rs.github.io/serde/serde/de/trait.Deserialize.html) traits.
    ///
    /// If this fails, an [`Err`] (https://doc.rust-lang.org/std/result/) is returned.
    ///
    /// # Return value
    /// A result containing the config struct `T`.
    pub fn load_config<T: Serialize + Deserialize> (&self, config_name: &str) -> Result<T, ()> {

        debug! ("Loading config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::open (&item.path).unwrap ();
                let mut s = String::new ();

                f.read_to_string (&mut s).unwrap ();
                return Ok (serde_json::from_str::<T> (&s).unwrap ());
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Saves a config of a given name.
    pub fn save_config<T: Serialize + Deserialize> (&self, config_name: &str, data: &T) -> Result<(), ()> {

        debug! ("Saving config file with name: '{}'", config_name);

        for item in &self._config_list {

            if item.name == config_name {

                let mut f = File::create (&item.path).unwrap ();
                f.write (serde_json::to_string_pretty (&data).unwrap ().as_bytes ()).unwrap ();
                return Ok (())
            }
        }

        warn! ("Could not find config file: '{}'.
                Try creating it first.", config_name);
        Err (())
    }

/*-----------------------------------------------------------------------------------------------*/

    /// Check if a config file exists.
    pub fn config_exists (&self, config_name: &str) -> bool {

        for item in &self._config_list {

            if item.name == config_name {
                return true;
            }
        }

        false
    }

/*===============================================================================================*/
/*------CONFIGMANAGER PUBLIC STATIC METHODS------------------------------------------------------*/
/*===============================================================================================*/

    /// Returns a new instance of the config manager.
    ///
    /// # Default values
    /// * `config_dir` - "config".to_string ()
    ///
    /// # Return value
    /// A new config manager instance.
    pub fn new () -> ConfigManager {

        ConfigManager {config_dir: "config".to_string (),
                       _config_list: Vec::new ()}
    }
}
<|endoftext|>


<commit_before>// vim: tw=80
#![cfg_attr(feature = "nightly", feature(specialization))]

use cfg_if::cfg_if;
use downcast::*;
use std::{
    any,
    collections::hash_map::{DefaultHasher, HashMap},
    hash::{Hash, Hasher},
    mem,
    ops::DerefMut,
    sync::Mutex
};

trait ExpectationT : Any + Send {}
downcast!(ExpectationT);

/// Return functions for expectations
enum Rfunc<I, O> {
    Default,
    // Indicates that a `return_once` expectation has already returned
    Expired,
    Mut(Box<dyn FnMut(I) -> O + Send>),
    // Should be Box<dyn FnOnce> once that feature is stabilized
    // https://github.com/rust-lang/rust/issues/28796
    Once(Box<dyn FnMut(I) -> O + Send>),
}

// TODO: change this to "impl FnMut" once unboxed_closures are stable
// https://github.com/rust-lang/rust/issues/29625
impl<I, O>  Rfunc<I, O> {
    fn call_mut(&mut self, args: I) -> O {
        match self {
            Rfunc::Default => {
                Self::return_default()
            },
            Rfunc::Expired => {
                panic!("Called a method twice that was expected only once")
            },
            Rfunc::Mut(f) => {
                f(args)
            },
            Rfunc::Once(_) => {
                let fo = mem::replace(self, Rfunc::Expired);
                if let Rfunc::Once(mut f) = fo {
                    f(args)
                } else {
                    unreachable!()
                }
            },
        }
    }
}

impl<I, O> Default for Rfunc<I, O> {
    fn default() -> Self {
        Rfunc::Default
    }
}

trait ReturnDefault<O> {
    fn return_default() -> O;
}

cfg_if! {
    if #[cfg(feature = "nightly")] {
        impl<I, O> ReturnDefault<O> for Rfunc<I, O> {
            default fn return_default() -> O {
                panic!("Can only return default values for types that impl std::Default");
            }
        }
    } else {
        impl<I, O> ReturnDefault<O> for Rfunc<I, O> {
            fn return_default() -> O {
                panic!("Returning default values requires the \"nightly\" feature");
            }
        }
    }
}

#[cfg(feature = "nightly")]
impl<I, O: Default> ReturnDefault<O> for Rfunc<I, O> {
    fn return_default() -> O {
        O::default()
    }
}

pub struct Expectation<I, O> {
    rfunc: Mutex<Rfunc<I, O>>
}

impl<I, O> Default for Expectation<I, O> {
    fn default() -> Self {
        Expectation::new()
    }
}

impl<I, O> Expectation<I, O> {
    pub fn call(&self, i: I) -> O {
        self.rfunc.lock().unwrap()
            .call_mut(i)
    }

    pub fn new() -> Self {
        let rfunc = Mutex::new(Rfunc::Default);
        Expectation{rfunc}
    }

    pub fn returning<F>(&mut self, f: F) -> &mut Self
        where F: FnMut(I) -> O + Send + 'static
    {
        {
            let mut guard = self.rfunc.lock().unwrap();
            mem::replace(guard.deref_mut(), Rfunc::Mut(Box::new(f)));
        }
        self
    }

    pub fn return_once<F>(&mut self, f: F) -> &mut Self
        where F: FnOnce(I) -> O + Send + 'static
    {
        let mut fopt = Some(f);
        let fmut = move |i| {
            if let Some(f) = fopt.take() {
                f(i)
            } else {
                panic!("Called a method twice that was expected only once")
            }
        };
        {
            let mut guard = self.rfunc.lock().unwrap();
            mem::replace(guard.deref_mut(), Rfunc::Once(Box::new(fmut)));
        }
        self
    }
}

impl<I: 'static, O: 'static> ExpectationT for Expectation<I, O> {}

/// Non-generic keys to `GenericExpectations` internal storage
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct Key(u64);

impl Key {
    fn new<I: 'static, O: 'static>(ident: &str) -> Self {
        let mut hasher = DefaultHasher::new();
        ident.hash(&mut hasher);
        any::TypeId::of::<(I, O)>().hash(&mut hasher);
        Key(hasher.finish())
    }
}

#[derive(Default)]
pub struct GenericExpectations {
    store: HashMap<Key, Box<dyn ExpectationT>>
}

impl GenericExpectations {
    pub fn expect<'e, I, O>(&'e mut self, ident: &str)
        -> &'e mut Expectation<I, O>
        where I: 'static, O: 'static
    {
        let key = Key::new::<I, O>(ident);
        let e = Box::new(Expectation::<I, O>::new());
        self.store.insert(key.clone(), e);
        self.store.get_mut(&key).unwrap()
            .downcast_mut()
            .unwrap()
    }

    // TODO: add a "called_nonstatic" method that can be used with types that
    // aren't 'static, and uses a different method to generate the key.
    pub fn called<I: 'static, O: 'static>(&self, ident: &str, args: I) -> O {
        let key = Key::new::<I, O>(ident);
        let e: &Expectation<I, O> = self.store.get(&key)
            .expect("No matching expectation found")
            .downcast_ref()
            .unwrap();
        e.call(args)
    }
}
<commit_msg>Slight simplification.  No functional change.<commit_after>// vim: tw=80
#![cfg_attr(feature = "nightly", feature(specialization))]

use cfg_if::cfg_if;
use downcast::*;
use std::{
    any,
    collections::hash_map::{DefaultHasher, HashMap},
    hash::{Hash, Hasher},
    mem,
    ops::DerefMut,
    sync::Mutex
};

trait ExpectationT : Any + Send {}
downcast!(ExpectationT);

/// Return functions for expectations
enum Rfunc<I, O> {
    Default,
    // Indicates that a `return_once` expectation has already returned
    Expired,
    Mut(Box<dyn FnMut(I) -> O + Send>),
    // Should be Box<dyn FnOnce> once that feature is stabilized
    // https://github.com/rust-lang/rust/issues/28796
    Once(Box<dyn FnMut(I) -> O + Send>),
}

// TODO: change this to "impl FnMut" once unboxed_closures are stable
// https://github.com/rust-lang/rust/issues/29625
impl<I, O>  Rfunc<I, O> {
    fn call_mut(&mut self, args: I) -> O {
        match self {
            Rfunc::Default => {
                Self::return_default()
            },
            Rfunc::Expired => {
                panic!("Called a method twice that was expected only once")
            },
            Rfunc::Mut(f) => {
                f(args)
            },
            Rfunc::Once(_) => {
                let fo = mem::replace(self, Rfunc::Expired);
                if let Rfunc::Once(mut f) = fo {
                    f(args)
                } else {
                    unreachable!()
                }
            },
        }
    }
}

impl<I, O> Default for Rfunc<I, O> {
    fn default() -> Self {
        Rfunc::Default
    }
}

trait ReturnDefault<O> {
    fn return_default() -> O;
}

cfg_if! {
    if #[cfg(feature = "nightly")] {
        impl<I, O> ReturnDefault<O> for Rfunc<I, O> {
            default fn return_default() -> O {
                panic!("Can only return default values for types that impl std::Default");
            }
        }

        impl<I, O: Default> ReturnDefault<O> for Rfunc<I, O> {
            fn return_default() -> O {
                O::default()
            }
        }
    } else {
        impl<I, O> ReturnDefault<O> for Rfunc<I, O> {
            fn return_default() -> O {
                panic!("Returning default values requires the \"nightly\" feature");
            }
        }
    }
}

pub struct Expectation<I, O> {
    rfunc: Mutex<Rfunc<I, O>>
}

impl<I, O> Default for Expectation<I, O> {
    fn default() -> Self {
        Expectation::new()
    }
}

impl<I, O> Expectation<I, O> {
    pub fn call(&self, i: I) -> O {
        self.rfunc.lock().unwrap()
            .call_mut(i)
    }

    pub fn new() -> Self {
        let rfunc = Mutex::new(Rfunc::Default);
        Expectation{rfunc}
    }

    pub fn returning<F>(&mut self, f: F) -> &mut Self
        where F: FnMut(I) -> O + Send + 'static
    {
        {
            let mut guard = self.rfunc.lock().unwrap();
            mem::replace(guard.deref_mut(), Rfunc::Mut(Box::new(f)));
        }
        self
    }

    pub fn return_once<F>(&mut self, f: F) -> &mut Self
        where F: FnOnce(I) -> O + Send + 'static
    {
        let mut fopt = Some(f);
        let fmut = move |i| {
            if let Some(f) = fopt.take() {
                f(i)
            } else {
                panic!("Called a method twice that was expected only once")
            }
        };
        {
            let mut guard = self.rfunc.lock().unwrap();
            mem::replace(guard.deref_mut(), Rfunc::Once(Box::new(fmut)));
        }
        self
    }
}

impl<I: 'static, O: 'static> ExpectationT for Expectation<I, O> {}

/// Non-generic keys to `GenericExpectations` internal storage
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
struct Key(u64);

impl Key {
    fn new<I: 'static, O: 'static>(ident: &str) -> Self {
        let mut hasher = DefaultHasher::new();
        ident.hash(&mut hasher);
        any::TypeId::of::<(I, O)>().hash(&mut hasher);
        Key(hasher.finish())
    }
}

#[derive(Default)]
pub struct GenericExpectations {
    store: HashMap<Key, Box<dyn ExpectationT>>
}

impl GenericExpectations {
    pub fn expect<'e, I, O>(&'e mut self, ident: &str)
        -> &'e mut Expectation<I, O>
        where I: 'static, O: 'static
    {
        let key = Key::new::<I, O>(ident);
        let e = Box::new(Expectation::<I, O>::new());
        self.store.insert(key.clone(), e);
        self.store.get_mut(&key).unwrap()
            .downcast_mut()
            .unwrap()
    }

    // TODO: add a "called_nonstatic" method that can be used with types that
    // aren't 'static, and uses a different method to generate the key.
    pub fn called<I: 'static, O: 'static>(&self, ident: &str, args: I) -> O {
        let key = Key::new::<I, O>(ident);
        let e: &Expectation<I, O> = self.store.get(&key)
            .expect("No matching expectation found")
            .downcast_ref()
            .unwrap();
        e.call(args)
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate pretty_assertions;

extern crate rexpect;

use rexpect::spawn;
use rexpect::errors::*;

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::process::{Command, Stdio};

#[test]
fn fmt_repl() {
    let source = "src/repl.glu";

    let mut before = String::new();
    File::open(source)
        .unwrap()
        .read_to_string(&mut before)
        .unwrap();

    let status = Command::new("../target/debug/gluon")
        .args(&["fmt", source])
        .spawn()
        .expect("Could not find gluon executable")
        .wait()
        .unwrap();
    assert!(status.success());

    let mut after = String::new();
    File::open(source)
        .unwrap()
        .read_to_string(&mut after)
        .unwrap();

    assert_eq!(before, after);
}

#[test]
fn issue_365_run_io_from_command_line() {
    if ::std::env::var("GLUON_PATH").is_err() {
        ::std::env::set_var("GLUON_PATH", "..");
    }

    let path = env::args().next().unwrap();
    let gluon_path = Path::new(&path[..])
        .parent()
        .and_then(|p| p.parent())
        .expect("folder")
        .join("gluon");
    let output = Command::new(&*gluon_path)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .arg("tests/print.glu")
        .output()
        .unwrap_or_else(|err| panic!("{}\nWhen opening `{}`", err, gluon_path.display()));

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr != "" {
        panic!("{}", stderr);
    }
    assert_eq!(String::from_utf8_lossy(&output.stdout), "123\n");
}

static COMMAND: &str = "../target/debug/gluon -i";
static TIMEOUT: u64 = 10_000;
static PROMPT: &str = "> ";

macro_rules! test {
    ($b: block) => {
        || -> Result<()> {
            $b
        }().unwrap_or_else(|err| panic!("{}", err));
    };
}

#[test]
fn prompt() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        Ok(())
    });
}

#[test]
fn exit() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line(":q")?;
        repl.exp_eof()?;

        Ok(())
    });
}

#[test]
#[ignore] // TODO fix intermittent test failure
fn hello_world() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("let io = import! std.io")?;

        repl.send_line("io.println \"Hello world\"")?;
        repl.exp_string("Hello world")?;

        Ok(())
    });
}

#[test]
fn expression_types() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line(":t 5")?;
        repl.exp_string("Int")?;

        repl.send_line(":t 5 + 5")?;
        repl.exp_string("Int -> Int")?;

        repl.send_line(":t \"gluon\"")?;
        repl.exp_string("String")?;

        Ok(())
    });
}

#[test]
fn names() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line(":i std.prelude.show")?;
        repl.exp_string("std.prelude.show: forall a . [std.prelude.Show a] -> a -> String")?;

        Ok(())
    });
}

#[test]
fn comments() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("1 + 2 // Calls the + function on 1 and 2")?;
        repl.exp_string("3")?;

        repl.send_line("1 + 2 /* Calls the + function on 1 and 2 */")?;
        repl.exp_string("3")?;

        Ok(())
    });
}

#[test]
fn if_expressions() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("if True then 1 else 0")?;
        repl.exp_string("1")?;

        repl.send_line("if False then 1 else 0")?;
        repl.exp_string("0")?;

        Ok(())
    });
}

#[test]
fn records() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("let record = { pi = 3.14, add1 = (+) 1.0 }")?;

        repl.send_line("record.pi")?;
        repl.exp_string("3.14")?;

        repl.send_line("let record_2 = {x = 1 .. record }")?;

        repl.send_line("record_2.x")?;
        repl.exp_string("1")?;

        repl.send_line("record_2.pi")?;
        repl.exp_string("3.14")?;

        Ok(())
    });
}

#[test]
fn arrays() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("let array = import! std.array")?;

        repl.send_line("array.len [1, 2, 3]")?;
        repl.exp_string("3")?;

        Ok(())
    });
}
<commit_msg>Add environment variable to tests.<commit_after>#[macro_use]
extern crate pretty_assertions;

extern crate rexpect;

use rexpect::spawn;
use rexpect::errors::*;

use std::env;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::process::{Command, Stdio};

#[test]
fn fmt_repl() {
    let source = "src/repl.glu";

    let mut before = String::new();
    File::open(source)
        .unwrap()
        .read_to_string(&mut before)
        .unwrap();

    let status = Command::new("../target/debug/gluon")
        .args(&["fmt", source])
        .spawn()
        .expect("Could not find gluon executable")
        .wait()
        .unwrap();
    assert!(status.success());

    let mut after = String::new();
    File::open(source)
        .unwrap()
        .read_to_string(&mut after)
        .unwrap();

    assert_eq!(before, after);
}

#[test]
fn issue_365_run_io_from_command_line() {
    if ::std::env::var("GLUON_PATH").is_err() {
        ::std::env::set_var("GLUON_PATH", "..");
    }

    let path = env::args().next().unwrap();
    let gluon_path = Path::new(&path[..])
        .parent()
        .and_then(|p| p.parent())
        .expect("folder")
        .join("gluon");
    let output = Command::new(&*gluon_path)
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .stderr(Stdio::piped())
        .arg("tests/print.glu")
        .output()
        .unwrap_or_else(|err| panic!("{}\nWhen opening `{}`", err, gluon_path.display()));

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr != "" {
        panic!("{}", stderr);
    }
    assert_eq!(String::from_utf8_lossy(&output.stdout), "123\n");
}

static COMMAND: &str = "../target/debug/gluon -i";
static TIMEOUT: u64 = 10_000;
static PROMPT: &str = "> ";

macro_rules! test {
    ($b: block) => {
        if ::std::env::var("GLUON_PATH").is_err() {
            ::std::env::set_var("GLUON_PATH", "..");
        }

        || -> Result<()> {
            $b
        }().unwrap_or_else(|err| panic!("{}", err));
    };
}

#[test]
fn prompt() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        Ok(())
    });
}

#[test]
fn exit() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line(":q")?;
        repl.exp_eof()?;

        Ok(())
    });
}

#[test]
fn hello_world() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("let io = import! std.io")?;

        repl.send_line("io.println \"Hello world\"")?;
        repl.exp_string("Hello world")?;

        Ok(())
    });
}

#[test]
fn expression_types() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line(":t 5")?;
        repl.exp_string("Int")?;

        repl.send_line(":t 5 + 5")?;
        repl.exp_string("Int -> Int")?;

        repl.send_line(":t \"gluon\"")?;
        repl.exp_string("String")?;

        Ok(())
    });
}

#[test]
fn names() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line(":i std.prelude.show")?;
        repl.exp_string("std.prelude.show: forall a . [std.prelude.Show a] -> a -> String")?;

        Ok(())
    });
}

#[test]
fn comments() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("1 + 2 // Calls the + function on 1 and 2")?;
        repl.exp_string("3")?;

        repl.send_line("1 + 2 /* Calls the + function on 1 and 2 */")?;
        repl.exp_string("3")?;

        Ok(())
    });
}

#[test]
fn if_expressions() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("if True then 1 else 0")?;
        repl.exp_string("1")?;

        repl.send_line("if False then 1 else 0")?;
        repl.exp_string("0")?;

        Ok(())
    });
}

#[test]
fn records() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("let record = { pi = 3.14, add1 = (+) 1.0 }")?;

        repl.send_line("record.pi")?;
        repl.exp_string("3.14")?;

        repl.send_line("let record_2 = {x = 1 .. record }")?;

        repl.send_line("record_2.x")?;
        repl.exp_string("1")?;

        repl.send_line("record_2.pi")?;
        repl.exp_string("3.14")?;

        Ok(())
    });
}

#[test]
fn arrays() {
    test!({
        let mut repl = spawn(COMMAND, Some(TIMEOUT))?;
        repl.exp_string(PROMPT)?;

        repl.send_line("let array = import! std.array")?;

        repl.send_line("array.len [1, 2, 3]")?;
        repl.exp_string("3")?;

        Ok(())
    });
}
<|endoftext|>


<commit_before>// Copyright © 2012 Bart Massey
// [This program is licensed under the "MIT License"]
// Please see the file COPYING in the source
// distribution of this software for license terms.

// CipherSaber
// http://ciphersaber.gurus.com

extern crate getopts;
extern crate rpassword;

use getopts::Options;
use rpassword::read_password;
use std::default::Default;
use std::env;
use std::fs::File;
use std::io::{stdin, stdout, Read, Write};
use std::path::Path;
use std::error::Error;

fn mkiv(ivb: &mut [u8;10]) {
    // http://rustbyexample.com/std_misc/file/open.html
    let urandom = Path::new("/dev/urandom");
    let mut fd = match File::open(&urandom) {
        Err(why) => panic!("couldn't open {}: {}",
                           urandom.display(),
                           why.description()),
        Ok(file) => file
    };
    let ok = fd.read_exact(ivb);
    match ok {
        Ok(()) => (),
        _ => panic!("couldn't read {}", urandom.display())
    }
}

enum Dirn {
    Encrypt,
    Decrypt
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut opts = Options::new();
    opts.optflag("e", "encrypt", "encrypt input to output");
    opts.optflag("d", "decrypt", "decrypt input to output");
    opts.optopt("k", "key", "KEY", "key on command line (dangerous)");
    opts.optopt("r", "reps", "N",
                "number of key-scheduling reps (default 20)");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string())
    };
    let en = matches.opt_present("e");
    let de = matches.opt_present("d");
    if en && de {
        panic!("cannot both encrypt and decrypt");
    }
    if !en && !de {
        panic!("must encrypt or decrypt");
    }
    let dirn = if en {
        Dirn::Encrypt
    } else {
        assert!(de);
        Dirn::Decrypt
    };
    let mut keybytes: Vec<u8> = vec![];
    match matches.opt_str("k") {
        Some(s) => keybytes.extend_from_slice(s.as_bytes()),
        _ => {
            let ok = read_password();
            match ok {
                Ok(s) => keybytes.extend_from_slice(s.as_bytes()),
                _ => panic!("password read error")
            }
        }
    };
    let reps = match matches.opt_str("r") {
        Some(rs) => rs.trim().parse().expect("bad rep count"),
        _ => 20
    };

    let mut sin = stdin();
    let mut sout = stdout();
    let mut ivb: [u8;10] = [Default::default();10];
    match dirn {
        Dirn::Encrypt => {
            mkiv(&mut ivb);
            sout.write(&mut ivb).expect("write failed");
        }
        Dirn::Decrypt => {
            let ok = sin.read_exact(&mut ivb);
            match ok {
                Ok(()) => (),
                _ => panic!("couldn't read iv")
            }
        }
    };
    keybytes.extend_from_slice(&ivb);

    let mut state: [u8;256] = [Default::default();256];
    for k in 0..256 {
        state[k] = k as u8;
    }
    let kl = keybytes.len();
    let mut i: usize = 0;
    for _ in 0..reps {
        for j in 0..256 {
            i = (i + state[j] as usize + keybytes[j % kl] as usize) & 0xff;
            let tmp = state[j];
            state[j] = state[i];
            state[i] = tmp;
        }
    }

    let mut i: usize = 0;
    let mut j: usize = 0;
    for ch in sin.bytes() {
        i = (i + 1) & 0xff;
        j = (j + state[i] as usize) & 0xff;
        let si = state[i];
        let sj = state[j];
        state[i] = sj;
        state[j] = si;
        let plain = ch.unwrap();
        let cipher = state[(si as usize + sj as usize) & 0xff] ^ plain;
        let b = [cipher];
        match sout.write(&b) {
            Ok(_) => (),
            _ => panic!("write error")
        };
    }
}
<commit_msg>cleaned up error handling in rust<commit_after>// Copyright © 2012 Bart Massey
// [This program is licensed under the "MIT License"]
// Please see the file COPYING in the source
// distribution of this software for license terms.

// CipherSaber
// http://ciphersaber.gurus.com

extern crate getopts;
extern crate rpassword;

use getopts::Options;
use rpassword::read_password;
use std::default::Default;
use std::env;
use std::fs::File;
use std::io::{stdin, stdout, Read, Write};
use std::path::Path;
use std::error::Error;

fn mkiv(ivb: &mut [u8;10]) {
    // http://rustbyexample.com/std_misc/file/open.html
    let urandom = Path::new("/dev/urandom");
    let mut fd = match File::open(&urandom) {
        Err(why) => panic!("couldn't open {}: {}",
                           urandom.display(),
                           why.description()),
        Ok(file) => file
    };
    fd.read_exact(ivb).expect(&format!("couldn't read {}", urandom.display()));
}

enum Dirn {
    Encrypt,
    Decrypt
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut opts = Options::new();
    opts.optflag("e", "encrypt", "encrypt input to output");
    opts.optflag("d", "decrypt", "decrypt input to output");
    opts.optopt("k", "key", "KEY", "key on command line (dangerous)");
    opts.optopt("r", "reps", "N",
                "number of key-scheduling reps (default 20)");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => panic!(f.to_string())
    };
    let en = matches.opt_present("e");
    let de = matches.opt_present("d");
    if en && de {
        panic!("cannot both encrypt and decrypt");
    }
    if !en && !de {
        panic!("must encrypt or decrypt");
    }
    let dirn = if en {
        Dirn::Encrypt
    } else {
        assert!(de);
        Dirn::Decrypt
    };
    let mut keybytes: Vec<u8> = vec![];
    match matches.opt_str("k") {
        Some(s) => keybytes.extend_from_slice(s.as_bytes()),
        _ => {
            let s = read_password().expect("password read error");
            keybytes.extend_from_slice(s.as_bytes());
        }
    };
    let reps = match matches.opt_str("r") {
        Some(rs) => rs.trim().parse().expect("bad rep count"),
        _ => 20
    };

    let mut sin = stdin();
    let mut sout = stdout();
    let mut ivb: [u8;10] = [Default::default();10];
    match dirn {
        Dirn::Encrypt => {
            mkiv(&mut ivb);
            sout.write(&mut ivb).expect("write failed");
        }
        Dirn::Decrypt => {
            sin.read_exact(&mut ivb).expect("couldn't read iv");
        }
    };
    keybytes.extend_from_slice(&ivb);

    let mut state: [u8;256] = [Default::default();256];
    for k in 0..256 {
        state[k] = k as u8;
    }
    let kl = keybytes.len();
    let mut i: usize = 0;
    for _ in 0..reps {
        for j in 0..256 {
            i = (i + state[j] as usize + keybytes[j % kl] as usize) & 0xff;
            let tmp = state[j];
            state[j] = state[i];
            state[i] = tmp;
        }
    }

    let mut i: usize = 0;
    let mut j: usize = 0;
    for ch in sin.bytes() {
        i = (i + 1) & 0xff;
        j = (j + state[i] as usize) & 0xff;
        let si = state[i];
        let sj = state[j];
        state[i] = sj;
        state[j] = si;
        let plain = ch.unwrap();
        let cipher = state[(si as usize + sj as usize) & 0xff] ^ plain;
        let b = [cipher];
        sout.write(&b).expect("write error");
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate core;

use self::core::mem;
use self::core::marker;
use super::CVoid;

#[repr(C)]
#[derive(Debug)]
struct MailboxInt {
    msg_buf: *mut u8,
    msg_buf_len: u32,
    msg_size: u32,
    read_pos: u32,
    write_pos: u32,
    data_added: Option<extern "C" fn()>,
}

impl Default for MailboxInt {
    fn default() -> Self { unsafe { mem::zeroed() } }
}

#[repr(C)]
#[derive(Debug)]
pub struct Mailbox<T> {
    mb: MailboxInt,
    data_type_marker: marker::PhantomData<T>
}

impl<T> Default for Mailbox<T> {
    fn default() -> Self { unsafe { mem::zeroed() } }
}

#[link (name = "mouros")]
extern "C" {
    fn os_mailbox_init(mb: *mut MailboxInt,
                       msg_buf: *mut CVoid,
                       msg_buf_len: u32,
                       msg_size: u32,
                       data_added_callback: Option<extern fn()>);

    fn os_mailbox_write(mb: *mut MailboxInt,
                        msg: *const CVoid) -> u8;

    fn os_mailbox_write_multiple(mb: *mut MailboxInt,
                                 msgs: *const CVoid,
                                 msg_num: u32) -> u32;

    fn os_mailbox_read(mb: *mut MailboxInt,
                       out: *mut CVoid) -> u8;

    fn os_mailbox_read_multiple(mb: *mut MailboxInt,
                                out: *mut CVoid,
                                out_msg_num: u32) -> u32;
}

impl<T> Mailbox<T> {

    pub fn new(buf: &mut [T]) -> Mailbox<T> {
        let mut mb = Mailbox::default();

        unsafe {
            os_mailbox_init(&mut mb.mb,
                            buf.as_mut_ptr() as *mut CVoid,
                            buf.len() as u32,
                            mem::size_of::<T>() as u32,
                            None);
        }

        mb
    }

    pub fn write(&mut self, msg: T) -> bool {
        unsafe {
            os_mailbox_write(&mut self.mb, &msg as *const T as *const CVoid) != 0
        }
    }

    pub fn write_multiple(&mut self, msgs: &[T]) -> u32 {
        unsafe {
            os_mailbox_write_multiple(&mut self.mb,
                                      msgs.as_ptr() as *const CVoid,
                                      msgs.len() as u32)
        }
    }

    pub fn read(&mut self) -> Option<T> {
        unsafe {
            let mut tmp = mem::zeroed();

            if os_mailbox_read(&mut self.mb, &mut tmp as *mut T as *mut CVoid) != 0 {
                Some(tmp)
            } else {
                None
            }
        }
    }

    pub fn read_multiple(&mut self, out_buf: &mut [T]) -> u32 {
        unsafe {
            os_mailbox_read_multiple(&mut self.mb,
                                     out_buf.as_mut_ptr() as *mut CVoid,
                                     out_buf.len() as u32)
        }
    }
}
<commit_msg>Renamed the Mailbox raw message struct<commit_after>#![allow(dead_code)]

use core::mem;
use core::marker;
use super::CVoid;

#[repr(C)]
#[derive(Debug)]
pub struct MailboxRaw {
    msg_buf: *mut u8,
    msg_buf_len: u32,
    msg_size: u32,
    read_pos: u32,
    write_pos: u32,
    data_added: Option<extern "C" fn()>,
}

impl Default for MailboxRaw {
    fn default() -> Self {
        unsafe { mem::zeroed() }
    }
}

#[repr(C)]
#[derive(Debug)]
pub struct Mailbox<T> {
    mb: MailboxRaw,
    data_type_marker: marker::PhantomData<T>,
}

impl<T> Default for Mailbox<T> {
    fn default() -> Self {
        unsafe { mem::zeroed() }
    }
}

#[link (name = "mouros")]
extern "C" {
    fn os_mailbox_init(mb: *mut MailboxRaw,
                       msg_buf: *mut CVoid,
                       msg_buf_len: u32,
                       msg_size: u32,
                       data_added_callback: Option<extern "C" fn()>);

    fn os_mailbox_write(mb: *mut MailboxRaw, msg: *const CVoid) -> u8;

    fn os_mailbox_write_multiple(mb: *mut MailboxRaw, msgs: *const CVoid, msg_num: u32) -> u32;

    fn os_mailbox_read(mb: *mut MailboxRaw, out: *mut CVoid) -> u8;

    fn os_mailbox_read_multiple(mb: *mut MailboxRaw, out: *mut CVoid, out_msg_num: u32) -> u32;
}

impl<T> Mailbox<T> {
    pub fn new(buf: &mut [T]) -> Mailbox<T> {
        let mut mb = Mailbox::default();

        unsafe {
            os_mailbox_init(&mut mb.mb,
                            buf.as_mut_ptr() as *mut CVoid,
                            buf.len() as u32,
                            mem::size_of::<T>() as u32,
                            None);
        }

        mb
    }

    pub fn write(&mut self, msg: T) -> bool {
        unsafe { os_mailbox_write(&mut self.mb, &msg as *const T as *const CVoid) != 0 }
    }

    pub fn write_multiple(&mut self, msgs: &[T]) -> u32 {
        unsafe {
            os_mailbox_write_multiple(&mut self.mb,
                                      msgs.as_ptr() as *const CVoid,
                                      msgs.len() as u32)
        }
    }

    pub fn read(&mut self) -> Option<T> {
        unsafe {
            let mut tmp = mem::zeroed();

            if os_mailbox_read(&mut self.mb, &mut tmp as *mut T as *mut CVoid) != 0 {
                Some(tmp)
            } else {
                None
            }
        }
    }

    pub fn read_multiple(&mut self, out_buf: &mut [T]) -> u32 {
        unsafe {
            os_mailbox_read_multiple(&mut self.mb,
                                     out_buf.as_mut_ptr() as *mut CVoid,
                                     out_buf.len() as u32)
        }
    }

    pub unsafe fn get_raw_mb_struct(&mut self) -> *mut MailboxRaw {
        &mut self.mb
    }
}
<|endoftext|>


<commit_before>//! Print sizes of structs and enums
//!
//! Run with `cargo test sizes -- --nocapture`
//! to get the printed output.

use std::collections::BTreeMap;

use stencila_schema::*;

macro_rules! sizeof {
    ($type:ty) => {{
        let size = std::mem::size_of::<$type>();
        println!("{}: {}", stringify!($type), size);
        size
    }};
}

#[test]
fn sizes() {
    println!("");
    println!("----------------------------------------------");
    sizeof!(Node);
    println!("----------------------------------------------");
    sizeof!(ArrayValidator);
    sizeof!(Article);
    sizeof!(AudioObject);
    sizeof!(BooleanValidator);
    sizeof!(Brand);
    sizeof!(CitationIntentEnumeration);
    sizeof!(Cite);
    sizeof!(CiteGroup);
    sizeof!(Claim);
    sizeof!(Code);
    sizeof!(CodeBlock);
    sizeof!(CodeChunk);
    sizeof!(CodeError);
    sizeof!(CodeExpression);
    sizeof!(CodeFragment);
    sizeof!(Collection);
    sizeof!(Comment);
    sizeof!(ConstantValidator);
    sizeof!(ContactPoint);
    sizeof!(CreativeWork);
    sizeof!(Datatable);
    sizeof!(DatatableColumn);
    sizeof!(Date);
    sizeof!(DefinedTerm);
    sizeof!(Delete);
    sizeof!(Emphasis);
    sizeof!(EnumValidator);
    sizeof!(Enumeration);
    sizeof!(Figure);
    sizeof!(Function);
    sizeof!(Grant);
    sizeof!(Heading);
    sizeof!(ImageObject);
    sizeof!(Include);
    sizeof!(IntegerValidator);
    sizeof!(Link);
    sizeof!(List);
    sizeof!(ListItem);
    sizeof!(Mark);
    sizeof!(Math);
    sizeof!(MathBlock);
    sizeof!(MathFragment);
    sizeof!(MediaObject);
    sizeof!(MonetaryGrant);
    sizeof!(NontextualAnnotation);
    sizeof!(Note);
    sizeof!(NumberValidator);
    sizeof!(Organization);
    sizeof!(Paragraph);
    sizeof!(Parameter);
    sizeof!(Periodical);
    sizeof!(Person);
    sizeof!(PostalAddress);
    sizeof!(Product);
    sizeof!(PropertyValue);
    sizeof!(PublicationIssue);
    sizeof!(PublicationVolume);
    sizeof!(Quote);
    sizeof!(QuoteBlock);
    sizeof!(Review);
    sizeof!(SoftwareApplication);
    sizeof!(SoftwareEnvironment);
    sizeof!(SoftwareSession);
    sizeof!(SoftwareSourceCode);
    sizeof!(StringValidator);
    sizeof!(Strong);
    sizeof!(Subscript);
    sizeof!(Superscript);
    sizeof!(Table);
    sizeof!(TableCell);
    sizeof!(TableRow);
    sizeof!(ThematicBreak);
    sizeof!(Thing);
    sizeof!(TupleValidator);
    sizeof!(Validator);
    sizeof!(Variable);
    sizeof!(VideoObject);
    sizeof!(VolumeMount);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    sizeof!(InlineContent);
    println!("----------------------------------------------");
    sizeof!(AudioObjectSimple);
    sizeof!(Cite);
    sizeof!(CiteGroup);
    sizeof!(CodeExpression);
    sizeof!(CodeFragment);
    sizeof!(Delete);
    sizeof!(Emphasis);
    sizeof!(ImageObjectSimple);
    sizeof!(Link);
    sizeof!(MathFragment);
    sizeof!(NontextualAnnotation);
    sizeof!(Note);
    sizeof!(Quote);
    sizeof!(Strong);
    sizeof!(Subscript);
    sizeof!(Superscript);
    sizeof!(VideoObjectSimple);
    sizeof!(bool);
    sizeof!(i64);
    sizeof!(f64);
    sizeof!(Vec<Primitive>);
    sizeof!(BTreeMap<String, Primitive>);
    sizeof!(String);
    sizeof!(Option<Box<String>>);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    sizeof!(BlockContent);
    println!("----------------------------------------------");
    sizeof!(ClaimSimple);
    sizeof!(CodeBlock);
    sizeof!(CodeChunk);
    sizeof!(CollectionSimple);
    sizeof!(FigureSimple);
    sizeof!(Heading);
    sizeof!(List);
    sizeof!(MathBlock);
    sizeof!(Paragraph);
    sizeof!(QuoteBlock);
    sizeof!(TableSimple);
    sizeof!(ThematicBreak);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    sizeof!(CreativeWorkTypes);
    println!("----------------------------------------------");
    sizeof!(CreativeWork);
    sizeof!(Article);
    sizeof!(AudioObject);
    sizeof!(Claim);
    sizeof!(Collection);
    sizeof!(Comment);
    sizeof!(Datatable);
    sizeof!(Figure);
    sizeof!(ImageObject);
    sizeof!(MediaObject);
    sizeof!(Periodical);
    sizeof!(PublicationIssue);
    sizeof!(PublicationVolume);
    sizeof!(Review);
    sizeof!(SoftwareApplication);
    sizeof!(SoftwareSourceCode);
    sizeof!(Table);
    sizeof!(VideoObject);
    println!("----------------------------------------------");
}
<commit_msg>test(Rust): Sizes<commit_after>//! Print sizes of structs and enums
//!
//! Run with `cargo test sizes -- --nocapture`
//! to get the printed output.

use std::collections::BTreeMap;

use stencila_schema::*;

macro_rules! sizeof {
    ($type:ty) => {{
        let size = std::mem::size_of::<$type>();
        println!("{}: {}", stringify!($type), size);
        size
    }};
}

#[test]
fn sizes() {
    println!("");
    println!("----------------------------------------------");
    sizeof!(Node);
    println!("----------------------------------------------");
    sizeof!(ArrayValidator);
    sizeof!(Article);
    sizeof!(AudioObject);
    sizeof!(BooleanValidator);
    sizeof!(Brand);
    sizeof!(CitationIntentEnumeration);
    sizeof!(Cite);
    sizeof!(CiteGroup);
    sizeof!(Claim);
    sizeof!(Code);
    sizeof!(CodeBlock);
    sizeof!(CodeChunk);
    sizeof!(CodeError);
    sizeof!(CodeExpression);
    sizeof!(CodeFragment);
    sizeof!(Collection);
    sizeof!(Comment);
    sizeof!(ConstantValidator);
    sizeof!(ContactPoint);
    sizeof!(CreativeWork);
    sizeof!(Datatable);
    sizeof!(DatatableColumn);
    sizeof!(Date);
    sizeof!(DefinedTerm);
    sizeof!(Delete);
    sizeof!(Emphasis);
    sizeof!(EnumValidator);
    sizeof!(Enumeration);
    sizeof!(Figure);
    sizeof!(Function);
    sizeof!(Grant);
    sizeof!(Heading);
    sizeof!(ImageObject);
    sizeof!(Include);
    sizeof!(IntegerValidator);
    sizeof!(Link);
    sizeof!(List);
    sizeof!(ListItem);
    sizeof!(Mark);
    sizeof!(Math);
    sizeof!(MathBlock);
    sizeof!(MathFragment);
    sizeof!(MediaObject);
    sizeof!(MonetaryGrant);
    sizeof!(NontextualAnnotation);
    sizeof!(Note);
    sizeof!(NumberValidator);
    sizeof!(Organization);
    sizeof!(Paragraph);
    sizeof!(Parameter);
    sizeof!(Periodical);
    sizeof!(Person);
    sizeof!(PostalAddress);
    sizeof!(Product);
    sizeof!(PropertyValue);
    sizeof!(PublicationIssue);
    sizeof!(PublicationVolume);
    sizeof!(Quote);
    sizeof!(QuoteBlock);
    sizeof!(Review);
    sizeof!(SoftwareApplication);
    sizeof!(SoftwareEnvironment);
    sizeof!(SoftwareSession);
    sizeof!(SoftwareSourceCode);
    sizeof!(StringValidator);
    sizeof!(Strong);
    sizeof!(Subscript);
    sizeof!(Superscript);
    sizeof!(Table);
    sizeof!(TableCell);
    sizeof!(TableRow);
    sizeof!(ThematicBreak);
    sizeof!(Thing);
    sizeof!(TupleValidator);
    sizeof!(Validator);
    sizeof!(Variable);
    sizeof!(VideoObject);
    sizeof!(VolumeMount);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    sizeof!(InlineContent);
    println!("----------------------------------------------");
    sizeof!(AudioObjectSimple);
    sizeof!(Cite);
    sizeof!(CiteGroup);
    sizeof!(CodeExpression);
    sizeof!(CodeFragment);
    sizeof!(Delete);
    sizeof!(Emphasis);
    sizeof!(ImageObjectSimple);
    sizeof!(Link);
    sizeof!(MathFragment);
    sizeof!(NontextualAnnotation);
    sizeof!(Note);
    sizeof!(Quote);
    sizeof!(Strong);
    sizeof!(Subscript);
    sizeof!(Superscript);
    sizeof!(VideoObjectSimple);
    sizeof!(bool);
    sizeof!(i64);
    sizeof!(f64);
    sizeof!(String);
    sizeof!(Vec<Primitive>);
    sizeof!(BTreeMap<String, Primitive>);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    sizeof!(BlockContent);
    println!("----------------------------------------------");
    sizeof!(ClaimSimple);
    sizeof!(CodeBlock);
    sizeof!(CodeChunk);
    sizeof!(CollectionSimple);
    sizeof!(FigureSimple);
    sizeof!(Heading);
    sizeof!(Include);
    sizeof!(List);
    sizeof!(MathBlock);
    sizeof!(Paragraph);
    sizeof!(QuoteBlock);
    sizeof!(TableSimple);
    sizeof!(ThematicBreak);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    sizeof!(CreativeWorkTypes);
    println!("----------------------------------------------");
    sizeof!(CreativeWork);
    sizeof!(Article);
    sizeof!(AudioObject);
    sizeof!(Claim);
    sizeof!(Collection);
    sizeof!(Comment);
    sizeof!(Datatable);
    sizeof!(Figure);
    sizeof!(ImageObject);
    sizeof!(MediaObject);
    sizeof!(Periodical);
    sizeof!(PublicationIssue);
    sizeof!(PublicationVolume);
    sizeof!(Review);
    sizeof!(SoftwareApplication);
    sizeof!(SoftwareSourceCode);
    sizeof!(Table);
    sizeof!(VideoObject);
    println!("----------------------------------------------");

    println!("");
    println!("----------------------------------------------");
    println!("Reference");
    println!("----------------------------------------------");
    sizeof!(String);
    sizeof!(Option<String>);
    sizeof!(Option<Box<String>>);
    println!("----------------------------------------------");
}
<|endoftext|>


<commit_before>use data::packet::Packet;
use data::rational::Rational64;
use stream::Stream;
use error::*;

use buffer::Buffered;
use std::io::SeekFrom;

#[derive(Clone, Debug, PartialEq)]
pub struct GlobalInfo {
    pub duration: Option<u64>,
    pub timebase: Option<Rational64>,
    pub streams: Vec<Stream>,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Event {
    NewPacket(Packet),
    NewStream(Stream),
    MoreDataNeeded,
}

pub trait Demuxer {
    fn read_headers(&mut self, buf: &Box<Buffered>, info: &mut GlobalInfo) -> Result<SeekFrom>;
    fn read_event(&mut self, buf: &Box<Buffered>) -> Result<(SeekFrom, Event)>;
}

#[derive(Clone, Debug, PartialEq)]
pub struct Descr {
    pub name: &'static str,
    pub demuxer: &'static str,
    pub description: &'static str,
    pub extensions: &'static [&'static str],
    pub mime: &'static [&'static str],
}

pub trait Descriptor {
    fn create(&self) -> Box<Demuxer>;
    fn describe<'a>(&'a self) -> &'a Descr;

    fn probe(&self, data: &[u8]) -> u8;
}

pub struct Context {
    demuxer: Box<Demuxer>,
    reader: Box<Buffered>,
    pub info: GlobalInfo,
}

impl Context {
    pub fn new<R: Buffered + 'static>(demuxer: Box<Demuxer>, reader: Box<R>) -> Self {
        Context {
            demuxer: demuxer,
            reader: reader,
            info: GlobalInfo {
                duration: None,
                timebase: None,
                streams: Vec::with_capacity(2),
            },
        }
    }

    pub fn read_headers(&mut self) -> Result<()> {
        let ref mut demux = self.demuxer;

        let res = demux.read_headers(&self.reader, &mut self.info);
        match res {
            Err(e) => Err(e),
            Ok(seek) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                try!(self.reader.fill_buf());
                println!("stream now at index: {:?}", res);
                Ok(())
            }
        }
    }

    pub fn read_event(&mut self) -> Result<Event> {
        let ref mut demux = self.demuxer;

        let res = demux.read_event(&self.reader);
        match res {
            Err(e) => Err(e),
            Ok((seek, event)) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                try!(self.reader.fill_buf());
                if let Event::NewStream(ref st) = event {
                    self.info.streams.push(st.clone());
                }
                println!("stream now at index: {:?}", res);
                Ok(event)
            }
        }
    }
}

pub const PROBE_DATA: usize = 4 * 1024;
pub const PROBE_SCORE_EXTENSION: u8 = 50;

// TODO:
// IntoIterator<Item = &'static Descriptor> is confusing

pub trait Probe {
    fn probe(&self, data: &[u8]) -> Option<&'static Descriptor>;
}

impl<'a> Probe for [&'static Descriptor] {
    fn probe(&self, data: &[u8]) -> Option<&'static Descriptor> {
        let mut max = u8::min_value();
        let mut candidate: Option<&'static Descriptor> = None;
        for desc in self {
            let score = desc.probe(data);

            if score > max {
                max = score;
                candidate = Some(*desc);
            }
        }

        if max > PROBE_SCORE_EXTENSION {
            candidate
        } else {
            None
        }
    }
}

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

    struct DummyDes {
        d: Descr,
    }

    struct DummyDemuxer {}

    impl Demuxer for DummyDemuxer {
        fn read_headers(&mut self, _buf: &Box<Buffered>, _info: &mut GlobalInfo) -> Result<SeekFrom> {
            unimplemented!()
        }
        fn read_event(&mut self, _buf: &Box<Buffered>) -> Result<(SeekFrom, Event)> {
            unimplemented!()
        }
    }

    impl Descriptor for DummyDes {
        fn create(&self) -> Box<Demuxer> {
            Box::new(DummyDemuxer {})
        }
        fn describe<'a>(&'a self) -> &'a Descr {
            &self.d
        }
        fn probe(&self, data: &[u8]) -> u8 {
            match data {
                b"dummy" => 100,
                _ => 0,
            }
        }
    }

    const DUMMY_DES: &Descriptor = &DummyDes {
        d: Descr {
            name: "dummy",
            demuxer: "dummy",
            description: "Dummy dem",
            extensions: &["dm", "dum"],
            mime: &["application/dummy"],
        },
    };

    #[test]
    fn probe() {
        let codecs: &[&'static Descriptor] = &[DUMMY_DES];

        codecs.probe(b"dummy").unwrap();
    }
}
<commit_msg>format: Always refill the buffer before calling the inner read_header<commit_after>use data::packet::Packet;
use data::rational::Rational64;
use stream::Stream;
use error::*;

use buffer::Buffered;
use std::io::SeekFrom;

#[derive(Clone, Debug, PartialEq)]
pub struct GlobalInfo {
    pub duration: Option<u64>,
    pub timebase: Option<Rational64>,
    pub streams: Vec<Stream>,
}

#[derive(Clone, Debug, PartialEq)]
pub enum Event {
    NewPacket(Packet),
    NewStream(Stream),
    MoreDataNeeded,
}

pub trait Demuxer {
    fn read_headers(&mut self, buf: &Box<Buffered>, info: &mut GlobalInfo) -> Result<SeekFrom>;
    fn read_event(&mut self, buf: &Box<Buffered>) -> Result<(SeekFrom, Event)>;
}

#[derive(Clone, Debug, PartialEq)]
pub struct Descr {
    pub name: &'static str,
    pub demuxer: &'static str,
    pub description: &'static str,
    pub extensions: &'static [&'static str],
    pub mime: &'static [&'static str],
}

pub trait Descriptor {
    fn create(&self) -> Box<Demuxer>;
    fn describe<'a>(&'a self) -> &'a Descr;

    fn probe(&self, data: &[u8]) -> u8;
}

pub struct Context {
    demuxer: Box<Demuxer>,
    reader: Box<Buffered>,
    pub info: GlobalInfo,
}

impl Context {
    pub fn new<R: Buffered + 'static>(demuxer: Box<Demuxer>, reader: Box<R>) -> Self {
        Context {
            demuxer: demuxer,
            reader: reader,
            info: GlobalInfo {
                duration: None,
                timebase: None,
                streams: Vec::with_capacity(2),
            },
        }
    }

    pub fn read_headers(&mut self) -> Result<()> {
        let ref mut demux = self.demuxer;

        try!(self.reader.fill_buf());

        let res = demux.read_headers(&self.reader, &mut self.info);
        match res {
            Err(e) => Err(e),
            Ok(seek) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                try!(self.reader.fill_buf());
                println!("stream now at index: {:?}", res);
                Ok(())
            }
        }
    }

    pub fn read_event(&mut self) -> Result<Event> {
        let ref mut demux = self.demuxer;

        let res = demux.read_event(&self.reader);
        match res {
            Err(e) => Err(e),
            Ok((seek, event)) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                try!(self.reader.fill_buf());
                if let Event::NewStream(ref st) = event {
                    self.info.streams.push(st.clone());
                }
                println!("stream now at index: {:?}", res);
                Ok(event)
            }
        }
    }
}

pub const PROBE_DATA: usize = 4 * 1024;
pub const PROBE_SCORE_EXTENSION: u8 = 50;

// TODO:
// IntoIterator<Item = &'static Descriptor> is confusing

pub trait Probe {
    fn probe(&self, data: &[u8]) -> Option<&'static Descriptor>;
}

impl<'a> Probe for [&'static Descriptor] {
    fn probe(&self, data: &[u8]) -> Option<&'static Descriptor> {
        let mut max = u8::min_value();
        let mut candidate: Option<&'static Descriptor> = None;
        for desc in self {
            let score = desc.probe(data);

            if score > max {
                max = score;
                candidate = Some(*desc);
            }
        }

        if max > PROBE_SCORE_EXTENSION {
            candidate
        } else {
            None
        }
    }
}

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

    struct DummyDes {
        d: Descr,
    }

    struct DummyDemuxer {}

    impl Demuxer for DummyDemuxer {
        fn read_headers(&mut self, _buf: &Box<Buffered>, _info: &mut GlobalInfo) -> Result<SeekFrom> {
            unimplemented!()
        }
        fn read_event(&mut self, _buf: &Box<Buffered>) -> Result<(SeekFrom, Event)> {
            unimplemented!()
        }
    }

    impl Descriptor for DummyDes {
        fn create(&self) -> Box<Demuxer> {
            Box::new(DummyDemuxer {})
        }
        fn describe<'a>(&'a self) -> &'a Descr {
            &self.d
        }
        fn probe(&self, data: &[u8]) -> u8 {
            match data {
                b"dummy" => 100,
                _ => 0,
            }
        }
    }

    const DUMMY_DES: &Descriptor = &DummyDes {
        d: Descr {
            name: "dummy",
            demuxer: "dummy",
            description: "Dummy dem",
            extensions: &["dm", "dum"],
            mime: &["application/dummy"],
        },
    };

    #[test]
    fn probe() {
        let codecs: &[&'static Descriptor] = &[DUMMY_DES];

        codecs.probe(b"dummy").unwrap();
    }
}
<|endoftext|>