<commit_before>use std::error::Error;
use std::fmt;
use std::io::Error as IOError;
use std::num::ParseIntError;
use std::string::FromUtf8Error;

use serde_json::error::Error as SerdeError;
#[cfg(feature = "dir_source")]
use walkdir::Error as WalkdirError;

#[cfg(feature = "script_helper")]
use rhai::{EvalAltResult, ParseError};

/// Error when rendering data on template.
#[derive(Debug)]
pub struct RenderError {
    pub desc: String,
    pub template_name: Option<String>,
    pub line_no: Option<usize>,
    pub column_no: Option<usize>,
    cause: Option<Box<dyn Error + Send + Sync + 'static>>,
}

impl fmt::Display for RenderError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match (self.line_no, self.column_no) {
            (Some(line), Some(col)) => write!(
                f,
                "Error rendering \"{}\" line {}, col {}: {}",
                self.template_name
                    .as_ref()
                    .unwrap_or(&"Unnamed template".to_owned(),),
                line,
                col,
                self.desc
            ),
            _ => write!(f, "{}", self.desc),
        }
    }
}

impl Error for RenderError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        self.cause.as_ref().map(|e| &**e as &(dyn Error + 'static))
    }
}

impl From<IOError> for RenderError {
    fn from(e: IOError) -> RenderError {
        RenderError::from_error("Error on output generation.", e)
    }
}

impl From<SerdeError> for RenderError {
    fn from(e: SerdeError) -> RenderError {
        RenderError::from_error("Error when accessing JSON data.", e)
    }
}

impl From<FromUtf8Error> for RenderError {
    fn from(e: FromUtf8Error) -> RenderError {
        RenderError::from_error("Error on bytes generation.", e)
    }
}

impl From<ParseIntError> for RenderError {
    fn from(e: ParseIntError) -> RenderError {
        RenderError::from_error("Error on accessing array/vector with string index.", e)
    }
}

impl From<TemplateError> for RenderError {
    fn from(e: TemplateError) -> RenderError {
        RenderError::from_error("Error with parsing template.", e)
    }
}

#[cfg(feature = "script_helper")]
impl From<Box<EvalAltResult>> for RenderError {
    fn from(e: Box<EvalAltResult>) -> RenderError {
        RenderError::from_error("Error on converting data to Rhai dynamic.", e)
    }
}

#[cfg(feature = "script_helper")]
impl From<ScriptError> for RenderError {
    fn from(e: ScriptError) -> RenderError {
        RenderError::from_error("Error loading rhai script.", e)
    }
}

impl RenderError {
    pub fn new<T: AsRef<str>>(desc: T) -> RenderError {
        RenderError {
            desc: desc.as_ref().to_owned(),
            template_name: None,
            line_no: None,
            column_no: None,
            cause: None,
        }
    }

    pub fn strict_error(path: Option<&String>) -> RenderError {
        let msg = match path {
            Some(path) => format!("Variable {:?} not found in strict mode.", path),
            None => "Value is missing in strict mode".to_owned(),
        };
        RenderError::new(&msg)
    }

    pub fn from_error<E>(error_kind: &str, cause: E) -> RenderError
    where
        E: Error + Send + Sync + 'static,
    {
        let mut e = RenderError::new(format!("{}: {}", error_kind, cause.to_string()));
        e.cause = Some(Box::new(cause));

        e
    }
}

quick_error! {
/// Template parsing error
    #[derive(Debug)]
    pub enum TemplateErrorReason {
        MismatchingClosedHelper(open: String, closed: String) {
            display("helper {:?} was opened, but {:?} is closing",
                open, closed)
        }
        MismatchingClosedDecorator(open: String, closed: String) {
            display("decorator {:?} was opened, but {:?} is closing",
                open, closed)
        }
        InvalidSyntax {
            display("invalid handlebars syntax.")
        }
        InvalidParam (param: String) {
            display("invalid parameter {:?}", param)
        }
        NestedSubexpression {
            display("nested subexpression is not supported")
        }
        IoError(err: IOError, name: String) {
             display("Template \"{}\": {}", name, err)
        }
        #[cfg(feature = "dir_source")]
        WalkdirError(err: WalkdirError) {
             display("Walk dir error: {}", err)
        }
    }
}

/// Error on parsing template.
#[derive(Debug)]
pub struct TemplateError {
    pub reason: TemplateErrorReason,
    pub template_name: Option<String>,
    pub line_no: Option<usize>,
    pub column_no: Option<usize>,
    segment: Option<String>,
}

impl TemplateError {
    pub fn of(e: TemplateErrorReason) -> TemplateError {
        TemplateError {
            reason: e,
            template_name: None,
            line_no: None,
            column_no: None,
            segment: None,
        }
    }

    pub fn at(mut self, template_str: &str, line_no: usize, column_no: usize) -> TemplateError {
        self.line_no = Some(line_no);
        self.column_no = Some(column_no);
        self.segment = Some(template_segment(template_str, line_no, column_no));
        self
    }

    pub fn in_template(mut self, name: String) -> TemplateError {
        self.template_name = Some(name);
        self
    }
}

impl Error for TemplateError {}

impl From<(IOError, String)> for TemplateError {
    fn from(err_info: (IOError, String)) -> TemplateError {
        let (e, name) = err_info;
        TemplateError::of(TemplateErrorReason::IoError(e, name))
    }
}

#[cfg(feature = "dir_source")]
impl From<WalkdirError> for TemplateError {
    fn from(e: WalkdirError) -> TemplateError {
        TemplateError::of(TemplateErrorReason::WalkdirError(e))
    }
}

fn template_segment(template_str: &str, line: usize, col: usize) -> String {
    let range = 3;
    let line_start = if line >= range { line - range } else { 0 };
    let line_end = line + range;

    let mut buf = String::new();
    for (line_count, line_content) in template_str.lines().enumerate() {
        if line_count >= line_start && line_count <= line_end {
            buf.push_str(&format!("{:4} | {}\n", line_count, line_content));
            if line_count == line - 1 {
                buf.push_str("     |");
                for c in 0..line_content.len() {
                    if c != col {
                        buf.push('-');
                    } else {
                        buf.push('^');
                    }
                }
                buf.push('\n');
            }
        }
    }

    buf
}

impl fmt::Display for TemplateError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match (self.line_no, self.column_no, &self.segment) {
            (Some(line), Some(col), &Some(ref seg)) => writeln!(
                f,
                "Template error: {}\n    --> Template error in \"{}\":{}:{}\n     |\n{}     |\n     = reason: {}",
                self.reason,
                self.template_name
                    .as_ref()
                    .unwrap_or(&"Unnamed template".to_owned()),
                line,
                col,
                seg,
                self.reason
            ),
            _ => write!(f, "{}", self.reason),
        }
    }
}

#[cfg(feature = "script_helper")]
quick_error! {
    #[derive(Debug)]
    pub enum ScriptError {
        IOError(err: IOError) {
            from()
            source(err)
        }
        ParseError(err: ParseError) {
            from()
            source(err)
        }
    }
}
<commit_msg>Fix punctuation in errors built with `RenderError::from_error`.<commit_after>use std::error::Error;
use std::fmt;
use std::io::Error as IOError;
use std::num::ParseIntError;
use std::string::FromUtf8Error;

use serde_json::error::Error as SerdeError;
#[cfg(feature = "dir_source")]
use walkdir::Error as WalkdirError;

#[cfg(feature = "script_helper")]
use rhai::{EvalAltResult, ParseError};

/// Error when rendering data on template.
#[derive(Debug)]
pub struct RenderError {
    pub desc: String,
    pub template_name: Option<String>,
    pub line_no: Option<usize>,
    pub column_no: Option<usize>,
    cause: Option<Box<dyn Error + Send + Sync + 'static>>,
}

impl fmt::Display for RenderError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match (self.line_no, self.column_no) {
            (Some(line), Some(col)) => write!(
                f,
                "Error rendering \"{}\" line {}, col {}: {}",
                self.template_name
                    .as_ref()
                    .unwrap_or(&"Unnamed template".to_owned(),),
                line,
                col,
                self.desc
            ),
            _ => write!(f, "{}", self.desc),
        }
    }
}

impl Error for RenderError {
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        self.cause.as_ref().map(|e| &**e as &(dyn Error + 'static))
    }
}

impl From<IOError> for RenderError {
    fn from(e: IOError) -> RenderError {
        RenderError::from_error("Error on output generation", e)
    }
}

impl From<SerdeError> for RenderError {
    fn from(e: SerdeError) -> RenderError {
        RenderError::from_error("Error when accessing JSON data", e)
    }
}

impl From<FromUtf8Error> for RenderError {
    fn from(e: FromUtf8Error) -> RenderError {
        RenderError::from_error("Error on bytes generation", e)
    }
}

impl From<ParseIntError> for RenderError {
    fn from(e: ParseIntError) -> RenderError {
        RenderError::from_error("Error on accessing array/vector with string index", e)
    }
}

impl From<TemplateError> for RenderError {
    fn from(e: TemplateError) -> RenderError {
        RenderError::from_error("Error with parsing template", e)
    }
}

#[cfg(feature = "script_helper")]
impl From<Box<EvalAltResult>> for RenderError {
    fn from(e: Box<EvalAltResult>) -> RenderError {
        RenderError::from_error("Error on converting data to Rhai dynamic", e)
    }
}

#[cfg(feature = "script_helper")]
impl From<ScriptError> for RenderError {
    fn from(e: ScriptError) -> RenderError {
        RenderError::from_error("Error loading rhai script", e)
    }
}

impl RenderError {
    pub fn new<T: AsRef<str>>(desc: T) -> RenderError {
        RenderError {
            desc: desc.as_ref().to_owned(),
            template_name: None,
            line_no: None,
            column_no: None,
            cause: None,
        }
    }

    pub fn strict_error(path: Option<&String>) -> RenderError {
        let msg = match path {
            Some(path) => format!("Variable {:?} not found in strict mode.", path),
            None => "Value is missing in strict mode".to_owned(),
        };
        RenderError::new(&msg)
    }

    pub fn from_error<E>(error_kind: &str, cause: E) -> RenderError
    where
        E: Error + Send + Sync + 'static,
    {
        let mut e = RenderError::new(format!("{}: {}", error_kind, cause.to_string()));
        e.cause = Some(Box::new(cause));

        e
    }
}

quick_error! {
/// Template parsing error
    #[derive(Debug)]
    pub enum TemplateErrorReason {
        MismatchingClosedHelper(open: String, closed: String) {
            display("helper {:?} was opened, but {:?} is closing",
                open, closed)
        }
        MismatchingClosedDecorator(open: String, closed: String) {
            display("decorator {:?} was opened, but {:?} is closing",
                open, closed)
        }
        InvalidSyntax {
            display("invalid handlebars syntax.")
        }
        InvalidParam (param: String) {
            display("invalid parameter {:?}", param)
        }
        NestedSubexpression {
            display("nested subexpression is not supported")
        }
        IoError(err: IOError, name: String) {
             display("Template \"{}\": {}", name, err)
        }
        #[cfg(feature = "dir_source")]
        WalkdirError(err: WalkdirError) {
             display("Walk dir error: {}", err)
        }
    }
}

/// Error on parsing template.
#[derive(Debug)]
pub struct TemplateError {
    pub reason: TemplateErrorReason,
    pub template_name: Option<String>,
    pub line_no: Option<usize>,
    pub column_no: Option<usize>,
    segment: Option<String>,
}

impl TemplateError {
    pub fn of(e: TemplateErrorReason) -> TemplateError {
        TemplateError {
            reason: e,
            template_name: None,
            line_no: None,
            column_no: None,
            segment: None,
        }
    }

    pub fn at(mut self, template_str: &str, line_no: usize, column_no: usize) -> TemplateError {
        self.line_no = Some(line_no);
        self.column_no = Some(column_no);
        self.segment = Some(template_segment(template_str, line_no, column_no));
        self
    }

    pub fn in_template(mut self, name: String) -> TemplateError {
        self.template_name = Some(name);
        self
    }
}

impl Error for TemplateError {}

impl From<(IOError, String)> for TemplateError {
    fn from(err_info: (IOError, String)) -> TemplateError {
        let (e, name) = err_info;
        TemplateError::of(TemplateErrorReason::IoError(e, name))
    }
}

#[cfg(feature = "dir_source")]
impl From<WalkdirError> for TemplateError {
    fn from(e: WalkdirError) -> TemplateError {
        TemplateError::of(TemplateErrorReason::WalkdirError(e))
    }
}

fn template_segment(template_str: &str, line: usize, col: usize) -> String {
    let range = 3;
    let line_start = if line >= range { line - range } else { 0 };
    let line_end = line + range;

    let mut buf = String::new();
    for (line_count, line_content) in template_str.lines().enumerate() {
        if line_count >= line_start && line_count <= line_end {
            buf.push_str(&format!("{:4} | {}\n", line_count, line_content));
            if line_count == line - 1 {
                buf.push_str("     |");
                for c in 0..line_content.len() {
                    if c != col {
                        buf.push('-');
                    } else {
                        buf.push('^');
                    }
                }
                buf.push('\n');
            }
        }
    }

    buf
}

impl fmt::Display for TemplateError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
        match (self.line_no, self.column_no, &self.segment) {
            (Some(line), Some(col), &Some(ref seg)) => writeln!(
                f,
                "Template error: {}\n    --> Template error in \"{}\":{}:{}\n     |\n{}     |\n     = reason: {}",
                self.reason,
                self.template_name
                    .as_ref()
                    .unwrap_or(&"Unnamed template".to_owned()),
                line,
                col,
                seg,
                self.reason
            ),
            _ => write!(f, "{}", self.reason),
        }
    }
}

#[cfg(feature = "script_helper")]
quick_error! {
    #[derive(Debug)]
    pub enum ScriptError {
        IOError(err: IOError) {
            from()
            source(err)
        }
        ParseError(err: ParseError) {
            from()
            source(err)
        }
    }
}
<|endoftext|>


<commit_before>// Take a look at the license at the top of the repository in the LICENSE file.

use crate::{
    Component, ComponentExt, Disk, DiskExt, NetworkData, NetworkExt, Networks, NetworksExt,
    Process, ProcessExt, Processor, ProcessorExt, System, SystemExt,
};

use std::fmt;

impl fmt::Debug for Processor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Processor")
            .field("name", &self.name())
            .field("CPU usage", &self.cpu_usage())
            .finish()
    }
}

impl fmt::Debug for System {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("System")
            .field(
                "global CPU usage",
                &self.global_processor_info().cpu_usage(),
            )
            .field("load average", &self.load_average())
            .field("total memory", &self.total_memory())
            .field("free memory", &self.free_memory())
            .field("total swap", &self.total_swap())
            .field("free swap", &self.free_swap())
            .field("nb CPUs", &self.processors().len())
            .field("nb network interfaces", &self.networks().iter().count())
            .field("nb processes", &self.processes().len())
            .field("nb disks", &self.disks().len())
            .field("nb components", &self.components().len())
            .finish()
    }
}

impl fmt::Debug for Disk {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            fmt,
            "Disk({:?})[FS: {:?}][Type: {:?}][removable: {}] mounted on {:?}: {}/{} B",
            self.name(),
            self.file_system()
                .iter()
                .map(|c| *c as char)
                .collect::<Vec<_>>(),
            self.type_(),
            if self.is_removable() { "yes" } else { "no" },
            self.mount_point(),
            self.available_space(),
            self.total_space(),
        )
    }
}

impl fmt::Debug for Process {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Process")
            .field("pid", &self.pid())
            .field("parent", &self.parent())
            .field("name", &self.name())
            .field("environ", &self.environ())
            .field("command", &self.cmd())
            .field("executable path", &self.exe())
            .field("current working directory", &self.cwd())
            .field("memory usage", &self.memory())
            .field("virtual memory usage", &self.virtual_memory())
            .field("CPU usage", &self.cpu_usage())
            .field("status", &self.status())
            .field("root", &self.root())
            .field("disk_usage", &self.disk_usage())
            .finish()
    }
}

impl fmt::Debug for Component {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if let Some(critical) = self.critical() {
            write!(
                f,
                "{}: {}°C (max: {}°C / critical: {}°C)",
                self.label(),
                self.temperature(),
                self.max(),
                critical
            )
        } else {
            write!(
                f,
                "{}: {}°C (max: {}°C)",
                self.label(),
                self.temperature(),
                self.max()
            )
        }
    }
}

impl fmt::Debug for Networks {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Networks {{ {} }}",
            self.iter()
                .map(|x| format!("{:?}", x))
                .collect::<Vec<_>>()
                .join(", ")
        )
    }
}

impl fmt::Debug for NetworkData {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("NetworkData")
            .field("income", &self.received())
            .field("total income", &self.total_received())
            .field("outcome", &self.transmitted())
            .field("total outcome", &self.total_transmitted())
            .field("packets income", &self.packets_received())
            .field("total packets income", &self.total_packets_received())
            .field("packets outcome", &self.packets_transmitted())
            .field("total packets outcome", &self.total_packets_transmitted())
            .field("errors income", &self.errors_on_received())
            .field("total errors income", &self.total_errors_on_received())
            .field("errors outcome", &self.errors_on_transmitted())
            .field("total errors outcome", &self.total_errors_on_transmitted())
            .finish()
    }
}
<commit_msg>Include other Processor fields in Debug impl<commit_after>// Take a look at the license at the top of the repository in the LICENSE file.

use crate::{
    Component, ComponentExt, Disk, DiskExt, NetworkData, NetworkExt, Networks, NetworksExt,
    Process, ProcessExt, Processor, ProcessorExt, System, SystemExt,
};

use std::fmt;

impl fmt::Debug for Processor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Processor")
            .field("name", &self.name())
            .field("CPU usage", &self.cpu_usage())
            .field("frequency", &self.frequency())
            .field("vendor ID", &self.vendor_id())
            .field("brand", &self.brand())
            .finish()
    }
}

impl fmt::Debug for System {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("System")
            .field(
                "global CPU usage",
                &self.global_processor_info().cpu_usage(),
            )
            .field("load average", &self.load_average())
            .field("total memory", &self.total_memory())
            .field("free memory", &self.free_memory())
            .field("total swap", &self.total_swap())
            .field("free swap", &self.free_swap())
            .field("nb CPUs", &self.processors().len())
            .field("nb network interfaces", &self.networks().iter().count())
            .field("nb processes", &self.processes().len())
            .field("nb disks", &self.disks().len())
            .field("nb components", &self.components().len())
            .finish()
    }
}

impl fmt::Debug for Disk {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            fmt,
            "Disk({:?})[FS: {:?}][Type: {:?}][removable: {}] mounted on {:?}: {}/{} B",
            self.name(),
            self.file_system()
                .iter()
                .map(|c| *c as char)
                .collect::<Vec<_>>(),
            self.type_(),
            if self.is_removable() { "yes" } else { "no" },
            self.mount_point(),
            self.available_space(),
            self.total_space(),
        )
    }
}

impl fmt::Debug for Process {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("Process")
            .field("pid", &self.pid())
            .field("parent", &self.parent())
            .field("name", &self.name())
            .field("environ", &self.environ())
            .field("command", &self.cmd())
            .field("executable path", &self.exe())
            .field("current working directory", &self.cwd())
            .field("memory usage", &self.memory())
            .field("virtual memory usage", &self.virtual_memory())
            .field("CPU usage", &self.cpu_usage())
            .field("status", &self.status())
            .field("root", &self.root())
            .field("disk_usage", &self.disk_usage())
            .finish()
    }
}

impl fmt::Debug for Component {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if let Some(critical) = self.critical() {
            write!(
                f,
                "{}: {}°C (max: {}°C / critical: {}°C)",
                self.label(),
                self.temperature(),
                self.max(),
                critical
            )
        } else {
            write!(
                f,
                "{}: {}°C (max: {}°C)",
                self.label(),
                self.temperature(),
                self.max()
            )
        }
    }
}

impl fmt::Debug for Networks {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Networks {{ {} }}",
            self.iter()
                .map(|x| format!("{:?}", x))
                .collect::<Vec<_>>()
                .join(", ")
        )
    }
}

impl fmt::Debug for NetworkData {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("NetworkData")
            .field("income", &self.received())
            .field("total income", &self.total_received())
            .field("outcome", &self.transmitted())
            .field("total outcome", &self.total_transmitted())
            .field("packets income", &self.packets_received())
            .field("total packets income", &self.total_packets_received())
            .field("packets outcome", &self.packets_transmitted())
            .field("total packets outcome", &self.total_packets_transmitted())
            .field("errors income", &self.errors_on_received())
            .field("total errors income", &self.total_errors_on_received())
            .field("errors outcome", &self.errors_on_transmitted())
            .field("total errors outcome", &self.total_errors_on_transmitted())
            .finish()
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::str;

static mut TARGET: Option<*mut io::Write> = None;

pub fn init(w: Box<io::Write>) {
    unsafe {
        TARGET = Some(Box::into_raw(w));
    }
}

pub struct NullDebug;

impl io::Write for NullDebug {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub struct PrintDebug;

impl io::Write for PrintDebug {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        print!("{}", str::from_utf8(buf).unwrap());
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub fn write(buf: &[u8]) -> io::Result<usize> {
    unsafe {
        TARGET.map_or_else(|| Err(io::Error::new(io::ErrorKind::NotFound, "Debug not initialised")),
                           |w| (&mut *w).write(buf))
    }
}

macro_rules! debug_print {
    ($($arg:tt)*) => {
        debug::write(format!($($arg)*).as_bytes()).unwrap()
    };
}

macro_rules! debug_println {
    ($fmt:expr) => {
        debug_print!(concat!($fmt, "\n"))
    };
    ($fmt:expr, $($arg:tt)*) => {
        debug_print!(concat!($fmt, "\n"), $($arg)*)
    };
}
<commit_msg>Don't need to `use debug;` to use debug_println!<commit_after>use std::io;
use std::str;

static mut TARGET: Option<*mut io::Write> = None;

pub fn init(w: Box<io::Write>) {
    unsafe {
        TARGET = Some(Box::into_raw(w));
    }
}

pub struct NullDebug;

impl io::Write for NullDebug {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub struct PrintDebug;

impl io::Write for PrintDebug {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        print!("{}", str::from_utf8(buf).unwrap());
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub fn write(buf: &[u8]) -> io::Result<usize> {
    unsafe {
        TARGET.map_or_else(|| Err(io::Error::new(io::ErrorKind::NotFound, "Debug not initialised")),
                           |w| (&mut *w).write(buf))
    }
}

macro_rules! debug_print {
    ($($arg:tt)*) => {
        use debug;
        debug::write(format!($($arg)*).as_bytes()).unwrap()
    };
}

macro_rules! debug_println {
    ($fmt:expr) => {
        debug_print!(concat!($fmt, "\n"))
    };
    ($fmt:expr, $($arg:tt)*) => {
        debug_print!(concat!($fmt, "\n"), $($arg)*)
    };
}
<|endoftext|>


<commit_before>use core::{char, mem, slice};
use core::ops::{Deref, DerefMut};

pub const EVENT_NONE: i64 = 0;
pub const EVENT_KEY: i64 = 1;
pub const EVENT_MOUSE: i64 = 2;
pub const EVENT_BUTTON: i64 = 3;
pub const EVENT_SCROLL: i64 = 4;
pub const EVENT_QUIT: i64 = 5;
pub const EVENT_FOCUS: i64 = 6;
pub const EVENT_MOVE: i64 = 7;
pub const EVENT_RESIZE: i64 = 8;

/// An optional event
#[derive(Copy, Clone, Debug)]
pub enum EventOption {
    /// A key event
    Key(KeyEvent),
    /// A mouse event
    Mouse(MouseEvent),
    /// A mouse button event
    Button(ButtonEvent),
    /// A mouse scroll event
    Scroll(ScrollEvent),
    /// A quit request event
    Quit(QuitEvent),
    /// A focus event
    Focus(FocusEvent),
    /// A move event
    Move(MoveEvent),
    /// A resize event
    Resize(ResizeEvent),
    /// An unknown event
    Unknown(Event),
    /// No event
    None,
}

/// An event
#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct Event {
    pub code: i64,
    pub a: i64,
    pub b: i64,
}

impl Event {
    /// Create a null event
    pub fn new() -> Event {
        Event {
            code: 0,
            a: 0,
            b: 0,
        }
    }

    /// Convert the event ot an optional event
    // TODO: Consider doing this via a From trait.
    pub fn to_option(self) -> EventOption {
        match self.code {
            EVENT_NONE => EventOption::None,
            EVENT_KEY => EventOption::Key(KeyEvent::from_event(self)),
            EVENT_MOUSE => EventOption::Mouse(MouseEvent::from_event(self)),
            EVENT_BUTTON => EventOption::Button(ButtonEvent::from_event(self)),
            EVENT_SCROLL => EventOption::Scroll(ScrollEvent::from_event(self)),
            EVENT_QUIT => EventOption::Quit(QuitEvent::from_event(self)),
            EVENT_FOCUS => EventOption::Focus(FocusEvent::from_event(self)),
            EVENT_MOVE => EventOption::Move(MoveEvent::from_event(self)),
            EVENT_RESIZE => EventOption::Resize(ResizeEvent::from_event(self)),
            _ => EventOption::Unknown(self),
        }
    }
}

impl Deref for Event {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::<Event>()) as &[u8]
        }
    }
}

impl DerefMut for Event {
    fn deref_mut(&mut self) -> &mut [u8] {
        unsafe {
            slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::<Event>()) as &mut [u8]
        }
    }
}

pub const K_A: u8 = 0x1E;
pub const K_B: u8 = 0x30;
pub const K_C: u8 = 0x2E;
pub const K_D: u8 = 0x20;
pub const K_E: u8 = 0x12;
pub const K_F: u8 = 0x21;
pub const K_G: u8 = 0x22;
pub const K_H: u8 = 0x23;
pub const K_I: u8 = 0x17;
pub const K_J: u8 = 0x24;
pub const K_K: u8 = 0x25;
pub const K_L: u8 = 0x26;
pub const K_M: u8 = 0x32;
pub const K_N: u8 = 0x31;
pub const K_O: u8 = 0x18;
pub const K_P: u8 = 0x19;
pub const K_Q: u8 = 0x10;
pub const K_R: u8 = 0x13;
pub const K_S: u8 = 0x1F;
pub const K_T: u8 = 0x14;
pub const K_U: u8 = 0x16;
pub const K_V: u8 = 0x2F;
pub const K_W: u8 = 0x11;
pub const K_X: u8 = 0x2D;
pub const K_Y: u8 = 0x15;
pub const K_Z: u8 = 0x2C;
pub const K_0: u8 = 0x0B;
pub const K_1: u8 = 0x02;
pub const K_2: u8 = 0x03;
pub const K_3: u8 = 0x04;
pub const K_4: u8 = 0x05;
pub const K_5: u8 = 0x06;
pub const K_6: u8 = 0x07;
pub const K_7: u8 = 0x08;
pub const K_8: u8 = 0x09;
pub const K_9: u8 = 0x0A;

/// Tick/tilde key
pub const K_TICK: u8 = 0x29;
/// Minus/underline key
pub const K_MINUS: u8 = 0x0C;
/// Equals/plus key
pub const K_EQUALS: u8 = 0x0D;
/// Backslash/pipe key
pub const K_BACKSLASH: u8 = 0x2B;
/// Bracket open key
pub const K_BRACE_OPEN: u8 = 0x1A;
/// Bracket close key
pub const K_BRACE_CLOSE: u8 = 0x1B;
/// Semicolon key
pub const K_SEMICOLON: u8 = 0x27;
/// Quote key
pub const K_QUOTE: u8 = 0x28;
/// Comma key
pub const K_COMMA: u8 = 0x33;
/// Period key
pub const K_PERIOD: u8 = 0x34;
/// Slash key
pub const K_SLASH: u8 = 0x35;
/// Backspace key
pub const K_BKSP: u8 = 0x0E;
/// Space key
pub const K_SPACE: u8 = 0x39;
/// Tab key
pub const K_TAB: u8 = 0x0F;
/// Capslock
pub const K_CAPS: u8 = 0x3A;
/// Left shift
pub const K_LEFT_SHIFT: u8 = 0x2A;
/// Right shift
pub const K_RIGHT_SHIFT: u8 = 0x36;
/// Control key
pub const K_CTRL: u8 = 0x1D;
/// Alt key
pub const K_ALT: u8 = 0x38;
/// Enter key
pub const K_ENTER: u8 = 0x1C;
/// Escape key
pub const K_ESC: u8 = 0x01;
/// F1 key
pub const K_F1: u8 = 0x3B;
/// F2 key
pub const K_F2: u8 = 0x3C;
/// F3 key
pub const K_F3: u8 = 0x3D;
/// F4 key
pub const K_F4: u8 = 0x3E;
/// F5 key
pub const K_F5: u8 = 0x3F;
/// F6 key
pub const K_F6: u8 = 0x40;
/// F7 key
pub const K_F7: u8 = 0x41;
/// F8 key
pub const K_F8: u8 = 0x42;
/// F9 key
pub const K_F9: u8 = 0x43;
/// F10 key
pub const K_F10: u8 = 0x44;
/// Home key
pub const K_HOME: u8 = 0x47;
/// Up key
pub const K_UP: u8 = 0x48;
/// Page up key
pub const K_PGUP: u8 = 0x49;
/// Left key
pub const K_LEFT: u8 = 0x4B;
/// Right key
pub const K_RIGHT: u8 = 0x4D;
/// End key
pub const K_END: u8 = 0x4F;
/// Down key
pub const K_DOWN: u8 = 0x50;
/// Page down key
pub const K_PGDN: u8 = 0x51;
/// Delete key
pub const K_DEL: u8 = 0x53;
/// F11 key
pub const K_F11: u8 = 0x57;
/// F12 key
pub const K_F12: u8 = 0x58;

/// A key event (such as a pressed key)
#[derive(Copy, Clone, Debug)]
pub struct KeyEvent {
    /// The charecter of the key
    pub character: char,
    /// The scancode of the key
    pub scancode: u8,
    /// Was it pressed?
    pub pressed: bool,
}

impl KeyEvent {
    /// Convert to an `Event`
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_KEY,
            a: self.character as i64,
            b: self.scancode as i64 | (self.pressed as i64) << 8,
        }
    }

    /// Convert from an `Event`
    pub fn from_event(event: Event) -> KeyEvent {
        KeyEvent {
            character: char::from_u32(event.a as u32).unwrap_or('\0'),
            scancode: event.b as u8,
            pressed: event.b & 1 << 8 == 1 << 8,
        }
    }
}

/// A event related to the mouse
#[derive(Copy, Clone, Debug)]
pub struct MouseEvent {
    /// The x coordinate of the mouse
    pub x: i32,
    /// The y coordinate of the mouse
    pub y: i32,
}

impl MouseEvent {
    /// Convert to an `Event`
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_MOUSE,
            a: self.x as i64,
            b: self.y as i64,
        }
    }

    /// Convert an `Event` to a `MouseEvent`
    pub fn from_event(event: Event) -> MouseEvent {
        MouseEvent {
            x: event.a as i32,
            y: event.b as i32,
        }
    }
}

/// A event for clicking the mouse
#[derive(Copy, Clone, Debug)]
pub struct ButtonEvent {
    /// Was the left button pressed?
    pub left: bool,
    /// Was the middle button pressed?
    pub middle: bool,
    /// Was the right button pressed?
    pub right: bool,
}

impl ButtonEvent {
    /// Convert to an `Event`
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_BUTTON,
            a: self.left as i64 | (self.middle as i64) << 1 |
               (self.right as i64) << 2,
            b: 0,
        }
    }

    /// Convert an `Event` to a `ButtonEvent`
    pub fn from_event(event: Event) -> ButtonEvent {
        ButtonEvent {
            left: event.a & 1 == 1,
            middle: event.a & 2 == 2,
            right: event.a & 4 == 4,
        }
    }
}

/// A event for scrolling the mouse
#[derive(Copy, Clone, Debug)]
pub struct ScrollEvent {
    /// The x distance of the scroll
    pub x: i32,
    /// The y distance of the scroll
    pub y: i32,
}

impl ScrollEvent {
    /// Convert to an `Event`
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_SCROLL,
            a: self.x as i64,
            b: self.y as i64,
        }
    }

    /// Convert an `Event` to a `ScrollEvent`
    pub fn from_event(event: Event) -> ScrollEvent {
        ScrollEvent {
            x: event.a as i32,
            y: event.b as i32,
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct QuitEvent;

impl QuitEvent {
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_QUIT,
            a: 0,
            b: 0,
        }
    }

    pub fn from_event(_: Event) -> QuitEvent {
        QuitEvent
    }
}

/// A focus event
#[derive(Copy, Clone, Debug)]
pub struct FocusEvent {
    /// True if window has been focused, false if not
    pub focused: bool
}

impl FocusEvent {
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_FOCUS,
            a: self.focused as i64,
            b: 0,
        }
    }

    pub fn from_event(event: Event) -> FocusEvent {
        FocusEvent {
            focused: event.a > 0
        }
    }
}

/// A move event
#[derive(Copy, Clone, Debug)]
pub struct MoveEvent {
    pub x: i32,
    pub y: i32
}

impl MoveEvent {
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_MOVE,
            a: self.x as i64,
            b: self.y as i64,
        }
    }

    pub fn from_event(event: Event) -> MoveEvent {
        MoveEvent {
            x: event.a as i32,
            y: event.b as i32
        }
    }
}

/// A resize event
#[derive(Copy, Clone, Debug)]
pub struct ResizeEvent {
    pub width: u32,
    pub height: u32
}

impl ResizeEvent {
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_RESIZE,
            a: self.width as i64,
            b: self.height as i64,
        }
    }

    pub fn from_event(event: Event) -> ResizeEvent {
        ResizeEvent {
            width: event.a as u32,
            height: event.b as u32
        }
    }
}
<commit_msg>Add an event to report screen size<commit_after>use core::{char, mem, slice};
use core::ops::{Deref, DerefMut};

pub const EVENT_NONE: i64 = 0;
pub const EVENT_KEY: i64 = 1;
pub const EVENT_MOUSE: i64 = 2;
pub const EVENT_BUTTON: i64 = 3;
pub const EVENT_SCROLL: i64 = 4;
pub const EVENT_QUIT: i64 = 5;
pub const EVENT_FOCUS: i64 = 6;
pub const EVENT_MOVE: i64 = 7;
pub const EVENT_RESIZE: i64 = 8;
pub const EVENT_SCREEN: i64 = 9;

/// An optional event
#[derive(Copy, Clone, Debug)]
pub enum EventOption {
    /// A key event
    Key(KeyEvent),
    /// A mouse event
    Mouse(MouseEvent),
    /// A mouse button event
    Button(ButtonEvent),
    /// A mouse scroll event
    Scroll(ScrollEvent),
    /// A quit request event
    Quit(QuitEvent),
    /// A focus event
    Focus(FocusEvent),
    /// A move event
    Move(MoveEvent),
    /// A resize event
    Resize(ResizeEvent),
    /// A screen report event
    Screen(ScreenEvent),
    /// An unknown event
    Unknown(Event),
    /// No event
    None,
}

/// An event
#[derive(Copy, Clone, Debug)]
#[repr(packed)]
pub struct Event {
    pub code: i64,
    pub a: i64,
    pub b: i64,
}

impl Event {
    /// Create a null event
    pub fn new() -> Event {
        Event {
            code: 0,
            a: 0,
            b: 0,
        }
    }

    /// Convert the event ot an optional event
    // TODO: Consider doing this via a From trait.
    pub fn to_option(self) -> EventOption {
        match self.code {
            EVENT_NONE => EventOption::None,
            EVENT_KEY => EventOption::Key(KeyEvent::from_event(self)),
            EVENT_MOUSE => EventOption::Mouse(MouseEvent::from_event(self)),
            EVENT_BUTTON => EventOption::Button(ButtonEvent::from_event(self)),
            EVENT_SCROLL => EventOption::Scroll(ScrollEvent::from_event(self)),
            EVENT_QUIT => EventOption::Quit(QuitEvent::from_event(self)),
            EVENT_FOCUS => EventOption::Focus(FocusEvent::from_event(self)),
            EVENT_MOVE => EventOption::Move(MoveEvent::from_event(self)),
            EVENT_RESIZE => EventOption::Resize(ResizeEvent::from_event(self)),
            EVENT_SCREEN => EventOption::Screen(ScreenEvent::from_event(self)),
            _ => EventOption::Unknown(self),
        }
    }
}

impl Deref for Event {
    type Target = [u8];
    fn deref(&self) -> &[u8] {
        unsafe {
            slice::from_raw_parts(self as *const Event as *const u8, mem::size_of::<Event>()) as &[u8]
        }
    }
}

impl DerefMut for Event {
    fn deref_mut(&mut self) -> &mut [u8] {
        unsafe {
            slice::from_raw_parts_mut(self as *mut Event as *mut u8, mem::size_of::<Event>()) as &mut [u8]
        }
    }
}

pub const K_A: u8 = 0x1E;
pub const K_B: u8 = 0x30;
pub const K_C: u8 = 0x2E;
pub const K_D: u8 = 0x20;
pub const K_E: u8 = 0x12;
pub const K_F: u8 = 0x21;
pub const K_G: u8 = 0x22;
pub const K_H: u8 = 0x23;
pub const K_I: u8 = 0x17;
pub const K_J: u8 = 0x24;
pub const K_K: u8 = 0x25;
pub const K_L: u8 = 0x26;
pub const K_M: u8 = 0x32;
pub const K_N: u8 = 0x31;
pub const K_O: u8 = 0x18;
pub const K_P: u8 = 0x19;
pub const K_Q: u8 = 0x10;
pub const K_R: u8 = 0x13;
pub const K_S: u8 = 0x1F;
pub const K_T: u8 = 0x14;
pub const K_U: u8 = 0x16;
pub const K_V: u8 = 0x2F;
pub const K_W: u8 = 0x11;
pub const K_X: u8 = 0x2D;
pub const K_Y: u8 = 0x15;
pub const K_Z: u8 = 0x2C;
pub const K_0: u8 = 0x0B;
pub const K_1: u8 = 0x02;
pub const K_2: u8 = 0x03;
pub const K_3: u8 = 0x04;
pub const K_4: u8 = 0x05;
pub const K_5: u8 = 0x06;
pub const K_6: u8 = 0x07;
pub const K_7: u8 = 0x08;
pub const K_8: u8 = 0x09;
pub const K_9: u8 = 0x0A;

/// Tick/tilde key
pub const K_TICK: u8 = 0x29;
/// Minus/underline key
pub const K_MINUS: u8 = 0x0C;
/// Equals/plus key
pub const K_EQUALS: u8 = 0x0D;
/// Backslash/pipe key
pub const K_BACKSLASH: u8 = 0x2B;
/// Bracket open key
pub const K_BRACE_OPEN: u8 = 0x1A;
/// Bracket close key
pub const K_BRACE_CLOSE: u8 = 0x1B;
/// Semicolon key
pub const K_SEMICOLON: u8 = 0x27;
/// Quote key
pub const K_QUOTE: u8 = 0x28;
/// Comma key
pub const K_COMMA: u8 = 0x33;
/// Period key
pub const K_PERIOD: u8 = 0x34;
/// Slash key
pub const K_SLASH: u8 = 0x35;
/// Backspace key
pub const K_BKSP: u8 = 0x0E;
/// Space key
pub const K_SPACE: u8 = 0x39;
/// Tab key
pub const K_TAB: u8 = 0x0F;
/// Capslock
pub const K_CAPS: u8 = 0x3A;
/// Left shift
pub const K_LEFT_SHIFT: u8 = 0x2A;
/// Right shift
pub const K_RIGHT_SHIFT: u8 = 0x36;
/// Control key
pub const K_CTRL: u8 = 0x1D;
/// Alt key
pub const K_ALT: u8 = 0x38;
/// Enter key
pub const K_ENTER: u8 = 0x1C;
/// Escape key
pub const K_ESC: u8 = 0x01;
/// F1 key
pub const K_F1: u8 = 0x3B;
/// F2 key
pub const K_F2: u8 = 0x3C;
/// F3 key
pub const K_F3: u8 = 0x3D;
/// F4 key
pub const K_F4: u8 = 0x3E;
/// F5 key
pub const K_F5: u8 = 0x3F;
/// F6 key
pub const K_F6: u8 = 0x40;
/// F7 key
pub const K_F7: u8 = 0x41;
/// F8 key
pub const K_F8: u8 = 0x42;
/// F9 key
pub const K_F9: u8 = 0x43;
/// F10 key
pub const K_F10: u8 = 0x44;
/// Home key
pub const K_HOME: u8 = 0x47;
/// Up key
pub const K_UP: u8 = 0x48;
/// Page up key
pub const K_PGUP: u8 = 0x49;
/// Left key
pub const K_LEFT: u8 = 0x4B;
/// Right key
pub const K_RIGHT: u8 = 0x4D;
/// End key
pub const K_END: u8 = 0x4F;
/// Down key
pub const K_DOWN: u8 = 0x50;
/// Page down key
pub const K_PGDN: u8 = 0x51;
/// Delete key
pub const K_DEL: u8 = 0x53;
/// F11 key
pub const K_F11: u8 = 0x57;
/// F12 key
pub const K_F12: u8 = 0x58;

/// A key event (such as a pressed key)
#[derive(Copy, Clone, Debug)]
pub struct KeyEvent {
    /// The charecter of the key
    pub character: char,
    /// The scancode of the key
    pub scancode: u8,
    /// Was it pressed?
    pub pressed: bool,
}

impl KeyEvent {
    /// Convert to an `Event`
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_KEY,
            a: self.character as i64,
            b: self.scancode as i64 | (self.pressed as i64) << 8,
        }
    }

    /// Convert from an `Event`
    pub fn from_event(event: Event) -> KeyEvent {
        KeyEvent {
            character: char::from_u32(event.a as u32).unwrap_or('\0'),
            scancode: event.b as u8,
            pressed: event.b & 1 << 8 == 1 << 8,
        }
    }
}

/// A event related to the mouse
#[derive(Copy, Clone, Debug)]
pub struct MouseEvent {
    /// The x coordinate of the mouse
    pub x: i32,
    /// The y coordinate of the mouse
    pub y: i32,
}

impl MouseEvent {
    /// Convert to an `Event`
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_MOUSE,
            a: self.x as i64,
            b: self.y as i64,
        }
    }

    /// Convert an `Event` to a `MouseEvent`
    pub fn from_event(event: Event) -> MouseEvent {
        MouseEvent {
            x: event.a as i32,
            y: event.b as i32,
        }
    }
}

/// A event for clicking the mouse
#[derive(Copy, Clone, Debug)]
pub struct ButtonEvent {
    /// Was the left button pressed?
    pub left: bool,
    /// Was the middle button pressed?
    pub middle: bool,
    /// Was the right button pressed?
    pub right: bool,
}

impl ButtonEvent {
    /// Convert to an `Event`
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_BUTTON,
            a: self.left as i64 | (self.middle as i64) << 1 |
               (self.right as i64) << 2,
            b: 0,
        }
    }

    /// Convert an `Event` to a `ButtonEvent`
    pub fn from_event(event: Event) -> ButtonEvent {
        ButtonEvent {
            left: event.a & 1 == 1,
            middle: event.a & 2 == 2,
            right: event.a & 4 == 4,
        }
    }
}

/// A event for scrolling the mouse
#[derive(Copy, Clone, Debug)]
pub struct ScrollEvent {
    /// The x distance of the scroll
    pub x: i32,
    /// The y distance of the scroll
    pub y: i32,
}

impl ScrollEvent {
    /// Convert to an `Event`
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_SCROLL,
            a: self.x as i64,
            b: self.y as i64,
        }
    }

    /// Convert an `Event` to a `ScrollEvent`
    pub fn from_event(event: Event) -> ScrollEvent {
        ScrollEvent {
            x: event.a as i32,
            y: event.b as i32,
        }
    }
}

#[derive(Copy, Clone, Debug)]
pub struct QuitEvent;

impl QuitEvent {
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_QUIT,
            a: 0,
            b: 0,
        }
    }

    pub fn from_event(_: Event) -> QuitEvent {
        QuitEvent
    }
}

/// A focus event
#[derive(Copy, Clone, Debug)]
pub struct FocusEvent {
    /// True if window has been focused, false if not
    pub focused: bool
}

impl FocusEvent {
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_FOCUS,
            a: self.focused as i64,
            b: 0,
        }
    }

    pub fn from_event(event: Event) -> FocusEvent {
        FocusEvent {
            focused: event.a > 0
        }
    }
}

/// A move event
#[derive(Copy, Clone, Debug)]
pub struct MoveEvent {
    pub x: i32,
    pub y: i32
}

impl MoveEvent {
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_MOVE,
            a: self.x as i64,
            b: self.y as i64,
        }
    }

    pub fn from_event(event: Event) -> MoveEvent {
        MoveEvent {
            x: event.a as i32,
            y: event.b as i32
        }
    }
}

/// A resize event
#[derive(Copy, Clone, Debug)]
pub struct ResizeEvent {
    pub width: u32,
    pub height: u32
}

impl ResizeEvent {
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_RESIZE,
            a: self.width as i64,
            b: self.height as i64,
        }
    }

    pub fn from_event(event: Event) -> ResizeEvent {
        ResizeEvent {
            width: event.a as u32,
            height: event.b as u32
        }
    }
}

/// A screen report event
#[derive(Copy, Clone, Debug)]
pub struct ScreenEvent {
    pub width: u32,
    pub height: u32
}

impl ScreenEvent {
    pub fn to_event(&self) -> Event {
        Event {
            code: EVENT_SCREEN,
            a: self.width as i64,
            b: self.height as i64,
        }
    }

    pub fn from_event(event: Event) -> ScreenEvent {
        ScreenEvent {
            width: event.a as u32,
            height: event.b as u32
        }
    }
}
<|endoftext|>


<commit_before>use alloc::arc::Arc;
use alloc::BTreeMap;
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};

use context;
use scheme::{self, SchemeId};
use sync::WaitQueue;
use syscall::data::Event;
use syscall::error::{Error, Result, EBADF, ESRCH};

int_like!(EventQueueId, AtomicEventQueueId, usize, AtomicUsize);

pub struct EventQueue {
    id: EventQueueId,
    queue: WaitQueue<Event>,
}

impl EventQueue {
    pub fn new(id: EventQueueId) -> EventQueue {
        EventQueue {
            id: id,
            queue: WaitQueue::new()
        }
    }

    pub fn dup(&self, other: &EventQueue) {
        panic!("EventQeuue::dup");
    }

    pub fn read(&self, events: &mut [Event]) -> Result<usize> {
        Ok(self.queue.receive_into(events, true))
    }

    pub fn write(&self, events: &[Event]) -> Result<usize> {
        for event in events {
            let file = {
                let contexts = context::contexts();
                let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
                let context = context_lock.read();
                let mut files = context.files.lock();
                match files.get(event.id).ok_or(Error::new(EBADF))? {
                    Some(file) => file.clone(),
                    None => return Err(Error::new(EBADF))
                }
            };

            let (scheme, number) = {
                let description = file.description.read();
                (description.scheme, description.number)
            };

            register(
                RegKey { scheme, number },
                QueueKey { queue: self.id, id: event.id, data: event.data },
                event.flags
            );

            send_flags(RegKey { scheme, number })?;
        }

        Ok(events.len())
    }
}

pub type EventQueueList = BTreeMap<EventQueueId, Arc<EventQueue>>;

// Next queue id
static NEXT_QUEUE_ID: AtomicUsize = ATOMIC_USIZE_INIT;

/// Get next queue id
pub fn next_queue_id() -> EventQueueId {
    EventQueueId::from(NEXT_QUEUE_ID.fetch_add(1, Ordering::SeqCst))
}

// Current event queues
static QUEUES: Once<RwLock<EventQueueList>> = Once::new();

/// Initialize queues, called if needed
fn init_queues() -> RwLock<EventQueueList> {
    RwLock::new(BTreeMap::new())
}

/// Get the event queues list, const
pub fn queues() -> RwLockReadGuard<'static, EventQueueList> {
    QUEUES.call_once(init_queues).read()
}

/// Get the event queues list, mutable
pub fn queues_mut() -> RwLockWriteGuard<'static, EventQueueList> {
    QUEUES.call_once(init_queues).write()
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct RegKey {
    pub scheme: SchemeId,
    pub number: usize,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct QueueKey {
    pub queue: EventQueueId,
    pub id: usize,
    pub data: usize
}

type Registry = BTreeMap<RegKey, BTreeMap<QueueKey, usize>>;

static REGISTRY: Once<RwLock<Registry>> = Once::new();

/// Initialize registry, called if needed
fn init_registry() -> RwLock<Registry> {
    RwLock::new(Registry::new())
}

/// Get the global schemes list, const
fn registry() -> RwLockReadGuard<'static, Registry> {
    REGISTRY.call_once(init_registry).read()
}

/// Get the global schemes list, mutable
pub fn registry_mut() -> RwLockWriteGuard<'static, Registry> {
    REGISTRY.call_once(init_registry).write()
}

pub fn register(reg_key: RegKey, queue_key: QueueKey, flags: usize) {
    let mut registry = registry_mut();

    let entry = registry.entry(reg_key).or_insert_with(|| {
        BTreeMap::new()
    });

    if flags == 0 {
        entry.remove(&queue_key);
    } else {
        entry.insert(queue_key, flags);
    }
}

pub fn send_flags(reg_key: RegKey) -> Result<usize> {
    let mut flags = 0;

    {
        let registry = registry();

        if let Some(queue_list) = registry.get(&reg_key) {
            for (_queue_key, queue_flags) in queue_list.iter() {
                flags |= queue_flags;
            }
        }
    }

    let scheme = {
        let schemes = scheme::schemes();
        let scheme = schemes.get(reg_key.scheme).ok_or(Error::new(EBADF))?;
        Arc::clone(&scheme)
    };

    scheme.fevent(reg_key.number, flags)
}

pub fn unregister_file(scheme: SchemeId, number: usize) {
    let mut registry = registry_mut();

    registry.remove(&RegKey { scheme, number });
}

//TODO: Implement unregister_queue
// pub fn unregister_queue(scheme: SchemeId, number: usize) {
//
// }

pub fn trigger(scheme: SchemeId, number: usize, flags: usize) {
    let registry = registry();

    if let Some(queue_list) = registry.get(&RegKey { scheme, number }) {
        for (queue_key, queue_flags) in queue_list.iter() {
            let common_flags = flags & queue_flags;
            if common_flags != 0 {
                let queues = queues();
                if let Some(queue) = queues.get(&queue_key.queue) {
                    queue.queue.send(Event {
                        id: queue_key.id,
                        flags: common_flags,
                        data: queue_key.data
                    });
                }
            }
        }
    }
}
<commit_msg>Require correct event id return<commit_after>use alloc::arc::Arc;
use alloc::BTreeMap;
use core::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};

use context;
use scheme::{self, SchemeId};
use sync::WaitQueue;
use syscall::data::Event;
use syscall::error::{Error, Result, EBADF, ESRCH};

int_like!(EventQueueId, AtomicEventQueueId, usize, AtomicUsize);

pub struct EventQueue {
    id: EventQueueId,
    queue: WaitQueue<Event>,
}

impl EventQueue {
    pub fn new(id: EventQueueId) -> EventQueue {
        EventQueue {
            id: id,
            queue: WaitQueue::new()
        }
    }

    pub fn dup(&self, other: &EventQueue) {
        panic!("EventQeuue::dup");
    }

    pub fn read(&self, events: &mut [Event]) -> Result<usize> {
        Ok(self.queue.receive_into(events, true))
    }

    pub fn write(&self, events: &[Event]) -> Result<usize> {
        for event in events {
            let file = {
                let contexts = context::contexts();
                let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
                let context = context_lock.read();
                let mut files = context.files.lock();
                match files.get(event.id).ok_or(Error::new(EBADF))? {
                    Some(file) => file.clone(),
                    None => return Err(Error::new(EBADF))
                }
            };

            let (scheme, number) = {
                let description = file.description.read();
                (description.scheme, description.number)
            };

            register(
                RegKey { scheme, number },
                QueueKey { queue: self.id, id: event.id, data: event.data },
                event.flags
            );

            send_flags(RegKey { scheme, number })?;
        }

        Ok(events.len())
    }
}

pub type EventQueueList = BTreeMap<EventQueueId, Arc<EventQueue>>;

// Next queue id
static NEXT_QUEUE_ID: AtomicUsize = ATOMIC_USIZE_INIT;

/// Get next queue id
pub fn next_queue_id() -> EventQueueId {
    EventQueueId::from(NEXT_QUEUE_ID.fetch_add(1, Ordering::SeqCst))
}

// Current event queues
static QUEUES: Once<RwLock<EventQueueList>> = Once::new();

/// Initialize queues, called if needed
fn init_queues() -> RwLock<EventQueueList> {
    RwLock::new(BTreeMap::new())
}

/// Get the event queues list, const
pub fn queues() -> RwLockReadGuard<'static, EventQueueList> {
    QUEUES.call_once(init_queues).read()
}

/// Get the event queues list, mutable
pub fn queues_mut() -> RwLockWriteGuard<'static, EventQueueList> {
    QUEUES.call_once(init_queues).write()
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct RegKey {
    pub scheme: SchemeId,
    pub number: usize,
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct QueueKey {
    pub queue: EventQueueId,
    pub id: usize,
    pub data: usize
}

type Registry = BTreeMap<RegKey, BTreeMap<QueueKey, usize>>;

static REGISTRY: Once<RwLock<Registry>> = Once::new();

/// Initialize registry, called if needed
fn init_registry() -> RwLock<Registry> {
    RwLock::new(Registry::new())
}

/// Get the global schemes list, const
fn registry() -> RwLockReadGuard<'static, Registry> {
    REGISTRY.call_once(init_registry).read()
}

/// Get the global schemes list, mutable
pub fn registry_mut() -> RwLockWriteGuard<'static, Registry> {
    REGISTRY.call_once(init_registry).write()
}

pub fn register(reg_key: RegKey, queue_key: QueueKey, flags: usize) {
    let mut registry = registry_mut();

    let entry = registry.entry(reg_key).or_insert_with(|| {
        BTreeMap::new()
    });

    if flags == 0 {
        entry.remove(&queue_key);
    } else {
        entry.insert(queue_key, flags);
    }
}

pub fn send_flags(reg_key: RegKey) -> Result<()> {
    let mut flags = 0;

    {
        let registry = registry();

        if let Some(queue_list) = registry.get(&reg_key) {
            for (_queue_key, queue_flags) in queue_list.iter() {
                flags |= queue_flags;
            }
        }
    }

    let event_id = {
        let scheme = {
            let schemes = scheme::schemes();
            let scheme = schemes.get(reg_key.scheme).ok_or(Error::new(EBADF))?;
            Arc::clone(&scheme)
        };

        scheme.fevent(reg_key.number, flags)?
    };

    if event_id != reg_key.number {
        let scheme_ns = {
            let contexts = context::contexts();
            let context_lock = contexts.current().ok_or(Error::new(ESRCH))?;
            let context = context_lock.read();
            context.ens
        };

        let schemes = scheme::schemes();
        for (name, &scheme_id) in schemes.iter_name(scheme_ns) {
            if scheme_id == reg_key.scheme {
                println!("  {}", unsafe { ::core::str::from_utf8_unchecked(name) });
            }
        }

        panic!("schemes returned event id {} instead of {}", event_id, reg_key.number);
    }

    Ok(())
}

pub fn unregister_file(scheme: SchemeId, number: usize) {
    let mut registry = registry_mut();

    registry.remove(&RegKey { scheme, number });
}

//TODO: Implement unregister_queue
// pub fn unregister_queue(scheme: SchemeId, number: usize) {
//
// }

pub fn trigger(scheme: SchemeId, number: usize, flags: usize) {
    let registry = registry();

    if let Some(queue_list) = registry.get(&RegKey { scheme, number }) {
        for (queue_key, queue_flags) in queue_list.iter() {
            let common_flags = flags & queue_flags;
            if common_flags != 0 {
                let queues = queues();
                if let Some(queue) = queues.get(&queue_key.queue) {
                    queue.queue.send(Event {
                        id: queue_key.id,
                        flags: common_flags,
                        data: queue_key.data
                    });
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::str::FromStr;
use std::collections::HashMap;

#[derive(PartialEq, Eq, Hash, Clone)]
enum Source {
    Pattern(u16),
    Wire(String),
}

impl FromStr for Source {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Source, Self::Err> {
        match s {
            s if s.is_empty() => Err("empty identifier"),
            s if (|s: &str| s.chars().all(|c| c.is_digit(10)))(s) => {
                s.parse::<u16>().map_err(|_| "parse error").map(Source::Pattern)
            }
            s if (|s: &str| s.chars().all(|c| c.is_alphabetic()))(s) => {
                Ok(Source::Wire(s.to_owned()))
            }
            _ => Err("unknown identifier format"),
        }
    }
}

#[derive(PartialEq, Eq, Hash, Clone)]
enum Gate {
    Pass {
        src: Source,
        out: Source,
    },
    Not {
        src: Source,
        out: Source,
    },
    And {
        a: Source,
        b: Source,
        out: Source,
    },
    Or {
        a: Source,
        b: Source,
        out: Source,
    },
    LShift {
        src: Source,
        shift: Source,
        out: Source,
    },
    RShift {
        src: Source,
        shift: Source,
        out: Source,
    },
}

impl FromStr for Gate {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Gate, Self::Err> {
        match &s.split_whitespace().collect::<Vec<_>>()[..] {
            [a, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| o.parse::<Source>().map(|o| Gate::Pass { src: a, out: o }))
            }
            ["NOT", a, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| o.parse::<Source>().map(|o| Gate::Not { src: a, out: o }))
            }
            [a, op @ "AND", b, "->", o] |
            [a, op @ "OR", b, "->", o] |
            [a, op @ "LSHIFT", b, "->", o] |
            [a, op @ "RSHIFT", b, "->", o] => {
                a.parse::<Source>().and_then(|a| {
                    b.parse::<Source>().and_then(|b| {
                        o.parse::<Source>().map(|o| {
                            match op {
                                "AND" => {
                                    Gate::And {
                                        a: a,
                                        b: b,
                                        out: o,
                                    }
                                }
                                "OR" => {
                                    Gate::Or {
                                        a: a,
                                        b: b,
                                        out: o,
                                    }
                                }
                                "LSHIFT" => {
                                    Gate::LShift {
                                        src: a,
                                        shift: b,
                                        out: o,
                                    }
                                }
                                "RSHIFT" => {
                                    Gate::RShift {
                                        src: a,
                                        shift: b,
                                        out: o,
                                    }
                                }
                                _ => unreachable!(),
                            }
                        })
                    })
                })
            }
            _ => Err("bad input"),
        }
    }
}

impl Gate {
    fn out(&self) -> Source {
        match *self {
            Gate::Pass{ ref out, ..} => out,
            Gate::Not{ ref out, ..} => out,
            Gate::And{ ref out, ..} => out,
            Gate::Or{ ref out, ..} => out,
            Gate::LShift{ ref out, ..} => out,
            Gate::RShift{ ref out, ..} => out,
        }
        .clone()
    }

    fn eval(&self, c: &mut Circuit) -> Option<u16> {
        match *self {
            Gate::Pass{ ref src, .. } => c.eval(src),
            Gate::Not{ ref src, .. } => c.eval(src).map(|v| !v),
            Gate::And{ ref a, ref b, .. } => {
                match (c.eval(a), c.eval(b)) {
                    (None, _) => None,
                    (_, None) => None,
                    (Some(lhs), Some(rhs)) => Some(lhs & rhs),
                }
            }
            Gate::Or{ ref a, ref b, .. } => {
                match (c.eval(a), c.eval(b)) {
                    (None, _) => None,
                    (_, None) => None,
                    (Some(lhs), Some(rhs)) => Some(lhs | rhs),
                }
            }
            Gate::LShift{ ref src, ref shift, .. } => c.eval(src).map(|v| v << c.eval(shift).unwrap()),
            Gate::RShift{ ref src, ref shift, .. } => c.eval(src).map(|v| v >> c.eval(shift).unwrap()),
        }
    }
}

struct Circuit {
    gates: HashMap<Source, Gate>,
    cache: HashMap<Source, u16>,
}

impl FromStr for Circuit {
    type Err = &'static str;

    fn from_str(input: &str) -> Result<Circuit, Self::Err> {
        let mut circuit = HashMap::new();
        let cache = HashMap::new();

        for line in input.lines() {
            if let Ok(gate) = Gate::from_str(line) {
                circuit.insert(gate.out(), gate);
            } else {
                return Err("gate parse error");
            }
        }
        Ok(Circuit {
            gates: circuit,
            cache: cache,
        })
    }
}

impl Circuit {
    fn eval(&mut self, wire: &Source) -> Option<u16> {
        match *wire {
            Source::Pattern(p) => Some(p),
            ref s @ Source::Wire(_) => {
                if self.cache.contains_key(s) {
                    self.cache.get(s).cloned()
                } else {
                    if let Some(v) = self.gates.get(s).cloned().and_then(|g| g.eval(self)) {
                        self.cache.insert(s.clone(), v);
                        Some(v)
                    } else {
                        None
                    }
                }
            }
        }
    }

    fn force(&mut self, s: &Source, v: u16) {
        self.cache.clear();
        self.cache.insert(s.clone(), v);
    }
}

fn run_circuit(input: &str, target: &str) -> Option<u16> {
    if let Ok(mut c) = Circuit::from_str(input) {
        c.eval(&Source::Wire(target.to_owned()))
    } else {
        None
    }
}

fn part2(input: &str, target: &str, force: &str, v: u16) -> Option<u16> {
    if let Ok(mut c) = Circuit::from_str(input) {
        c.force(&Source::Wire(force.to_owned()), v);
        c.eval(&Source::Wire(target.to_owned()))
    } else {
        None
    }
}

#[cfg(test)]
mod test {
    use std::str::FromStr;
    use super::{Circuit, Source};

    #[test]
    fn test_circuit() {
        let cs = ["123 -> x",
                  "456 -> y",
                  "x AND y -> d",
                  "x OR y -> e",
                  "x LSHIFT 2 -> f",
                  "y RSHIFT 2 -> g",
                  "NOT x -> h",
                  "NOT y -> i"]
                     .join("\n");
        let mut c = Circuit::from_str(&cs).unwrap();
        assert_eq!(c.eval(&Source::Wire("d".to_owned())), Some(72));
        assert_eq!(c.eval(&Source::Wire("e".to_owned())), Some(507));
        assert_eq!(c.eval(&Source::Wire("f".to_owned())), Some(492));
        assert_eq!(c.eval(&Source::Wire("g".to_owned())), Some(114));
        assert_eq!(c.eval(&Source::Wire("h".to_owned())), Some(65412));
        assert_eq!(c.eval(&Source::Wire("i".to_owned())), Some(65079));
        assert_eq!(c.eval(&Source::Wire("x".to_owned())), Some(123));
        assert_eq!(c.eval(&Source::Wire("y".to_owned())), Some(456));
    }
}

const DATA: &'static str = include_str!("../data/input_7.txt");

pub fn main() -> Vec<String> {
    let s1 = run_circuit(DATA, "a").unwrap();
    let s2 = part2(DATA, "a", "b", 956).unwrap();
    vec![s1.to_string(), s2.to_string()]
}
<commit_msg>unify gate types into unary and binary<commit_after>use std::str::FromStr;
use std::collections::HashMap;
use std::ops::{BitAnd, BitOr, Shl, Shr, Not};

#[derive(PartialEq, Eq, Hash, Clone)]
enum Source {
    Pattern(u16),
    Wire(String),
}

impl FromStr for Source {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Source, Self::Err> {
        match s {
            s if s.is_empty() => Err("empty identifier"),
            s if (|s: &str| s.chars().all(|c| c.is_digit(10)))(s) => {
                s.parse::<u16>().map_err(|_| "parse error").map(Source::Pattern)
            }
            s if (|s: &str| s.chars().all(|c| c.is_alphabetic()))(s) => {
                Ok(Source::Wire(s.to_owned()))
            }
            _ => Err("unknown identifier format"),
        }
    }
}

#[derive(PartialEq, Eq, Hash, Clone)]
enum Gate {
    UnaryOp {
        src: Source,
        out: Source,
        f: fn(u16) -> u16,
    },
    BinaryOp {
        a: Source,
        b: Source,
        out: Source,
        f: fn(u16, u16) -> u16,
    },
}

impl FromStr for Gate {
    type Err = &'static str;

    fn from_str(s: &str) -> Result<Gate, Self::Err> {

        fn id<T>(x: T) -> T {
            x
        };

        match &s.split_whitespace().collect::<Vec<_>>()[..] {
            [a, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| {
                     o.parse::<Source>().map(|o| {
                         Gate::UnaryOp {
                             src: a,
                             out: o,
                             f: id,
                         }
                     })
                 })
            }
            ["NOT", a, "->", o] => {
                a.parse::<Source>()
                 .and_then(|a| {
                     o.parse::<Source>().map(|o| {
                         Gate::UnaryOp {
                             src: a,
                             out: o,
                             f: Not::not,
                         }
                     })
                 })
            }
            [a, op, b, "->", o] => {
                a.parse::<Source>().and_then(|a| {
                    b.parse::<Source>().and_then(|b| {
                        o.parse::<Source>().map(|o| {
                            Gate::BinaryOp {
                                a: a,
                                b: b,
                                out: o,
                                f: match op {
                                    "AND" => BitAnd::bitand,
                                    "OR" => BitOr::bitor,
                                    "LSHIFT" => Shl::shl,
                                    "RSHIFT" => Shr::shr,
                                    _ => unreachable!(),
                                },
                            }
                        })
                    })
                })
            }
            _ => Err("bad input"),
        }
    }
}

impl Gate {
    fn out(&self) -> Source {
        match *self {
            Gate::UnaryOp{ ref out, ..} => out,
            Gate::BinaryOp{ ref out, ..} => out,
        }
        .clone()
    }

    fn eval(&self, c: &mut Circuit) -> Option<u16> {
        match *self {
            Gate::UnaryOp{ ref src, ref f, .. } => c.eval(src).map(|v| f(v)),
            Gate::BinaryOp{ ref a, ref b, ref f, .. } => {
                match (c.eval(a), c.eval(b)) {
                    (Some(lhs), Some(rhs)) => Some(f(lhs, rhs)),
                    _ => None,
                }
            }
        }
    }
}

struct Circuit {
    gates: HashMap<Source, Gate>,
    cache: HashMap<Source, u16>,
}

impl FromStr for Circuit {
    type Err = &'static str;

    fn from_str(input: &str) -> Result<Circuit, Self::Err> {
        let mut circuit = HashMap::new();
        let cache = HashMap::new();

        for line in input.lines() {
            if let Ok(gate) = Gate::from_str(line) {
                circuit.insert(gate.out(), gate);
            } else {
                return Err("gate parse error");
            }
        }
        Ok(Circuit {
            gates: circuit,
            cache: cache,
        })
    }
}

impl Circuit {
    fn eval(&mut self, wire: &Source) -> Option<u16> {
        match *wire {
            Source::Pattern(p) => Some(p),
            ref s @ Source::Wire(_) => {
                if self.cache.contains_key(s) {
                    self.cache.get(s).cloned()
                } else {
                    if let Some(v) = self.gates.get(s).cloned().and_then(|g| g.eval(self)) {
                        self.cache.insert(s.clone(), v);
                        Some(v)
                    } else {
                        None
                    }
                }
            }
        }
    }

    fn force(&mut self, s: &Source, v: u16) {
        self.cache.clear();
        self.cache.insert(s.clone(), v);
    }
}

fn run_circuit(input: &str, target: &str) -> Option<u16> {
    if let Ok(mut c) = Circuit::from_str(input) {
        c.eval(&Source::Wire(target.to_owned()))
    } else {
        None
    }
}

fn part2(input: &str, target: &str, force: &str, v: u16) -> Option<u16> {
    if let Ok(mut c) = Circuit::from_str(input) {
        c.force(&Source::Wire(force.to_owned()), v);
        c.eval(&Source::Wire(target.to_owned()))
    } else {
        None
    }
}

#[cfg(test)]
mod test {
    use std::str::FromStr;
    use super::{Circuit, Source};

    #[test]
    fn test_circuit() {
        let cs = ["123 -> x",
                  "456 -> y",
                  "x AND y -> d",
                  "x OR y -> e",
                  "x LSHIFT 2 -> f",
                  "y RSHIFT 2 -> g",
                  "NOT x -> h",
                  "NOT y -> i"]
                     .join("\n");
        let mut c = Circuit::from_str(&cs).unwrap();
        assert_eq!(c.eval(&Source::Wire("d".to_owned())), Some(72));
        assert_eq!(c.eval(&Source::Wire("e".to_owned())), Some(507));
        assert_eq!(c.eval(&Source::Wire("f".to_owned())), Some(492));
        assert_eq!(c.eval(&Source::Wire("g".to_owned())), Some(114));
        assert_eq!(c.eval(&Source::Wire("h".to_owned())), Some(65412));
        assert_eq!(c.eval(&Source::Wire("i".to_owned())), Some(65079));
        assert_eq!(c.eval(&Source::Wire("x".to_owned())), Some(123));
        assert_eq!(c.eval(&Source::Wire("y".to_owned())), Some(456));
    }
}

const DATA: &'static str = include_str!("../data/input_7.txt");

pub fn main() -> Vec<String> {
    let s1 = run_circuit(DATA, "a").unwrap();
    let s2 = part2(DATA, "a", "b", 956).unwrap();
    vec![s1.to_string(), s2.to_string()]
}
<|endoftext|>


<commit_before>use std::sync::Arc;

use Object;
use Runtime;
use Variable;

pub fn obj_field<T: PopVariable>(rt: &Runtime, obj: &Object, name: &str) -> Result<T, String> {
    let var = try!(obj.get(&Arc::new(name.into()))
        .ok_or_else(|| format!("Object has no key `{}`", name)));
    PopVariable::pop_var(rt, var)
}

/// Implemented by types that can be popped from the runtime stack.
pub trait PopVariable: Sized {
    /// Converts variable to self.
    /// The variable should be resolved before call.
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String>;
}

/// Implemented by types that can be pushed to the runtime stack.
pub trait PushVariable {
    /// Converts from self to variable.
    fn push_var(&self) -> Variable;
}

/// Implemented by types that can be converted to and from vec4.
pub trait ConvertVec4: Sized {
    /// Converts vec4 to self.
    fn from(val: [f32; 4]) -> Self;
    fn to(&self) -> [f32; 4];
}

impl PopVariable for String {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Text(ref s) = var {
            Ok((&**s).clone())
        } else {
            Err(rt.expected(var, "string"))
        }
    }
}

impl PopVariable for Arc<String> {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Text(ref s) = var {
            Ok(s.clone())
        } else {
            Err(rt.expected(var, "string"))
        }
    }
}

impl PopVariable for u32 {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::F64(n) = var {
            Ok(n as u32)
        } else {
            Err(rt.expected(var, "number"))
        }
    }
}

impl PopVariable for usize {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::F64(n) = var {
            Ok(n as usize)
        } else {
            Err(rt.expected(var, "number"))
        }
    }
}

impl PopVariable for f32 {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::F64(n) = var {
            Ok(n as f32)
        } else {
            Err(rt.expected(var, "number"))
        }
    }
}

impl PopVariable for f64 {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::F64(n) = var {
            Ok(n)
        } else {
            Err(rt.expected(var, "number"))
        }
    }
}

impl<T: PopVariable> PopVariable for Option<T> {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Option(ref s) = var {
            Ok(match *s {
                Some(ref s) => Some(try!(PopVariable::pop_var(rt, rt.resolve(s)))),
                None => None
            })
        } else {
            Err(rt.expected(var, "option"))
        }
    }
}

impl<T: PopVariable> PopVariable for [T; 2] {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            Ok([
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[0]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[1])))
            ])
        } else {
            Err(rt.expected(var, "[_; 2]"))
        }
    }
}

impl<T: PopVariable> PopVariable for [T; 3] {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            Ok([
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[0]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[1]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[2])))
            ])
        } else {
            Err(rt.expected(var, "[_; 3]"))
        }
    }
}

impl<T: PopVariable> PopVariable for [T; 4] {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            Ok([
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[0]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[1]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[2]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[3])))
            ])
        } else {
            Err(rt.expected(var, "[_; 4]"))
        }
    }
}

impl<T: PopVariable> PopVariable for Vec<T> {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            let mut res = Vec::with_capacity(arr.len());
            for it in &**arr {
                res.push(try!(PopVariable::pop_var(rt, rt.resolve(it))))
            }
            Ok(res)
        } else {
            Err(rt.expected(var, "array"))
        }
    }
}

impl PushVariable for bool {
    fn push_var(&self) -> Variable { Variable::Bool(*self) }
}

impl PushVariable for u32 {
    fn push_var(&self) -> Variable { Variable::F64(*self as f64) }
}

impl PushVariable for usize {
    fn push_var(&self) -> Variable { Variable::F64(*self as f64) }
}

impl PushVariable for f32 {
    fn push_var(&self) -> Variable { Variable::F64(*self as f64) }
}

impl PushVariable for f64 {
    fn push_var(&self) -> Variable { Variable::F64(*self) }
}

impl PushVariable for str {
    fn push_var(&self) -> Variable { Variable::Text(Arc::new(self.into())) }
}

impl PushVariable for String {
    fn push_var(&self) -> Variable { Variable::Text(Arc::new(self.clone())) }
}

impl PushVariable for Arc<String> {
    fn push_var(&self) -> Variable { Variable::Text(self.clone()) }
}

impl<T: PushVariable> PushVariable for Option<T> {
    fn push_var(&self) -> Variable {
        Variable::Option(self.as_ref().map(|v| Box::new(v.push_var())))
    }
}

impl<T: PushVariable> PushVariable for [T; 2] {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(vec![
            self[0].push_var(),
            self[1].push_var()
        ]))
    }
}

impl<T: PushVariable> PushVariable for [T; 3] {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(vec![
            self[0].push_var(),
            self[1].push_var(),
            self[2].push_var()
        ]))
    }
}

impl<T: PushVariable> PushVariable for [T; 4] {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(vec![
            self[0].push_var(),
            self[1].push_var(),
            self[2].push_var(),
            self[3].push_var()
        ]))
    }
}

impl<T: PushVariable> PushVariable for Vec<T> {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(self.iter().map(|it| it.push_var()).collect()))
    }
}

impl ConvertVec4 for [f32; 2] {
    fn from(val: [f32; 4]) -> Self { [val[0], val[1]] }
    fn to(&self) -> [f32; 4] { [self[0], self[1], 0.0, 0.0] }
}

impl ConvertVec4 for [f32; 3] {
    fn from(val: [f32; 4]) -> Self { [val[0], val[1], val[2]] }
    fn to(&self) -> [f32; 4] { [self[0], self[1], self[2], 0.0] }
}

impl ConvertVec4 for [f32; 4] {
    fn from(val: [f32; 4]) -> Self { val }
    fn to(&self) -> [f32; 4] { *self }
}

impl ConvertVec4 for [f64; 2] {
    fn from(val: [f32; 4]) -> Self { [val[0] as f64, val[1] as f64] }
    fn to(&self) -> [f32; 4] { [self[0] as f32, self[1] as f32, 0.0, 0.0] }
}

impl ConvertVec4 for [f64; 3] {
    fn from(val: [f32; 4]) -> Self { [val[0] as f64, val[1] as f64, val[2] as f64] }
    fn to(&self) -> [f32; 4] { [self[0] as f32, self[1] as f32, self[2] as f32, 0.0] }
}

impl ConvertVec4 for [f64; 4] {
    fn from(val: [f32; 4]) -> Self { [val[0] as f64, val[1] as f64, val[2] as f64, val[3] as f64] }
    fn to(&self) -> [f32; 4] { [self[0] as f32, self[1] as f32, self[2] as f32, self[3] as f32] }
}
<commit_msg>Added pop/push for tuples<commit_after>use std::sync::Arc;

use Object;
use Runtime;
use Variable;

pub fn obj_field<T: PopVariable>(rt: &Runtime, obj: &Object, name: &str) -> Result<T, String> {
    let var = try!(obj.get(&Arc::new(name.into()))
        .ok_or_else(|| format!("Object has no key `{}`", name)));
    PopVariable::pop_var(rt, var)
}

/// Implemented by types that can be popped from the runtime stack.
pub trait PopVariable: Sized {
    /// Converts variable to self.
    /// The variable should be resolved before call.
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String>;
}

/// Implemented by types that can be pushed to the runtime stack.
pub trait PushVariable {
    /// Converts from self to variable.
    fn push_var(&self) -> Variable;
}

/// Implemented by types that can be converted to and from vec4.
pub trait ConvertVec4: Sized {
    /// Converts vec4 to self.
    fn from(val: [f32; 4]) -> Self;
    fn to(&self) -> [f32; 4];
}

impl PopVariable for String {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Text(ref s) = var {
            Ok((&**s).clone())
        } else {
            Err(rt.expected(var, "string"))
        }
    }
}

impl PopVariable for Arc<String> {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Text(ref s) = var {
            Ok(s.clone())
        } else {
            Err(rt.expected(var, "string"))
        }
    }
}

impl PopVariable for u32 {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::F64(n) = var {
            Ok(n as u32)
        } else {
            Err(rt.expected(var, "number"))
        }
    }
}

impl PopVariable for usize {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::F64(n) = var {
            Ok(n as usize)
        } else {
            Err(rt.expected(var, "number"))
        }
    }
}

impl PopVariable for f32 {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::F64(n) = var {
            Ok(n as f32)
        } else {
            Err(rt.expected(var, "number"))
        }
    }
}

impl PopVariable for f64 {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::F64(n) = var {
            Ok(n)
        } else {
            Err(rt.expected(var, "number"))
        }
    }
}

impl<T: PopVariable> PopVariable for Option<T> {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Option(ref s) = var {
            Ok(match *s {
                Some(ref s) => Some(try!(PopVariable::pop_var(rt, rt.resolve(s)))),
                None => None
            })
        } else {
            Err(rt.expected(var, "option"))
        }
    }
}

impl<T: PopVariable> PopVariable for [T; 2] {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            Ok([
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[0]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[1])))
            ])
        } else {
            Err(rt.expected(var, "[_; 2]"))
        }
    }
}

impl<T: PopVariable> PopVariable for [T; 3] {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            Ok([
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[0]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[1]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[2])))
            ])
        } else {
            Err(rt.expected(var, "[_; 3]"))
        }
    }
}

impl<T: PopVariable> PopVariable for [T; 4] {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            Ok([
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[0]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[1]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[2]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[3])))
            ])
        } else {
            Err(rt.expected(var, "[_; 4]"))
        }
    }
}

impl<T: PopVariable, U: PopVariable> PopVariable for (T, U) {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            Ok((
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[0]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[1])))
            ))
        } else {
            Err(rt.expected(var, "[_; 2]"))
        }
    }
}

impl<T: PopVariable, U: PopVariable, V: PopVariable> PopVariable for (T, U, V) {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            Ok((
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[0]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[1]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[2])))
            ))
        } else {
            Err(rt.expected(var, "[_; 3]"))
        }
    }
}

impl<T: PopVariable, U: PopVariable, V: PopVariable, W: PopVariable> PopVariable for (T, U, V, W) {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            Ok((
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[0]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[1]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[2]))),
                try!(PopVariable::pop_var(rt, rt.resolve(&arr[3])))
            ))
        } else {
            Err(rt.expected(var, "[_; 4]"))
        }
    }
}

impl<T: PopVariable> PopVariable for Vec<T> {
    fn pop_var(rt: &Runtime, var: &Variable) -> Result<Self, String> {
        if let &Variable::Array(ref arr) = var {
            let mut res = Vec::with_capacity(arr.len());
            for it in &**arr {
                res.push(try!(PopVariable::pop_var(rt, rt.resolve(it))))
            }
            Ok(res)
        } else {
            Err(rt.expected(var, "array"))
        }
    }
}

impl PushVariable for bool {
    fn push_var(&self) -> Variable { Variable::Bool(*self) }
}

impl PushVariable for u32 {
    fn push_var(&self) -> Variable { Variable::F64(*self as f64) }
}

impl PushVariable for usize {
    fn push_var(&self) -> Variable { Variable::F64(*self as f64) }
}

impl PushVariable for f32 {
    fn push_var(&self) -> Variable { Variable::F64(*self as f64) }
}

impl PushVariable for f64 {
    fn push_var(&self) -> Variable { Variable::F64(*self) }
}

impl PushVariable for str {
    fn push_var(&self) -> Variable { Variable::Text(Arc::new(self.into())) }
}

impl PushVariable for String {
    fn push_var(&self) -> Variable { Variable::Text(Arc::new(self.clone())) }
}

impl PushVariable for Arc<String> {
    fn push_var(&self) -> Variable { Variable::Text(self.clone()) }
}

impl<T: PushVariable> PushVariable for Option<T> {
    fn push_var(&self) -> Variable {
        Variable::Option(self.as_ref().map(|v| Box::new(v.push_var())))
    }
}

impl<T: PushVariable> PushVariable for [T; 2] {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(vec![
            self[0].push_var(),
            self[1].push_var()
        ]))
    }
}

impl<T: PushVariable> PushVariable for [T; 3] {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(vec![
            self[0].push_var(),
            self[1].push_var(),
            self[2].push_var()
        ]))
    }
}

impl<T: PushVariable> PushVariable for [T; 4] {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(vec![
            self[0].push_var(),
            self[1].push_var(),
            self[2].push_var(),
            self[3].push_var()
        ]))
    }
}

impl<T: PushVariable, U: PushVariable> PushVariable for (T, U) {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(vec![
            self.0.push_var(),
            self.1.push_var()
        ]))
    }
}

impl<T: PushVariable, U: PushVariable, V: PushVariable> PushVariable for (T, U, V) {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(vec![
            self.0.push_var(),
            self.1.push_var(),
            self.2.push_var()
        ]))
    }
}

impl<T: PushVariable, U: PushVariable, V: PushVariable, W: PushVariable>
PushVariable for (T, U, V, W) {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(vec![
            self.0.push_var(),
            self.1.push_var(),
            self.2.push_var(),
            self.3.push_var()
        ]))
    }
}

impl<T: PushVariable> PushVariable for Vec<T> {
    fn push_var(&self) -> Variable {
        Variable::Array(Arc::new(self.iter().map(|it| it.push_var()).collect()))
    }
}

impl ConvertVec4 for [f32; 2] {
    fn from(val: [f32; 4]) -> Self { [val[0], val[1]] }
    fn to(&self) -> [f32; 4] { [self[0], self[1], 0.0, 0.0] }
}

impl ConvertVec4 for [f32; 3] {
    fn from(val: [f32; 4]) -> Self { [val[0], val[1], val[2]] }
    fn to(&self) -> [f32; 4] { [self[0], self[1], self[2], 0.0] }
}

impl ConvertVec4 for [f32; 4] {
    fn from(val: [f32; 4]) -> Self { val }
    fn to(&self) -> [f32; 4] { *self }
}

impl ConvertVec4 for [f64; 2] {
    fn from(val: [f32; 4]) -> Self { [val[0] as f64, val[1] as f64] }
    fn to(&self) -> [f32; 4] { [self[0] as f32, self[1] as f32, 0.0, 0.0] }
}

impl ConvertVec4 for [f64; 3] {
    fn from(val: [f32; 4]) -> Self { [val[0] as f64, val[1] as f64, val[2] as f64] }
    fn to(&self) -> [f32; 4] { [self[0] as f32, self[1] as f32, self[2] as f32, 0.0] }
}

impl ConvertVec4 for [f64; 4] {
    fn from(val: [f32; 4]) -> Self { [val[0] as f64, val[1] as f64, val[2] as f64, val[3] as f64] }
    fn to(&self) -> [f32; 4] { [self[0] as f32, self[1] as f32, self[2] as f32, self[3] as f32] }
}
<|endoftext|>


<commit_before>//! Implements the custom `GrafenError` class for the library.

use std::error;
use std::fmt;
use std::io;
use std::result;

#[derive(Debug)]
/// A class for configuration or runtime errors.
pub enum GrafenError {
    /// Something went wrong when reading or writing.
    IoError(io::Error),
    /// Something went wrong when creating the system.
    RunError(String),
}

/// Shorthand for our `Result` class.
pub type Result<T> = result::Result<T, GrafenError>;

impl fmt::Display for GrafenError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GrafenError::IoError(ref err) => {
                write!(f, "{}", err)
            },
            GrafenError::RunError(ref err) => {
                write!(f, "{}", err)
            },
        }
    }
}

impl error::Error for GrafenError {
    fn description(&self) -> &str {
        match *self {
            GrafenError::IoError(ref err) => err.description(),
            GrafenError::RunError(ref err) => &err,
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            GrafenError::IoError(ref err) => Some(err),
            GrafenError::RunError(_) => None, // There is no good cause for this currently.
        }
    }
}

impl From<io::Error> for GrafenError {
    fn from(err: io::Error) -> GrafenError {
        GrafenError::IoError(err)
    }
}
<commit_msg>Remove `IOError` from `GrafenError`<commit_after>//! Implements the custom `GrafenError` class for the library.

use std::error;
use std::fmt;
use std::result;

#[derive(Debug)]
/// A class for configuration or runtime errors.
pub enum GrafenError {
    /// Something went wrong when creating the system.
    RunError(String),
}

/// Shorthand for our `Result` class.
pub type Result<T> = result::Result<T, GrafenError>;

impl fmt::Display for GrafenError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GrafenError::RunError(ref err) => {
                write!(f, "{}", err)
            },
        }
    }
}

impl error::Error for GrafenError {
    fn description(&self) -> &str {
        match *self {
            GrafenError::RunError(ref err) => &err,
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            GrafenError::RunError(_) => None, // There is no good cause for this currently.
        }
    }
}
<|endoftext|>