<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#![deny(warnings)]
#![deny(unused)]
#![deny(unsafe_code)]

use std::mem::size_of;
use std::ops::Deref;
use std::ops::DerefMut;

use thiserror::Error;
use zerocopy::AsBytes;
use zerocopy::LayoutVerified;

use crate::manifest::Manifest;

#[derive(Error, Debug, PartialEq)]
pub enum ImageError {
    #[error("Failed to parse image manifest.")]
    Parse,
}

/// A thin wrapper around manifest and payload buffers to help with setting manifest fields and
/// signing the image.
#[derive(Debug)]
pub struct Image<'a> {
    pub manifest: LayoutVerified<&'a mut [u8], Manifest>,
    pub payload: &'a [u8],
}

impl<'a> Image<'a> {
    pub fn new(
        manifest_buffer: &'a mut ManifestBuffer,
        payload: &'a [u8],
    ) -> Result<Image<'a>, ImageError> {
        let manifest = LayoutVerified::new(&mut **manifest_buffer)
            .ok_or(ImageError::Parse)?;
        Ok(Self { manifest, payload })
    }

    pub fn bytes(&self) -> Vec<u8> {
        [self.manifest.as_bytes(), self.payload].concat()
    }

    pub fn signed_bytes(&self) -> Vec<u8> {
        self.bytes()
            .split_off(self.manifest.signature.as_bytes().len())
    }
}

/// A buffer with the same size and alignment as `Manifest`.
pub struct ManifestBuffer {
    buf: [u8; size_of::<Manifest>()],
    // This forces this struct to have the same alignment as `Manifest`.
    _align: [Manifest; 0],
}

impl ManifestBuffer {
    pub fn new() -> Self {
        Self {
            buf: [0u8; size_of::<Manifest>()],
            _align: [],
        }
    }
}

impl Default for ManifestBuffer {
    fn default() -> Self {
        Self::new()
    }
}

impl Deref for ManifestBuffer {
    type Target = [u8];

    fn deref(&self) -> &Self::Target {
        &self.buf
    }
}

impl DerefMut for ManifestBuffer {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.buf
    }
}

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

    #[test]
    fn test_set_manifest_field() -> Result<(), ImageError> {
        let mut manifest_buffer = ManifestBuffer::new();
        let payload = [0u8; 0];
        let mut image = Image::new(&mut manifest_buffer, &payload)?;
        let identifier: u32 = 0x01020304;
        image.manifest.identifier = identifier;
        for i in 0..4 {
            assert_eq!(manifest_buffer[i], identifier.to_le_bytes()[i]);
        }
        Ok(())
    }

    #[test]
    fn test_bytes() -> Result<(), ImageError> {
        let mut manifest_buffer = ManifestBuffer::new();
        let payload = [5u8, 6u8, 7u8, 8u8];
        let mut image = Image::new(&mut manifest_buffer, &payload)?;
        let identifier: u32 = 0x01020304;
        image.manifest.identifier = identifier;
        let bytes = image.bytes();
        for i in 0..4 {
            assert_eq!(bytes[i], manifest_buffer[i]);
            assert_eq!(bytes[size_of::<Manifest>() + i], payload[i]);
        }
        Ok(())
    }
}
<commit_msg>[host,test] Fix broken test in host tools.<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#![deny(warnings)]
#![deny(unused)]
#![deny(unsafe_code)]

use std::mem::size_of;
use std::ops::Deref;
use std::ops::DerefMut;

use thiserror::Error;
use zerocopy::AsBytes;
use zerocopy::LayoutVerified;

use crate::manifest::Manifest;

#[derive(Error, Debug, PartialEq)]
pub enum ImageError {
    #[error("Failed to parse image manifest.")]
    Parse,
}

/// A thin wrapper around manifest and payload buffers to help with setting manifest fields and
/// signing the image.
#[derive(Debug)]
pub struct Image<'a> {
    pub manifest: LayoutVerified<&'a mut [u8], Manifest>,
    pub payload: &'a [u8],
}

impl<'a> Image<'a> {
    pub fn new(
        manifest_buffer: &'a mut ManifestBuffer,
        payload: &'a [u8],
    ) -> Result<Image<'a>, ImageError> {
        let manifest = LayoutVerified::new(&mut **manifest_buffer)
            .ok_or(ImageError::Parse)?;
        Ok(Self { manifest, payload })
    }

    pub fn bytes(&self) -> Vec<u8> {
        [self.manifest.as_bytes(), self.payload].concat()
    }

    pub fn signed_bytes(&self) -> Vec<u8> {
        self.bytes()
            .split_off(self.manifest.signature.as_bytes().len())
    }
}

/// A buffer with the same size and alignment as `Manifest`.
pub struct ManifestBuffer {
    buf: [u8; size_of::<Manifest>()],
    // This forces this struct to have the same alignment as `Manifest`.
    _align: [Manifest; 0],
}

impl ManifestBuffer {
    pub fn new() -> Self {
        Self {
            buf: [0u8; size_of::<Manifest>()],
            _align: [],
        }
    }
}

impl Default for ManifestBuffer {
    fn default() -> Self {
        Self::new()
    }
}

impl Deref for ManifestBuffer {
    type Target = [u8];

    fn deref(&self) -> &Self::Target {
        &self.buf
    }
}

impl DerefMut for ManifestBuffer {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.buf
    }
}

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

    #[test]
    fn test_set_manifest_field() -> Result<(), ImageError> {
        let mut manifest_buffer = ManifestBuffer::new();
        let payload = [0u8; 0];
        let mut image = Image::new(&mut manifest_buffer, &payload)?;
        let identifier: u32 = 0x01020304;
        image.manifest.identifier = identifier;
        for i in 0..4 {
            assert_eq!(
                manifest_buffer[offset_of!(Manifest, identifier) + i],
                identifier.to_le_bytes()[i]
            );
        }
        Ok(())
    }

    #[test]
    fn test_bytes() -> Result<(), ImageError> {
        let mut manifest_buffer = ManifestBuffer::new();
        let payload = [5u8, 6u8, 7u8, 8u8];
        let mut image = Image::new(&mut manifest_buffer, &payload)?;
        let identifier: u32 = 0x01020304;
        image.manifest.identifier = identifier;
        let bytes = image.bytes();
        for i in 0..4 {
            assert_eq!(bytes[i], manifest_buffer[i]);
            assert_eq!(bytes[size_of::<Manifest>() + i], payload[i]);
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use diesel::ConnectionError as DieselConnectionError;
use diesel::result::Error as DieselResultError;
use iron::prelude::*;
use iron::status;
use std::error::Error;
use std::fmt::{self, Debug};
use std::string::FromUtf8Error;
use time::ParseError;

#[derive(Debug)]
pub struct BadRequestError(pub String);

impl fmt::Display for BadRequestError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

impl Error for BadRequestError {
    fn description(&self) -> &str { &*self.0.as_str() }
}

impl From<BadRequestError> for IronError {
    fn from(error: BadRequestError) -> IronError {
        IronError::new(error, status::BadRequest)
    }
}

// FIXME: Remove this generic error once all errors are implemented
#[derive(Debug)]
pub struct StringError(pub &'static str);

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

impl Error for StringError {
    fn description(&self) -> &str { &*self.0 }
}

impl PartialEq for StringError {
    fn eq(&self, other: &StringError) -> bool {
        self.description() == other.description()
    }
}

impl From<DieselConnectionError> for StringError {
    fn from(_: DieselConnectionError) -> StringError {
        StringError("Database connection error")
    }
}

impl From<DieselResultError> for StringError {
    fn from(_: DieselResultError) -> StringError {
        StringError("ORM result error")
    }
}

impl From<FromUtf8Error> for StringError {
    fn from(_: FromUtf8Error) -> StringError {
        StringError("Error when parsing bytes to String")
    }
}

impl From<ParseError> for StringError {
    fn from(_: ParseError) -> StringError {
        StringError("Time parse error")
    }
}

impl From<StringError> for IronError {
    fn from(error: StringError) -> IronError {
        IronError::new(error, status::InternalServerError)
    }
}
<commit_msg>Add a custom NotFoundError<commit_after>use diesel::ConnectionError as DieselConnectionError;
use diesel::result::Error as DieselResultError;
use iron::prelude::*;
use iron::status;
use std::error::Error;
use std::fmt::{self, Debug};
use std::string::FromUtf8Error;
use time::ParseError;

#[derive(Debug)]
pub struct BadRequestError(pub String);

impl fmt::Display for BadRequestError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

impl Error for BadRequestError {
    fn description(&self) -> &str { &*self.0.as_str() }
}

impl From<BadRequestError> for IronError {
    fn from(error: BadRequestError) -> IronError {
        IronError::new(error, status::BadRequest)
    }
}

#[derive(Debug)]
pub struct NotFoundError(pub String);

impl fmt::Display for NotFoundError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

impl Error for NotFoundError {
    fn description(&self) -> &str { &*self.0.as_str() }
}

impl From<NotFoundError> for IronError {
    fn from(error: NotFoundError) -> IronError {
        IronError::new(error, status::NotFound)
    }
}

// FIXME: Remove this generic error once all errors are implemented
#[derive(Debug)]
pub struct StringError(pub &'static str);

impl fmt::Display for StringError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(self, f)
    }
}

impl Error for StringError {
    fn description(&self) -> &str { &*self.0 }
}

impl PartialEq for StringError {
    fn eq(&self, other: &StringError) -> bool {
        self.description() == other.description()
    }
}

impl From<DieselConnectionError> for StringError {
    fn from(_: DieselConnectionError) -> StringError {
        StringError("Database connection error")
    }
}

impl From<DieselResultError> for StringError {
    fn from(_: DieselResultError) -> StringError {
        StringError("ORM result error")
    }
}

impl From<FromUtf8Error> for StringError {
    fn from(_: FromUtf8Error) -> StringError {
        StringError("Error when parsing bytes to String")
    }
}

impl From<ParseError> for StringError {
    fn from(_: ParseError) -> StringError {
        StringError("Time parse error")
    }
}

impl From<StringError> for IronError {
    fn from(error: StringError) -> IronError {
        IronError::new(error, status::InternalServerError)
    }
}
<|endoftext|>


<commit_before>pub use winit::{Event, WindowEvent, TouchPhase, Touch, ScanCode, ElementState, MouseButton, MouseScrollDelta, VirtualKeyCode};
<commit_msg>Expose `ModifiersState` from `winit` to allow usage w/o importing crate > Yay contributing :-)<commit_after>pub use winit::{Event, WindowEvent, TouchPhase, Touch, ScanCode, ElementState, ModifiersState, MouseButton, MouseScrollDelta, VirtualKeyCode};
<|endoftext|>


<commit_before>use crate::common::util::*;
use regex::Regex;
use std::os::unix::process::ExitStatusExt;
use std::process::{Child, Command};

// A child process the tests will try to kill.
struct Target {
    child: Child,
    killed: bool,
}

impl Target {
    // Creates a target that will naturally die after some time if not killed
    // fast enough.
    // This timeout avoids hanging failing tests.
    fn new() -> Target {
        Target {
            child: Command::new("sleep")
                .arg("30")
                .spawn()
                .expect("cannot spawn target"),
            killed: false,
        }
    }

    // Waits for the target to complete and returns the signal it received if any.
    fn wait_for_signal(&mut self) -> Option<i32> {
        let sig = self.child.wait().expect("cannot wait on target").signal();
        self.killed = true;
        sig
    }

    fn pid(&self) -> u32 {
        self.child.id()
    }
}

impl Drop for Target {
    // Terminates this target to avoid littering test boxes with zombi processes
    // when a test fails after creating a target but before killing it.
    fn drop(&mut self) {
        if !self.killed {
            self.child.kill().expect("cannot kill target");
        }
    }
}

#[test]
fn test_kill_list_all_signals() {
    // Check for a few signals.  Do not try to be comprehensive.
    new_ucmd!()
        .arg("-l")
        .succeeds()
        .stdout_contains("KILL")
        .stdout_contains("TERM")
        .stdout_contains("HUP");
}

#[test]
fn test_kill_list_all_signals_as_table() {
    // Check for a few signals.  Do not try to be comprehensive.
    new_ucmd!()
        .arg("-t")
        .succeeds()
        .stdout_contains("KILL")
        .stdout_contains("TERM")
        .stdout_contains("HUP");
}

#[test]
fn test_kill_list_one_signal_from_name() {
    // Use SIGKILL because it is 9 on all unixes.
    new_ucmd!()
        .arg("-l")
        .arg("KILL")
        .succeeds()
        .stdout_matches(&Regex::new("\\b9\\b").unwrap());
}

#[test]
fn test_kill_set_bad_signal_name() {
    // spell-checker:disable-line
    new_ucmd!()
        .arg("-s")
        .arg("IAMNOTASIGNAL") // spell-checker:disable-line
        .fails()
        .stderr_contains("unknown signal");
}

#[test]
fn test_kill_with_default_signal() {
    let mut target = Target::new();
    new_ucmd!().arg(format!("{}", target.pid())).succeeds();
    assert_eq!(target.wait_for_signal(), Some(libc::SIGTERM));
}

#[test]
fn test_kill_with_signal_number_old_form() {
    let mut target = Target::new();
    new_ucmd!()
        .arg("-9")
        .arg(format!("{}", target.pid()))
        .succeeds();
    assert_eq!(target.wait_for_signal(), Some(9));
}

#[test]
fn test_kill_with_signal_number_new_form() {
    let mut target = Target::new();
    new_ucmd!()
        .arg("-s")
        .arg("9")
        .arg(format!("{}", target.pid()))
        .succeeds();
    assert_eq!(target.wait_for_signal(), Some(9));
}

#[test]
fn test_kill_with_signal_name_new_form() {
    let mut target = Target::new();
    new_ucmd!()
        .arg("-s")
        .arg("KILL")
        .arg(format!("{}", target.pid()))
        .succeeds();
    assert_eq!(target.wait_for_signal(), Some(libc::SIGKILL));
}
<commit_msg>add kill list final new line test<commit_after>use crate::common::util::*;
use regex::Regex;
use std::os::unix::process::ExitStatusExt;
use std::process::{Child, Command};

// A child process the tests will try to kill.
struct Target {
    child: Child,
    killed: bool,
}

impl Target {
    // Creates a target that will naturally die after some time if not killed
    // fast enough.
    // This timeout avoids hanging failing tests.
    fn new() -> Target {
        Target {
            child: Command::new("sleep")
                .arg("30")
                .spawn()
                .expect("cannot spawn target"),
            killed: false,
        }
    }

    // Waits for the target to complete and returns the signal it received if any.
    fn wait_for_signal(&mut self) -> Option<i32> {
        let sig = self.child.wait().expect("cannot wait on target").signal();
        self.killed = true;
        sig
    }

    fn pid(&self) -> u32 {
        self.child.id()
    }
}

impl Drop for Target {
    // Terminates this target to avoid littering test boxes with zombi processes
    // when a test fails after creating a target but before killing it.
    fn drop(&mut self) {
        if !self.killed {
            self.child.kill().expect("cannot kill target");
        }
    }
}

#[test]
fn test_kill_list_all_signals() {
    // Check for a few signals.  Do not try to be comprehensive.
    new_ucmd!()
        .arg("-l")
        .succeeds()
        .stdout_contains("KILL")
        .stdout_contains("TERM")
        .stdout_contains("HUP");
}

#[test]
fn test_kill_list_final_new_line() {
    new_ucmd!()
        .arg("-l")
        .succeeds()
        .stdout_matches(&Regex::new("\\n$").unwrap());
}

#[test]
fn test_kill_list_all_signals_as_table() {
    // Check for a few signals.  Do not try to be comprehensive.
    new_ucmd!()
        .arg("-t")
        .succeeds()
        .stdout_contains("KILL")
        .stdout_contains("TERM")
        .stdout_contains("HUP");
}

#[test]
fn test_kill_list_one_signal_from_name() {
    // Use SIGKILL because it is 9 on all unixes.
    new_ucmd!()
        .arg("-l")
        .arg("KILL")
        .succeeds()
        .stdout_matches(&Regex::new("\\b9\\b").unwrap());
}

#[test]
fn test_kill_set_bad_signal_name() {
    // spell-checker:disable-line
    new_ucmd!()
        .arg("-s")
        .arg("IAMNOTASIGNAL") // spell-checker:disable-line
        .fails()
        .stderr_contains("unknown signal");
}

#[test]
fn test_kill_with_default_signal() {
    let mut target = Target::new();
    new_ucmd!().arg(format!("{}", target.pid())).succeeds();
    assert_eq!(target.wait_for_signal(), Some(libc::SIGTERM));
}

#[test]
fn test_kill_with_signal_number_old_form() {
    let mut target = Target::new();
    new_ucmd!()
        .arg("-9")
        .arg(format!("{}", target.pid()))
        .succeeds();
    assert_eq!(target.wait_for_signal(), Some(9));
}

#[test]
fn test_kill_with_signal_number_new_form() {
    let mut target = Target::new();
    new_ucmd!()
        .arg("-s")
        .arg("9")
        .arg(format!("{}", target.pid()))
        .succeeds();
    assert_eq!(target.wait_for_signal(), Some(9));
}

#[test]
fn test_kill_with_signal_name_new_form() {
    let mut target = Target::new();
    new_ucmd!()
        .arg("-s")
        .arg("KILL")
        .arg(format!("{}", target.pid()))
        .succeeds();
    assert_eq!(target.wait_for_signal(), Some(libc::SIGKILL));
}
<|endoftext|>


<commit_before>use std::net::ToSocketAddrs;
use std::convert::AsRef;
use std::net;
use std::io::Write;
use rustc_serialize::Encodable;
use time;
use retry::retry;
use record::Record;
use record::FluentError;
use retry_conf::RetryConf;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Fluent
    where A: ToSocketAddrs
{
    addr: A,
    tag: String,
    conf: RetryConf,
}

impl Fluent {
    /// Create Fluent type.
    ///
    /// ### Usage
    ///
    /// ```
    /// use fruently::fluent::Fluent;
    /// let fruently_with_str_tag = Fluent::new("0.0.0.0:24224", "test");
    /// let fruently_with_string_tag = Fluent::new("0.0.0.0:24224", "test".to_string());
    /// ```
    pub fn new<T>(addr: A, tag: T) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: RetryConf::new(),
        }
    }

    pub fn new_with_conf<T>(addr: A, tag: T, conf: RetryConf) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: conf,
        }
    }

    /// Post record into Fluentd. Without time version.
    pub fn post<T>(self, record: T) -> Result<(), FluentError>
        where T: Encodable
    {
        let time = time::now();
        return self.post_with_time(record, time);
    }

    /// Post record into Fluentd. With time version.
    pub fn post_with_time<T>(self, record: T, time: time::Tm) -> Result<(), FluentError>
        where T: Encodable
    {
        let record = Record::new(self.tag.clone(), time, record);
        let message = try!(record.make_forwardable_json());
        return self.send_data(message)
    }

    /// Post record into Fluentd. With retryable version.
    pub fn post_with_retry<T>(self, record: T, time: time::Tm) -> Result<(), FluentError>
        where T: Encodable
    {
        let record = Record::new(self.tag.clone(), time, record);
        let message = try!(record.make_forwardable_json());
        let addr = self.addr;
        let (max, timeout) = self.conf.build();
        match retry(max, timeout, || Fluent::closure_send_data(&addr, message.clone()), |response| response.is_ok()) {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    fn send_data(self, message: String) -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(self.addr));
        let result = stream.write(&message.into_bytes());
        drop(stream);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    fn closure_send_data(addr: &A, message: String) -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let result = stream.write(&message.into_bytes());
        drop(stream);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }
}

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

    #[test]
    fn create_fruently() {
        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let expected = Fluent {
            addr: "0.0.0.0:24224",
            tag: "test".to_string(),
            conf: RetryConf::new(),
        };
        assert_eq!(expected, fruently);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let result = fruently.post(obj);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post_with_time() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let time = time::now();
        let result = fruently.post_with_time(obj, time);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post_with_retry() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let time = time::now();
        let result = fruently.post_with_retry(obj, time);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }
}
<commit_msg>fluent: Make all posting method retryable<commit_after>use std::net::ToSocketAddrs;
use std::convert::AsRef;
use std::net;
use std::io::Write;
use rustc_serialize::Encodable;
use time;
use retry::retry;
use record::Record;
use record::FluentError;
use retry_conf::RetryConf;

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Fluent
    where A: ToSocketAddrs
{
    addr: A,
    tag: String,
    conf: RetryConf,
}

impl Fluent {
    /// Create Fluent type.
    ///
    /// ### Usage
    ///
    /// ```
    /// use fruently::fluent::Fluent;
    /// let fruently_with_str_tag = Fluent::new("0.0.0.0:24224", "test");
    /// let fruently_with_string_tag = Fluent::new("0.0.0.0:24224", "test".to_string());
    /// ```
    pub fn new<T>(addr: A, tag: T) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: RetryConf::new(),
        }
    }

    pub fn new_with_conf<T>(addr: A, tag: T, conf: RetryConf) -> Fluent
        where T: AsRef<str>
    {
        Fluent {
            addr: addr,
            tag: format!("{}", tag.as_ref()),
            conf: conf,
        }
    }

    /// Post record into Fluentd. Without time version.
    pub fn post<T>(self, record: T) -> Result<(), FluentError>
        where T: Encodable
    {
        let time = time::now();
        return self.post_with_time(record, time);
    }

    /// Post record into Fluentd. With time version.
    pub fn post_with_time<T>(self, record: T, time: time::Tm) -> Result<(), FluentError>
        where T: Encodable
    {
        let record = Record::new(self.tag.clone(), time, record);
        let message = try!(record.make_forwardable_json());
        let addr = self.addr;
        let (max, timeout) = self.conf.build();
        match retry(max, timeout, || Fluent::closure_send_data(&addr, message.clone()), |response| response.is_ok()) {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }

    fn closure_send_data(addr: &A, message: String) -> Result<(), FluentError> {
        let mut stream = try!(net::TcpStream::connect(addr));
        let result = stream.write(&message.into_bytes());
        drop(stream);

        match result {
            Ok(_) => Ok(()),
            Err(v) => Err(From::from(v)),
        }
    }
}

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

    #[test]
    fn create_fruently() {
        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let expected = Fluent {
            addr: "0.0.0.0:24224",
            tag: "test".to_string(),
            conf: RetryConf::new(),
        };
        assert_eq!(expected, fruently);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let result = fruently.post(obj);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }

    #[test]
    #[cfg(feature="fluentd")]
    fn test_post_with_time() {
        use std::collections::HashMap;

        let fruently = Fluent::new("0.0.0.0:24224", "test");
        let mut obj: HashMap<String, String> = HashMap::new();
        obj.insert("hey".to_string(), "Rust!".to_string());
        let time = time::now();
        let result = fruently.post_with_time(obj, time);
        let is_ok = match result {
            Ok(()) => true,
            _ => false,
        };
        assert_eq!(true, is_ok);
    }
}
<|endoftext|>


<commit_before>use crate::{channel::Reply, Error, Promise, PromiseResolver};
use amq_protocol::frame::AMQPFrame;
use log::{log_enabled, trace, Level::Trace};
use parking_lot::Mutex;
use pinky_swear::Cancellable;
use std::{
    collections::{HashMap, VecDeque},
    fmt,
    sync::Arc,
};

pub(crate) struct ExpectedReply(
    pub(crate) Reply,
    pub(crate) Box<dyn Cancellable<Error> + Send>,
);

impl fmt::Debug for ExpectedReply {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("ExpectedReply").field(&self.0).finish()
    }
}

#[derive(Clone, Default)]
pub(crate) struct Frames {
    inner: Arc<Mutex<Inner>>,
}

impl Frames {
    pub(crate) fn push(
        &self,
        channel_id: u16,
        frame: AMQPFrame,
        resolver: PromiseResolver<()>,
        expected_reply: Option<ExpectedReply>,
    ) {
        self.inner
            .lock()
            .push(channel_id, frame, resolver, expected_reply);
    }

    pub(crate) fn push_frames(&self, frames: Vec<AMQPFrame>) -> Promise<()> {
        self.inner.lock().push_frames(frames)
    }

    pub(crate) fn retry(&self, frame: (AMQPFrame, Option<PromiseResolver<()>>)) {
        self.inner.lock().retry(frame);
    }

    pub(crate) fn pop(&self, flow: bool) -> Option<(AMQPFrame, Option<PromiseResolver<()>>)> {
        self.inner.lock().pop(flow)
    }

    pub(crate) fn next_expected_reply(&self, channel_id: u16) -> Option<Reply> {
        self.inner
            .lock()
            .expected_replies
            .get_mut(&channel_id)
            .and_then(|replies| replies.pop_front())
            .map(|t| t.0)
    }

    pub(crate) fn has_pending(&self) -> bool {
        self.inner.lock().has_pending()
    }

    pub(crate) fn drop_pending(&self, error: Error) {
        self.inner.lock().drop_pending(error);
    }

    pub(crate) fn clear_expected_replies(&self, channel_id: u16, error: Error) {
        self.inner.lock().clear_expected_replies(channel_id, error);
    }
}

struct Inner {
    /* Header frames must follow basic.publish frames directly, otherwise RabbitMQ-server send us an UNEXPECTED_FRAME */
    header_frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    /* Body frames must be sent after the header frame but before the next publish */
    body_frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    priority_frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    low_prio_frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    expected_replies: HashMap<u16, VecDeque<ExpectedReply>>,
}

impl Default for Inner {
    fn default() -> Self {
        Self {
            header_frames: VecDeque::default(),
            body_frames: VecDeque::default(),
            priority_frames: VecDeque::default(),
            frames: VecDeque::default(),
            low_prio_frames: VecDeque::default(),
            expected_replies: HashMap::default(),
        }
    }
}

impl fmt::Debug for Frames {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut debug = f.debug_struct("Frames");
        if let Some(inner) = self.inner.try_lock() {
            debug.field("expected_replies", &inner.expected_replies);
        }
        debug.finish()
    }
}

impl Inner {
    fn push(
        &mut self,
        channel_id: u16,
        frame: AMQPFrame,
        resolver: PromiseResolver<()>,
        expected_reply: Option<ExpectedReply>,
    ) {
        self.frames.push_back((frame, Some(resolver)));
        if let Some(reply) = expected_reply {
            trace!(
                "channel {} state is now waiting for {:?}",
                channel_id,
                reply
            );
            self.expected_replies
                .entry(channel_id)
                .or_default()
                .push_back(reply);
        }
    }

    fn push_frames(&mut self, mut frames: Vec<AMQPFrame>) -> Promise<()> {
        let (promise, resolver) = Promise::new();
        let last_frame = frames.pop();

        if log_enabled!(Trace) {
            promise.set_marker("Frames".into());
        }

        for frame in frames {
            self.low_prio_frames.push_back((frame, None));
        }
        if let Some(last_frame) = last_frame {
            self.low_prio_frames.push_back((last_frame, Some(resolver)));
        } else {
            resolver.swear(Ok(()));
        }

        promise
    }

    fn pop(&mut self, flow: bool) -> Option<(AMQPFrame, Option<PromiseResolver<()>>)> {
        if let Some(frame) = self
            .priority_frames
            .pop_front()
            .or_else(|| self.header_frames.pop_front())
            .or_else(|| self.body_frames.pop_front())
            .or_else(|| self.frames.pop_front())
        {
            return Some(frame);
        }
        if flow {
            if let Some(frame) = self.low_prio_frames.pop_front() {
                // If the next frame is a header, that means we're a basic.publish
                // Header frame needs to follow directly the basic.publish frame or
                // the AMQP server will close the connection.
                // Push the header into header_frames which is there to handle just that.
                if self
                    .low_prio_frames
                    .front()
                    .map(|(frame, _)| frame.is_header())
                    .unwrap_or(false)
                {
                    // Yes, this will always be Some(), but let's keep our unwrap() count low
                    if let Some(next_frame) = self.low_prio_frames.pop_front() {
                        self.header_frames.push_back(next_frame);
                    }
                    while let Some(next_frame) = self.low_prio_frames.pop_front() {
                        match next_frame.0 {
                            AMQPFrame::Body(..) => {
                                self.body_frames.push_back(next_frame);
                            }
                            _ => {
                                self.low_prio_frames.push_front(next_frame);
                                break;
                            }
                        }
                    }
                }
                return Some(frame);
            }
        }
        None
    }

    fn retry(&mut self, frame: (AMQPFrame, Option<PromiseResolver<()>>)) {
        if frame.0.is_header() {
            self.header_frames.push_front(frame);
        } else {
            self.priority_frames.push_back(frame);
        }
    }

    fn has_pending(&self) -> bool {
        !(self.header_frames.is_empty()
            && self.priority_frames.is_empty()
            && self.frames.is_empty()
            && self.low_prio_frames.is_empty())
    }

    fn drop_pending(&mut self, error: Error) {
        Self::drop_pending_frames(&mut self.header_frames, error.clone());
        Self::drop_pending_frames(&mut self.priority_frames, error.clone());
        Self::drop_pending_frames(&mut self.frames, error.clone());
        Self::drop_pending_frames(&mut self.low_prio_frames, error.clone());
        for (_, replies) in self.expected_replies.drain() {
            Self::cancel_expected_replies(replies, error.clone());
        }
    }

    fn drop_pending_frames(
        frames: &mut VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
        error: Error,
    ) {
        for (_, resolver) in std::mem::take(frames) {
            if let Some(resolver) = resolver {
                resolver.swear(Err(error.clone()));
            }
        }
    }

    fn clear_expected_replies(&mut self, channel_id: u16, error: Error) {
        if let Some(replies) = self.expected_replies.remove(&channel_id) {
            Self::cancel_expected_replies(replies, error);
        }
    }

    fn cancel_expected_replies(replies: VecDeque<ExpectedReply>, error: Error) {
        for ExpectedReply(_, cancel) in replies {
            cancel.cancel(error.clone());
        }
    }
}
<commit_msg>frames: properly account for body frames when checking if we have pending ones<commit_after>use crate::{channel::Reply, Error, Promise, PromiseResolver};
use amq_protocol::frame::AMQPFrame;
use log::{log_enabled, trace, Level::Trace};
use parking_lot::Mutex;
use pinky_swear::Cancellable;
use std::{
    collections::{HashMap, VecDeque},
    fmt,
    sync::Arc,
};

pub(crate) struct ExpectedReply(
    pub(crate) Reply,
    pub(crate) Box<dyn Cancellable<Error> + Send>,
);

impl fmt::Debug for ExpectedReply {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_tuple("ExpectedReply").field(&self.0).finish()
    }
}

#[derive(Clone, Default)]
pub(crate) struct Frames {
    inner: Arc<Mutex<Inner>>,
}

impl Frames {
    pub(crate) fn push(
        &self,
        channel_id: u16,
        frame: AMQPFrame,
        resolver: PromiseResolver<()>,
        expected_reply: Option<ExpectedReply>,
    ) {
        self.inner
            .lock()
            .push(channel_id, frame, resolver, expected_reply);
    }

    pub(crate) fn push_frames(&self, frames: Vec<AMQPFrame>) -> Promise<()> {
        self.inner.lock().push_frames(frames)
    }

    pub(crate) fn retry(&self, frame: (AMQPFrame, Option<PromiseResolver<()>>)) {
        self.inner.lock().retry(frame);
    }

    pub(crate) fn pop(&self, flow: bool) -> Option<(AMQPFrame, Option<PromiseResolver<()>>)> {
        self.inner.lock().pop(flow)
    }

    pub(crate) fn next_expected_reply(&self, channel_id: u16) -> Option<Reply> {
        self.inner
            .lock()
            .expected_replies
            .get_mut(&channel_id)
            .and_then(|replies| replies.pop_front())
            .map(|t| t.0)
    }

    pub(crate) fn has_pending(&self) -> bool {
        self.inner.lock().has_pending()
    }

    pub(crate) fn drop_pending(&self, error: Error) {
        self.inner.lock().drop_pending(error);
    }

    pub(crate) fn clear_expected_replies(&self, channel_id: u16, error: Error) {
        self.inner.lock().clear_expected_replies(channel_id, error);
    }
}

struct Inner {
    /* Header frames must follow basic.publish frames directly, otherwise RabbitMQ-server send us an UNEXPECTED_FRAME */
    header_frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    /* Body frames must be sent after the header frame but before the next publish */
    body_frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    priority_frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    low_prio_frames: VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
    expected_replies: HashMap<u16, VecDeque<ExpectedReply>>,
}

impl Default for Inner {
    fn default() -> Self {
        Self {
            header_frames: VecDeque::default(),
            body_frames: VecDeque::default(),
            priority_frames: VecDeque::default(),
            frames: VecDeque::default(),
            low_prio_frames: VecDeque::default(),
            expected_replies: HashMap::default(),
        }
    }
}

impl fmt::Debug for Frames {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut debug = f.debug_struct("Frames");
        if let Some(inner) = self.inner.try_lock() {
            debug.field("expected_replies", &inner.expected_replies);
        }
        debug.finish()
    }
}

impl Inner {
    fn push(
        &mut self,
        channel_id: u16,
        frame: AMQPFrame,
        resolver: PromiseResolver<()>,
        expected_reply: Option<ExpectedReply>,
    ) {
        self.frames.push_back((frame, Some(resolver)));
        if let Some(reply) = expected_reply {
            trace!(
                "channel {} state is now waiting for {:?}",
                channel_id,
                reply
            );
            self.expected_replies
                .entry(channel_id)
                .or_default()
                .push_back(reply);
        }
    }

    fn push_frames(&mut self, mut frames: Vec<AMQPFrame>) -> Promise<()> {
        let (promise, resolver) = Promise::new();
        let last_frame = frames.pop();

        if log_enabled!(Trace) {
            promise.set_marker("Frames".into());
        }

        for frame in frames {
            self.low_prio_frames.push_back((frame, None));
        }
        if let Some(last_frame) = last_frame {
            self.low_prio_frames.push_back((last_frame, Some(resolver)));
        } else {
            resolver.swear(Ok(()));
        }

        promise
    }

    fn pop(&mut self, flow: bool) -> Option<(AMQPFrame, Option<PromiseResolver<()>>)> {
        if let Some(frame) = self
            .priority_frames
            .pop_front()
            .or_else(|| self.header_frames.pop_front())
            .or_else(|| self.body_frames.pop_front())
            .or_else(|| self.frames.pop_front())
        {
            return Some(frame);
        }
        if flow {
            if let Some(frame) = self.low_prio_frames.pop_front() {
                // If the next frame is a header, that means we're a basic.publish
                // Header frame needs to follow directly the basic.publish frame or
                // the AMQP server will close the connection.
                // Push the header into header_frames which is there to handle just that.
                if self
                    .low_prio_frames
                    .front()
                    .map(|(frame, _)| frame.is_header())
                    .unwrap_or(false)
                {
                    // Yes, this will always be Some(), but let's keep our unwrap() count low
                    if let Some(next_frame) = self.low_prio_frames.pop_front() {
                        self.header_frames.push_back(next_frame);
                    }
                    while let Some(next_frame) = self.low_prio_frames.pop_front() {
                        match next_frame.0 {
                            AMQPFrame::Body(..) => {
                                self.body_frames.push_back(next_frame);
                            }
                            _ => {
                                self.low_prio_frames.push_front(next_frame);
                                break;
                            }
                        }
                    }
                }
                return Some(frame);
            }
        }
        None
    }

    fn retry(&mut self, frame: (AMQPFrame, Option<PromiseResolver<()>>)) {
        if frame.0.is_header() {
            self.header_frames.push_front(frame);
        } else {
            self.priority_frames.push_back(frame);
        }
    }

    fn has_pending(&self) -> bool {
        !(self.header_frames.is_empty()
            && self.body_frames.is_empty()
            && self.priority_frames.is_empty()
            && self.frames.is_empty()
            && self.low_prio_frames.is_empty())
    }

    fn drop_pending(&mut self, error: Error) {
        Self::drop_pending_frames(&mut self.header_frames, error.clone());
        Self::drop_pending_frames(&mut self.body_frames, error.clone());
        Self::drop_pending_frames(&mut self.priority_frames, error.clone());
        Self::drop_pending_frames(&mut self.frames, error.clone());
        Self::drop_pending_frames(&mut self.low_prio_frames, error.clone());
        for (_, replies) in self.expected_replies.drain() {
            Self::cancel_expected_replies(replies, error.clone());
        }
    }

    fn drop_pending_frames(
        frames: &mut VecDeque<(AMQPFrame, Option<PromiseResolver<()>>)>,
        error: Error,
    ) {
        for (_, resolver) in std::mem::take(frames) {
            if let Some(resolver) = resolver {
                resolver.swear(Err(error.clone()));
            }
        }
    }

    fn clear_expected_replies(&mut self, channel_id: u16, error: Error) {
        if let Some(replies) = self.expected_replies.remove(&channel_id) {
            Self::cancel_expected_replies(replies, error);
        }
    }

    fn cancel_expected_replies(replies: VecDeque<ExpectedReply>, error: Error) {
        for ExpectedReply(_, cancel) in replies {
            cancel.cancel(error.clone());
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>fix typo<commit_after><|endoftext|>


<commit_before>use postgres::Connection;
use postgres_array::Array;

#[derive(Debug)]
pub struct Company {
  pub presented_talents: Vec<i32>,
}

impl Company {
  pub fn find(conn: &Connection, id: &i32) -> Option<Company> {
    conn.query("SELECT * FROM companies
                WHERE id = $1
                LIMIT 1", &[&id])
        .unwrap()
        .iter()
        .map(|row| {
          let presented_talents: Array<String> = row.get("presented_talents");

          Company {
            presented_talents: presented_talents.iter()
                                                .map(|s| s.parse::<i32>()
                                                          .unwrap())
                                                .collect::<Vec<i32>>(),
          }
        })
        .collect::<Vec<Company>>()
        .pop()
  }
}
<commit_msg>company: set the type of presented_talents' members to i32<commit_after>use postgres::Connection;
use postgres_array::Array;

#[derive(Debug)]
pub struct Company {
  pub presented_talents: Vec<i32>,
}

impl Company {
  pub fn find(conn: &Connection, id: &i32) -> Option<Company> {
    conn.query("SELECT * FROM companies
                WHERE id = $1
                LIMIT 1", &[&id])
        .unwrap()
        .iter()
        .map(|row| {
          let presented_talents: Array<i32> = row.get("presented_talents");

          Company {
            presented_talents: presented_talents.iter()
                                                .cloned()
                                                .collect::<Vec<i32>>(),
          }
        })
        .collect::<Vec<Company>>()
        .pop()
  }
}
<|endoftext|>


<commit_before>use std::env;
use regex::Regex;
use std::default::{Default};
use std::io::{Read, Error, ErrorKind};
use std::path::PathBuf;
use std::fs::File;
use serde::{Serialize, Deserialize};
use toml;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ApiConfigs {
    pub host: Option<String>,
    pub path: Option<String>,
    pub key: Option<String>,
    pub port: Option<u32>,
    pub scheme: Option<String>
}

impl ApiConfigs {
    //copies self field values into target only it's not None value
    fn merge_to(&self, target: &mut ApiConfigs){
        if self.host.is_some() { target.host = self.host.clone(); }
        if self.path.is_some() { target.path = self.path.clone(); }
        if self.key.is_some()  { target.key  = self.key.clone(); }
        if self.port.is_some() { target.port = self.port.clone(); }
        if self.scheme.is_some() { target.scheme = self.scheme.clone(); }
    }
}

impl Default for ApiConfigs {
    fn default() -> ApiConfigs {
        ApiConfigs {
            host: Some( "www.versioneye.com".to_string() ),
            path: Some("api/v2".to_string()),
            key: None,
            port: None,
            scheme: Some("https".to_string())
        }
    }
}

//-- CSVConfigs ---------------------------------------------------------------
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CSVConfigs {
    pub separator: Option<String>,
    pub quote: Option<String>, // which character to use for quoted string
    pub flexible: Option<bool>, //doesnt include empty fields. None = False, only Some(true) is true
}

impl CSVConfigs {
    //copies fields values into target only if it's not None value and overwrites existing value
    fn merge_to(&self, target: &mut CSVConfigs){
        if self.separator.is_some() { target.separator = self.separator.clone(); }
        if self.quote.is_some() { target.quote = self.quote.clone(); }
        if self.flexible.is_some() { target.flexible = self.flexible.clone(); }
    }
}

impl Default for CSVConfigs {
    fn default() -> CSVConfigs {
        CSVConfigs {
            separator: Some(";".to_string()),
            quote: Some("\"".to_string()),
            flexible: Some(false)
        }
    }
}

//-- Configs ------------------------------------------------------------------

#[derive(Serialize, Deserialize, Debug)]
pub struct Configs {
    pub api: ApiConfigs,
    pub csv: CSVConfigs
}

impl Configs {
    fn merge_to(&self, target: &mut Configs) {
        self.api.merge_to(&mut target.api);
        self.csv.merge_to(&mut target.csv);
    }
}

impl Default for Configs {
    fn default() -> Configs {
        Configs {
            api: ApiConfigs::default(),
            csv: CSVConfigs::default()
        }
    }
}

pub fn read_configs(filepath: Option<String>) -> Configs {
    let conf_filepath = filepath.unwrap_or("veye_checker.toml".to_string());
    let conf_file = PathBuf::from(conf_filepath.clone());
    let mut confs = Configs::default();

    //all every config reader overwrites previous values
    match read_configs_from_toml(&conf_file) {
        Ok(toml_confs)  => toml_confs.merge_to(&mut confs),
        Err(_)          => ()
    };

    match read_configs_from_env() {
        Ok(env_confs)  => env_confs.merge_to(&mut confs),
        Err(_)         => ()
    };

    confs
}

pub fn read_configs_from_env() -> Result<Configs, Error> {
    let re_api_key = Regex::new(r"\AVERSIONEYE_API_(\w+)\z").unwrap();
    let re_csv_key = Regex::new(r"\AVERSIONEYE_CSV_(\w+)\z").unwrap();

    let mut configs = Configs::default();

    for (key, val) in env::vars() {
        if let Some(m) = re_api_key.captures(&key) {
            let api_val = val.clone();

            match m.get(1).unwrap().as_str() {
                "KEY"    => configs.api.key = Some(api_val),
                "HOST"   => configs.api.host = Some(api_val),
                "PORT"   => configs.api.port = api_val.parse::<u32>().ok(),
                "PATH"   => configs.api.path = Some(api_val),
                "SCHEME" => configs.api.scheme = Some(api_val),
                _ => ()
            }
        };

        //read csv configs
        if let Some(m) = re_csv_key.captures(&key) {
            let csv_val = val.clone();

            match m.get(1).unwrap().as_str() {
                "SEPARATOR" => configs.csv.separator = Some(csv_val),
                "QUOTE"     => configs.csv.quote = Some(csv_val),
                "FLEXIBLE"  => {
                    let flex_val = csv_val.clone().to_string().to_lowercase();
                    let is_flexible = match flex_val.as_str() {
                        "1"     => true,
                        "t"     => true,
                        "true"  => true,
                        _       => false
                    };

                    configs.csv.flexible = Some(is_flexible)
                },
                _ => () //ignore unsupported csv keys
            }
        };
    }

    Ok(configs)
}

pub fn read_configs_from_toml(file_path: &PathBuf) -> Result<Configs, Error> {
    //todo: check does the file exists
    let mut toml_file = File::open(file_path)?;
    let mut toml_txt = String::new();
    toml_file.read_to_string(&mut toml_txt)?;

    match toml::from_str(toml_txt.as_str()) {
        Err(e) => {
            Err(
                Error::new(
                    ErrorKind::InvalidData,
                    format!("Failed to extract config data from TOML {}", e)
                )
            )
        },
        Ok(configs) => Ok(configs)
    }
}

<commit_msg>remove unused import clause from configs module;<commit_after>use std::env;
use regex::Regex;
use std::default::{Default};
use std::io::{Read, Error, ErrorKind};
use std::path::PathBuf;
use std::fs::File;
use toml;

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ApiConfigs {
    pub host: Option<String>,
    pub path: Option<String>,
    pub key: Option<String>,
    pub port: Option<u32>,
    pub scheme: Option<String>
}

impl ApiConfigs {
    //copies self field values into target only it's not None value
    fn merge_to(&self, target: &mut ApiConfigs){
        if self.host.is_some() { target.host = self.host.clone(); }
        if self.path.is_some() { target.path = self.path.clone(); }
        if self.key.is_some()  { target.key  = self.key.clone(); }
        if self.port.is_some() { target.port = self.port.clone(); }
        if self.scheme.is_some() { target.scheme = self.scheme.clone(); }
    }
}

impl Default for ApiConfigs {
    fn default() -> ApiConfigs {
        ApiConfigs {
            host: Some( "www.versioneye.com".to_string() ),
            path: Some("api/v2".to_string()),
            key: None,
            port: None,
            scheme: Some("https".to_string())
        }
    }
}

//-- CSVConfigs ---------------------------------------------------------------
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CSVConfigs {
    pub separator: Option<String>,
    pub quote: Option<String>, // which character to use for quoted string
    pub flexible: Option<bool>, //doesnt include empty fields. None = False, only Some(true) is true
}

impl CSVConfigs {
    //copies fields values into target only if it's not None value and overwrites existing value
    fn merge_to(&self, target: &mut CSVConfigs){
        if self.separator.is_some() { target.separator = self.separator.clone(); }
        if self.quote.is_some() { target.quote = self.quote.clone(); }
        if self.flexible.is_some() { target.flexible = self.flexible.clone(); }
    }
}

impl Default for CSVConfigs {
    fn default() -> CSVConfigs {
        CSVConfigs {
            separator: Some(";".to_string()),
            quote: Some("\"".to_string()),
            flexible: Some(false)
        }
    }
}

//-- Configs ------------------------------------------------------------------

#[derive(Serialize, Deserialize, Debug)]
pub struct Configs {
    pub api: ApiConfigs,
    pub csv: CSVConfigs
}

impl Configs {
    fn merge_to(&self, target: &mut Configs) {
        self.api.merge_to(&mut target.api);
        self.csv.merge_to(&mut target.csv);
    }
}

impl Default for Configs {
    fn default() -> Configs {
        Configs {
            api: ApiConfigs::default(),
            csv: CSVConfigs::default()
        }
    }
}

pub fn read_configs(filepath: Option<String>) -> Configs {
    let conf_filepath = filepath.unwrap_or("veye_checker.toml".to_string());
    let conf_file = PathBuf::from(conf_filepath.clone());
    let mut confs = Configs::default();

    //all every config reader overwrites previous values
    match read_configs_from_toml(&conf_file) {
        Ok(toml_confs)  => toml_confs.merge_to(&mut confs),
        Err(_)          => ()
    };

    match read_configs_from_env() {
        Ok(env_confs)  => env_confs.merge_to(&mut confs),
        Err(_)         => ()
    };

    confs
}

pub fn read_configs_from_env() -> Result<Configs, Error> {
    let re_api_key = Regex::new(r"\AVERSIONEYE_API_(\w+)\z").unwrap();
    let re_csv_key = Regex::new(r"\AVERSIONEYE_CSV_(\w+)\z").unwrap();

    let mut configs = Configs::default();

    for (key, val) in env::vars() {
        if let Some(m) = re_api_key.captures(&key) {
            let api_val = val.clone();

            match m.get(1).unwrap().as_str() {
                "KEY"    => configs.api.key = Some(api_val),
                "HOST"   => configs.api.host = Some(api_val),
                "PORT"   => configs.api.port = api_val.parse::<u32>().ok(),
                "PATH"   => configs.api.path = Some(api_val),
                "SCHEME" => configs.api.scheme = Some(api_val),
                _ => ()
            }
        };

        //read csv configs
        if let Some(m) = re_csv_key.captures(&key) {
            let csv_val = val.clone();

            match m.get(1).unwrap().as_str() {
                "SEPARATOR" => configs.csv.separator = Some(csv_val),
                "QUOTE"     => configs.csv.quote = Some(csv_val),
                "FLEXIBLE"  => {
                    let flex_val = csv_val.clone().to_string().to_lowercase();
                    let is_flexible = match flex_val.as_str() {
                        "1"     => true,
                        "t"     => true,
                        "true"  => true,
                        _       => false
                    };

                    configs.csv.flexible = Some(is_flexible)
                },
                _ => () //ignore unsupported csv keys
            }
        };
    }

    Ok(configs)
}

pub fn read_configs_from_toml(file_path: &PathBuf) -> Result<Configs, Error> {
    //todo: check does the file exists
    let mut toml_file = File::open(file_path)?;
    let mut toml_txt = String::new();
    toml_file.read_to_string(&mut toml_txt)?;

    match toml::from_str(toml_txt.as_str()) {
        Err(e) => {
            Err(
                Error::new(
                    ErrorKind::InvalidData,
                    format!("Failed to extract config data from TOML {}", e)
                )
            )
        },
        Ok(configs) => Ok(configs)
    }
}

<|endoftext|>


<commit_before>use std::rc::Rc;

use super::{config, Conditions, Message, TimerEvent};
use state::State;

use self::linear::LinearContext;

#[derive(Debug)]
pub enum Context {
    Linear(LinearContext),
}

impl Context {
    pub fn on_timer(&mut self, event: &TimerEvent) {
        match *self {
            Context::Linear(ref mut context) => context.on_timer(event)
        }
    }

    pub fn on_message(&mut self, event: Rc<Message>) {
        match *self {
            Context::Linear(ref mut context) => context.on_message(event)
        }
    }

    pub fn is_open(&self) -> bool {
        match *self {
            Context::Linear(ref context) => context.is_open()
        }
    }

    pub fn new(conditions: Conditions) -> Context {
        Context::Linear(
            LinearContext::new(conditions)
        )
    }
}

impl From<config::Context> for Context {
    fn from(context: config::Context) -> Context {
        Context::new(context.conditions)
    }
}

mod linear {
    use std::rc::Rc;

    use Conditions;
    use config;
    use Message;
    use state::State;
    use TimerEvent;

    #[derive(Debug)]
    pub struct LinearContext {
        conditions: Conditions,
        state: State
    }

    impl LinearContext {
        pub fn new(conditions: Conditions) -> LinearContext {
            LinearContext {
                conditions: conditions,
                state: State::new()
            }
        }

        pub fn on_timer(&mut self, event: &TimerEvent) {
            self.conditions.on_timer(event, &mut self.state);
        }

        pub fn on_message(&mut self, event: Rc<Message>) {
            self.conditions.on_message(event, &mut self.state);
        }

        pub fn is_open(&self) -> bool {
            self.state.is_open()
        }
    }
}

mod map {
    use std::collections::BTreeMap;
    use std::fmt::Write;
    use std::rc::Rc;

    use Conditions;
    use config;
    use Message;
    use state::State;
    use TimerEvent;

    pub struct MapContext {
        map: BTreeMap<String, State>,
        conditions: Conditions,
        format_buffer: String
    }

    impl MapContext {
        pub fn new(conditions: Conditions) -> MapContext {
            MapContext {
                map: BTreeMap::new(),
                conditions: conditions,
                format_buffer: String::new()
            }
        }

        pub fn on_timer(&mut self, event: &TimerEvent) {
            for (id, mut state) in self.map.iter_mut() {
                self.conditions.on_timer(event, &mut state);
            }
        }

        pub fn on_message(&mut self, event: Rc<Message>) {
            self.format_context_id(&event);
            let state = self.map.entry(self.format_buffer.clone()).or_insert(State::new());
            self.conditions.on_message(event, state);
            self.format_buffer.clear();
        }

        pub fn is_open(&mut self) -> bool {
            !self.map.is_empty()
        }

        fn format_context_id(&mut self, message: &Message) {
            let _ = self.format_buffer.write_str("foo bar baz");
        }
    }
}

use conditions::Builder;

#[test]
fn test_given_close_condition_with_timeout_when_the_timeout_expires_then_the_condition_is_met() {
    let timeout = 100;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).patterns(vec![msg_id.clone()]).build());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    println!("{:?}", &context);
    assert_false!(context.is_open());
    context.on_message(event);
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(50));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(49));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_false!(context.is_open());
}
#[test]
fn test_given_close_condition_with_max_size_when_the_max_size_reached_then_the_condition_is_met() {
    let timeout = 100;
    let max_size = 3;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).max_size(max_size).patterns(vec![msg_id.clone()]).build());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    println!("{:?}", &context);
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_message(event.clone());
    println!("{:?}", &context);
    assert_false!(context.is_open());
}

#[test]
fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_without_renewing_messages_then_the_condition_is_met() {
    let timeout = 100;
    let renew_timeout = 10;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).renew_timeout(renew_timeout).patterns(vec![msg_id.clone()]).build());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(8));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_false!(context.is_open());
}

#[test]
fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_with_renewing_messages_then_the_context_is_not_closed() {
    let timeout = 100;
    let renew_timeout = 10;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).renew_timeout(renew_timeout).patterns(vec![msg_id.clone()]).build());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    assert_false!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(8));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_true!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_true!(context.is_open());
}
<commit_msg>Context: rename Context::new() to new_linear()<commit_after>use std::rc::Rc;

use super::{config, Conditions, Message, TimerEvent};
use state::State;

use self::linear::LinearContext;

#[derive(Debug)]
pub enum Context {
    Linear(LinearContext),
}

impl Context {
    pub fn on_timer(&mut self, event: &TimerEvent) {
        match *self {
            Context::Linear(ref mut context) => context.on_timer(event)
        }
    }

    pub fn on_message(&mut self, event: Rc<Message>) {
        match *self {
            Context::Linear(ref mut context) => context.on_message(event)
        }
    }

    pub fn is_open(&self) -> bool {
        match *self {
            Context::Linear(ref context) => context.is_open()
        }
    }

    pub fn new_linear(conditions: Conditions) -> Context {
        Context::Linear(
            LinearContext::new(conditions)
        )
    }
}

impl From<config::Context> for Context {
    fn from(context: config::Context) -> Context {
        Context::new_linear(context.conditions)
    }
}

mod linear {
    use std::rc::Rc;

    use Conditions;
    use config;
    use Message;
    use state::State;
    use TimerEvent;

    #[derive(Debug)]
    pub struct LinearContext {
        conditions: Conditions,
        state: State
    }

    impl LinearContext {
        pub fn new(conditions: Conditions) -> LinearContext {
            LinearContext {
                conditions: conditions,
                state: State::new()
            }
        }

        pub fn on_timer(&mut self, event: &TimerEvent) {
            self.conditions.on_timer(event, &mut self.state);
        }

        pub fn on_message(&mut self, event: Rc<Message>) {
            self.conditions.on_message(event, &mut self.state);
        }

        pub fn is_open(&self) -> bool {
            self.state.is_open()
        }
    }
}

mod map {
    use std::collections::BTreeMap;
    use std::fmt::Write;
    use std::rc::Rc;

    use Conditions;
    use config;
    use Message;
    use state::State;
    use TimerEvent;

    pub struct MapContext {
        map: BTreeMap<String, State>,
        conditions: Conditions,
        format_buffer: String
    }

    impl MapContext {
        pub fn new(conditions: Conditions) -> MapContext {
            MapContext {
                map: BTreeMap::new(),
                conditions: conditions,
                format_buffer: String::new()
            }
        }

        pub fn on_timer(&mut self, event: &TimerEvent) {
            for (id, mut state) in self.map.iter_mut() {
                self.conditions.on_timer(event, &mut state);
            }
        }

        pub fn on_message(&mut self, event: Rc<Message>) {
            self.format_context_id(&event);
            let state = self.map.entry(self.format_buffer.clone()).or_insert(State::new());
            self.conditions.on_message(event, state);
            self.format_buffer.clear();
        }

        pub fn is_open(&mut self) -> bool {
            !self.map.is_empty()
        }

        fn format_context_id(&mut self, message: &Message) {
            let _ = self.format_buffer.write_str("foo bar baz");
        }
    }
}

use conditions::Builder;

#[test]
fn test_given_close_condition_with_timeout_when_the_timeout_expires_then_the_condition_is_met() {
    let timeout = 100;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).patterns(vec![msg_id.clone()]).build());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    println!("{:?}", &context);
    assert_false!(context.is_open());
    context.on_message(event);
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(50));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(49));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_false!(context.is_open());
}
#[test]
fn test_given_close_condition_with_max_size_when_the_max_size_reached_then_the_condition_is_met() {
    let timeout = 100;
    let max_size = 3;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).max_size(max_size).patterns(vec![msg_id.clone()]).build());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    println!("{:?}", &context);
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_message(event.clone());
    println!("{:?}", &context);
    assert_false!(context.is_open());
}

#[test]
fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_without_renewing_messages_then_the_condition_is_met() {
    let timeout = 100;
    let renew_timeout = 10;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).renew_timeout(renew_timeout).patterns(vec![msg_id.clone()]).build());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(8));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_false!(context.is_open());
}

#[test]
fn test_given_close_condition_with_renew_timeout_when_the_timeout_expires_with_renewing_messages_then_the_context_is_not_closed() {
    let timeout = 100;
    let renew_timeout = 10;
    let msg_id = "1".to_string();
    let mut context = Context::new(Builder::new(timeout).renew_timeout(renew_timeout).patterns(vec![msg_id.clone()]).build());
    let msg1 = btreemap!{
        "uuid".to_string() => msg_id.clone(),
    };
    let event = Rc::new(msg1);
    assert_false!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(8));
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_true!(context.is_open());
    context.on_message(event.clone());
    assert_true!(context.is_open());
    context.on_timer(&mut TimerEvent(1));
    assert_true!(context.is_open());
}
<|endoftext|>


<commit_before>use byteorder::{ByteOrder, BigEndian, LittleEndian};

use std::fmt;
use cpu::mem::MMU;
const BOOT_SIZE: u16 = 256;

pub struct CPU {
    f: u8, // flags
    a: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    h: u8,
    l: u8,
    Z: u8, // set if math operation is zzero or two values match during CP
    N: u8, // set if subtraction was performed in the last math instruction
    H: u8, // set if a carry occurs from the lower nibble
    C: u8, // set if if carry occued in the last math op or if registare A is smaller in CP instruction
    sp: u16,
    pc: u16,
    opcode: u8,
    word: u16,
    byte: u8,
    memory: MMU,
    pub boot: [u8; 256], // boot rom
}

impl fmt::Debug for CPU {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "A: {:X}\nB: {:X}\nC: {:X}\nH: {:X}\nL: {:X}\nSP: {:X} PC: {:X}\nFlags: Z {:X} N {:X} H {:X} C {:X}",
               self.a, self.b, self.c, self.h, self.l, self.sp, self.pc, self.Z, self.N, self.H, self.C)
    }
}

impl CPU {
    pub fn new() -> CPU {
        let cpu = CPU {
            a: 0x0,
            f: 0x0,
            b: 0x0,
            c: 0x0,
            d: 0x0,
            e: 0x0,
            h: 0x0,
            l: 0x0,
            Z: 0x0,
            N: 0x0,
            H: 0x0,
            C: 0x0,
            sp: 0,
            pc: 0,
            opcode: 0x0,
            word: 0x0,
            byte: 0x0,
            memory: MMU::new(),
            boot: [0; 256],
        };
        cpu
    }

    pub fn cycle(&mut self) {
        self.get_opcode();
        self.parse_opcode();
    }

    // pub fn print_boot(&self) {
    //     println!("Boot Rom");
    //     for i in 0..BOOT_SIZE {
    //         println!("{:X}", self.boot[i as usize]);
    //     }
    // }

    pub fn get_opcode(&mut self) {
        println!("Mem loc: {:X}", self.pc);
        self.opcode = self.boot[self.pc as usize];
        println!("Opcode {:X}", self.opcode);
    }

    pub fn get_opcode_big(&mut self) {
        let temp = self.boot[self.pc as usize];
        let upper = (temp >> 4) as u8;
        // println!("upper {:X}", upper);
    }

    pub fn read_word(&self) -> u16 {
        let aa: u8 = self.boot[(self.pc + 2) as usize];
        let bb: u8 = self.boot[(self.pc + 1) as usize];
        let word: u16 = (aa as u16) << 8 | bb as u16;
        word
    }

    pub fn read_byte(&self, count: u16) -> u8 {
        self.boot[(self.pc + count) as usize]
    }

    fn half_carry(&self, initial: u8, value: u8) -> bool {
        let a = initial & 0xF;
        let b = value & 0xF;
        return (a + b) & 0x10 == 0x10;
    }

    fn parse_opcode(&mut self) {
        match self.opcode {
            0x0C => { // INC C
                self.c += 1;
                if self.half_carry(self.c, 1) {
                    println!("INC C HALF CARRY");
                    self.H = 1;
                }
                self.N = 0;
                self.pc += 1;
            },
            0xaf => { // XOR A set Z
                self.a ^= self.a;
                self.f = 0b10000000;
                self.pc += 1;

            },
            0x20 => { // JR NZ
                let mut location = LittleEndian::read_int(&[self.boot[(self.pc + 1) as usize]], 1);
                if self.Z == 1 {
                    location  = (((self.pc + 2) as i32) + (((location as u8) as i8) as i32)) as i64;
                    self.pc = location as u16;
                } else {
                    self.pc += 2;
                }
            },
            0x21 => { // LD HL, $aabb
                self.h = self.read_byte(2);
                self.l = self.read_byte(1);
                // println!("H {:X} L {:X}", self.h, self.l);
                self.pc += 3;
            },
            0x31 => { // LD SP, $aabb
                let val: u16 = self.read_word();
                self.sp = val;
                self.pc += 3;
            },
            0x32 => { // LD (HL-), A
                // load the value in A into memory location HL, then decremement HL

                // construct memory loation from HL
                // println!("H {:X}, L {:X}", self.h, self.l);

                let mut location = (self.h as u16) << 8 | (self.l as u16);
                // println!("loocation {:X}", location);
                self.memory.load_value_u8(location as usize, self.a);

                // decrement HL
                let hl = location.wrapping_sub(1);
                // println!("HL {:X} decrement {:X}", HL, HL - 1);
                self.h = (hl >> 8) as u8;
                self.l = (hl & 0xFF) as u8;
                println!("hl {:X}", hl);
                self.pc += 1;
            },
            0x3E => { // ld
                let val: u8 = self.read_byte(1);
                self.a = val;
                self.pc += 2;
            }
            0xCB => {
                self.pc += 1;
                self.redirect();
            },
            0x0E => { // LD C, d8
                let val: u8 = self.read_byte(1);
                self.c = val;
                println!("HERE");
                self.pc += 2;
            },
            0xE0 => {

            },
            0xE2 => { // LD (0xFF00+C), A load A into location 0xFF00 + self.c
                let location = 0xFF00 + self.c as u16;
                self.memory.load_value_u8(location as usize, self.c);
                self.pc += 1;
            },
            0x77 => { // LD (HL-), A - load A into the address at HL, decrement HL
                println!("77");
                self.pc += 1;
            },
            _ => panic!("Not implemented. Opcode: {:X}", self.opcode)
        }
    }

    fn redirect(&mut self) {
        self.get_opcode();
        // println!("Redirect {:X}", self.opcode);
        match self.opcode {
            0x7C => { // BIT 7, H, 2 8, Z 0 1
                // println!("7C");
                // println!("compare bit 7 of H");
                let comp = 0b10000000 & self.h;
                println!("comp {:b}", comp);
                if comp == 0 {
                    self.Z = 0;
                } else {
                    self.Z = 1;
                }
                self.pc += 1;
            },
            _ => panic!("Not Implemented Redirect. Opcode: {:X}", self.opcode)
        }
    }

}
<commit_msg>checking if the jobref on a docket is populated<commit_after>use byteorder::{ByteOrder, BigEndian, LittleEndian};

use std::fmt;
use cpu::mem::MMU;
const BOOT_SIZE: u16 = 256;

pub struct CPU {
    f: u8, // flags
    a: u8,
    b: u8,
    c: u8,
    d: u8,
    e: u8,
    h: u8,
    l: u8,
    Z: u8, // set if math operation is zzero or two values match during CP
    N: u8, // set if subtraction was performed in the last math instruction
    H: u8, // set if a carry occurs from the lower nibble
    C: u8, // set if if carry occued in the last math op or if registare A is smaller in CP instruction
    sp: u16,
    pc: u16,
    opcode: u8,
    word: u16,
    byte: u8,
    memory: MMU,
    pub boot: [u8; 256], // boot rom
}

impl fmt::Debug for CPU {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "A: {:X}\nB: {:X}\nC: {:X}\nH: {:X}\nL: {:X}\nSP: {:X} PC: {:X}\nFlags: Z {:X} N {:X} H {:X} C {:X}",
               self.a, self.b, self.c, self.h, self.l, self.sp, self.pc, self.Z, self.N, self.H, self.C)
    }
}

impl CPU {
    pub fn new() -> CPU {
        let cpu = CPU {
            a: 0x0,
            f: 0x0,
            b: 0x0,
            c: 0x0,
            d: 0x0,
            e: 0x0,
            h: 0x0,
            l: 0x0,
            Z: 0x0,
            N: 0x0,
            H: 0x0,
            C: 0x0,
            sp: 0,
            pc: 0,
            opcode: 0x0,
            word: 0x0,
            byte: 0x0,
            memory: MMU::new(),
            boot: [0; 256],
        };
        cpu
    }

    pub fn cycle(&mut self) {
        self.get_opcode();
        self.parse_opcode();
    }

    // pub fn print_boot(&self) {
    //     println!("Boot Rom");
    //     for i in 0..BOOT_SIZE {
    //         println!("{:X}", self.boot[i as usize]);
    //     }
    // }

    pub fn get_opcode(&mut self) {
        println!("Mem loc: {:X}", self.pc);
        self.opcode = self.boot[self.pc as usize];
        println!("Opcode {:X}", self.opcode);
    }

    pub fn get_opcode_big(&mut self) {
        let temp = self.boot[self.pc as usize];
        let upper = (temp >> 4) as u8;
        // println!("upper {:X}", upper);
    }

    pub fn read_word(&self) -> u16 {
        let aa: u8 = self.boot[(self.pc + 2) as usize];
        let bb: u8 = self.boot[(self.pc + 1) as usize];
        let word: u16 = (aa as u16) << 8 | bb as u16;
        word
    }

    pub fn read_byte(&self, count: u16) -> u8 {
        self.boot[(self.pc + count) as usize]
    }

    fn half_carry(&self, initial: u8, value: u8) -> bool {
        let a = initial & 0xF;
        let b = value & 0xF;
        return (a + b) & 0x10 == 0x10;
    }

    fn parse_opcode(&mut self) {
        match self.opcode {
            0x0C => { // INC C
                println!("INC C");
                self.c += 1;
                if self.half_carry(self.c, 1) {
                    println!("INC C HALF CARRY");
                    self.H = 1;
                }
                self.N = 0;
                self.pc += 1;
            },
            0xaf => { // XOR A set Z
                println!("XOR A");
                self.a ^= self.a;
                self.f = 0b10000000;
                self.pc += 1;

            },
            0x11 => {
                println!("LD DE, d16");
                self.d = self.read_byte(2);
                self.e = self.read_byte(1);
                self.pc += 3;
            },
            0x20 => { // JR NZ
                let mut location = LittleEndian::read_int(&[self.boot[(self.pc + 1) as usize]], 1);
                if self.Z == 1 {
                    location  = (((self.pc + 2) as i32) + (((location as u8) as i8) as i32)) as i64;
                    self.pc = location as u16;
                } else {
                    self.pc += 2;
                }
            },
            0x21 => { // LD HL, $aabb
                self.h = self.read_byte(2);
                self.l = self.read_byte(1);
                // println!("H {:X} L {:X}", self.h, self.l);
                self.pc += 3;
            },
            0x31 => { // LD SP, $aabb
                let val: u16 = self.read_word();
                self.sp = val;
                self.pc += 3;
            },
            0x32 => { // LD (HL-), A
                // load the value in A into memory location HL, then decremement HL

                // construct memory loation from HL
                // println!("H {:X}, L {:X}", self.h, self.l);

                let mut location = (self.h as u16) << 8 | (self.l as u16);
                // println!("loocation {:X}", location);
                self.memory.load_value_u8(location as usize, self.a);

                // decrement HL
                let hl = location.wrapping_sub(1);
                // println!("HL {:X} decrement {:X}", HL, HL - 1);
                self.h = (hl >> 8) as u8;
                self.l = (hl & 0xFF) as u8;
                println!("hl {:X}", hl);
                self.pc += 1;
            },
            0x3E => { // ld
                let val: u8 = self.read_byte(1);
                self.a = val;
                self.pc += 2;
            }
            0xCB => {
                self.pc += 1;
                self.redirect();
            },
            0x0E => { // LD C, d8
                let val: u8 = self.read_byte(1);
                self.c = val;
                println!("HERE");
                self.pc += 2;
            },
            0xE0 => { // LDH ($FF00 + n), A - load A into 0xFF00 + d8
                let val: u8 = self.read_byte(1);
                self.memory.load_value_u8((0xFF00 + val) as usize, self.a);
                self.pc += 2;
            },
            0xE2 => { // LD (0xFF00+C), A load A into location 0xFF00 + self.c
                let location = 0xFF00 + self.c as u16;
                self.memory.load_value_u8(location as usize, self.c);
                self.pc += 1;
            },
            0x77 => { // LD (HL-), A - load A into the address at HL, decrement HL
                println!("77");
                self.pc += 1;
            },
            _ => panic!("Not implemented. Opcode: {:X}", self.opcode)
        }
    }

    fn redirect(&mut self) {
        self.get_opcode();
        // println!("Redirect {:X}", self.opcode);
        match self.opcode {
            0x7C => { // BIT 7, H, 2 8, Z 0 1
                // println!("7C");
                // println!("compare bit 7 of H");
                let comp = 0b10000000 & self.h;
                println!("comp {:b}", comp);
                if comp == 0 {
                    self.Z = 0;
                } else {
                    self.Z = 1;
                }
                self.pc += 1;
            },
            _ => panic!("Not Implemented Redirect. Opcode: {:X}", self.opcode)
        }
    }

}
<|endoftext|>


<commit_before>use std::fmt;
use std::collections::VecDeque;
use data::{Value, List, Function, RuntimeError};
use scope::{Scope, RcScope};

pub struct Lambda
{
    args: Vec<String>,
    code: VecDeque<Value>,
    env: RcScope,
}

impl PartialEq for Lambda
{
    fn eq(&self, other: &Self) -> bool
    {
        self as *const _ == other as *const _
    }
}

impl fmt::Debug for Lambda
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "args:{:?} code:{:?} ", self.args, self.code)
    }
}

impl Lambda
{
    pub fn new(args: Vec<String>, code: VecDeque<Value>, env: RcScope) -> Lambda
    {
        Lambda{ args: args, code: code, env: env }
    }
}

impl Function for Lambda
{
    fn call(&self, args: &List, env: RcScope, do_eval: bool) -> Result<Value, RuntimeError>
    {
        let vals = if do_eval { try!(args.eval(env)) } else { args.iter().collect() };
        let (na, nv) = (self.args.len(), vals.len());
        if nv < na { return Err(RuntimeError::InvalidArgNum(na as u32, nv as u32)) }

        let mut local = Scope::local(self.env.clone());
        for (name, val) in self.args.iter().zip(vals.into_iter())
        {
            local.decl(&name, val);
        }

        let wenv = local.wrap();
        let mut last = Value::Nil;
        for val in self.code.iter()
        {
            last = try!(val.eval(wenv.clone()));
        }
        Ok(last)
    }
}
<commit_msg>better debug pretty print for Lambda's<commit_after>use std::fmt;
use std::collections::VecDeque;
use data::{Value, List, Function, RuntimeError};
use scope::{Scope, RcScope};

pub struct Lambda
{
    args: Vec<String>,
    code: VecDeque<Value>,
    env: RcScope,
}

impl PartialEq for Lambda
{
    fn eq(&self, other: &Self) -> bool
    {
        self as *const _ == other as *const _
    }
}

impl fmt::Debug for Lambda
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        write!(f, "args: {:?} code: {}", self.args,
            self.code.iter().fold(String::new(), |a, v| a + &format!("{} ", v)))
    }
}

impl Lambda
{
    pub fn new(args: Vec<String>, code: VecDeque<Value>, env: RcScope) -> Lambda
    {
        Lambda{ args: args, code: code, env: env }
    }
}

impl Function for Lambda
{
    fn call(&self, args: &List, env: RcScope, do_eval: bool) -> Result<Value, RuntimeError>
    {
        let vals = if do_eval { try!(args.eval(env)) } else { args.iter().collect() };
        let (na, nv) = (self.args.len(), vals.len());
        if nv < na { return Err(RuntimeError::InvalidArgNum(na as u32, nv as u32)) }

        let mut local = Scope::local(self.env.clone());
        for (name, val) in self.args.iter().zip(vals.into_iter())
        {
            local.decl(&name, val);
        }

        let wenv = local.wrap();
        let mut last = Value::Nil;
        for val in self.code.iter()
        {
            last = try!(val.eval(wenv.clone()));
        }
        Ok(last)
    }
}
<|endoftext|>