<commit_before>pub use crate::format::parse::Error as Parse;
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, vec::Vec};
use core::fmt;

/// A unified error type for anything returned by a method in the time crate.
///
/// This can be used when you either don't know or don't care about the exact
/// error returned. `Result<_, time::Error>` will work in these situations.
// Boxing the `ComponentRange` reduces the size of `Error` from 72 bytes to 16.
#[allow(clippy::missing_docs_in_private_items)] // variants only
#[cfg_attr(__time_02_supports_non_exhaustive, non_exhaustive)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
    ConversionRange(ConversionRange),
    ComponentRange(Box<ComponentRange>),
    Parse(Parse),
    IndeterminateOffset(IndeterminateOffset),
    #[cfg(not(__time_02_supports_non_exhaustive))]
    #[doc(hidden)]
    __NonExhaustive,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::ConversionRange(e) => e.fmt(f),
            Error::ComponentRange(e) => e.fmt(f),
            Error::Parse(e) => e.fmt(f),
            Error::IndeterminateOffset(e) => e.fmt(f),
            #[cfg(not(__time_02_supports_non_exhaustive))]
            Error::__NonExhaustive => unreachable!(),
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Error::ConversionRange(err) => Some(err),
            Error::ComponentRange(box_err) => Some(box_err.as_ref()),
            Error::Parse(err) => Some(err),
            Error::IndeterminateOffset(err) => Some(err),
            #[cfg(not(__time_02_supports_non_exhaustive))]
            Error::__NonExhaustive => unreachable!(),
        }
    }
}

/// An error type indicating that a conversion failed because the target type
/// could not store the initial value.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ConversionRange {
    #[allow(clippy::missing_docs_in_private_items)]
    __non_exhaustive: (),
}

impl ConversionRange {
    #[allow(clippy::missing_docs_in_private_items)]
    pub(crate) const fn new() -> Self {
        Self {
            __non_exhaustive: (),
        }
    }
}

impl fmt::Display for ConversionRange {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Source value is out of range for the target type")
    }
}

#[cfg(feature = "std")]
impl std::error::Error for ConversionRange {}

impl From<ConversionRange> for Error {
    fn from(original: ConversionRange) -> Self {
        Error::ConversionRange(original)
    }
}

/// An error type indicating that a component provided to a method was out of
/// range, causing a failure.
// i64 is the narrowest type fitting all use cases. This eliminates the need
// for a type parameter.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ComponentRange {
    /// Name of the component.
    pub(crate) name: &'static str,
    /// Minimum allowed value, inclusive.
    pub(crate) minimum: i64,
    /// Maximum allowed value, inclusive.
    pub(crate) maximum: i64,
    /// Value that was provided.
    pub(crate) value: i64,
    /// The minimum and/or maximum value is conditional on the value of other
    /// parameters.
    pub(crate) conditional_range: bool,
}

impl fmt::Display for ComponentRange {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{} must be in the range {}..={}",
            self.name, self.minimum, self.maximum
        )?;

        if self.conditional_range {
            write!(f, ", given values of other parameters")?;
        }

        Ok(())
    }
}

impl From<ComponentRange> for Error {
    fn from(original: ComponentRange) -> Self {
        Error::ComponentRange(Box::new(original))
    }
}

#[cfg(feature = "std")]
impl std::error::Error for ComponentRange {}

impl From<Parse> for Error {
    fn from(original: Parse) -> Self {
        Error::Parse(original)
    }
}

/// The system's UTC offset could not be determined at the given datetime.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IndeterminateOffset {
    #[allow(clippy::missing_docs_in_private_items)]
    __non_exhaustive: (),
}

impl IndeterminateOffset {
    #[allow(clippy::missing_docs_in_private_items, dead_code)]
    pub(crate) const fn new() -> Self {
        Self {
            __non_exhaustive: (),
        }
    }
}

impl fmt::Display for IndeterminateOffset {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("The system's UTC offset could not be determined")
    }
}

#[cfg(feature = "std")]
impl std::error::Error for IndeterminateOffset {}

impl From<IndeterminateOffset> for Error {
    fn from(original: IndeterminateOffset) -> Self {
        Error::IndeterminateOffset(original)
    }
}
<commit_msg>Remove unused import<commit_after>pub use crate::format::parse::Error as Parse;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
use core::fmt;

/// A unified error type for anything returned by a method in the time crate.
///
/// This can be used when you either don't know or don't care about the exact
/// error returned. `Result<_, time::Error>` will work in these situations.
// Boxing the `ComponentRange` reduces the size of `Error` from 72 bytes to 16.
#[allow(clippy::missing_docs_in_private_items)] // variants only
#[cfg_attr(__time_02_supports_non_exhaustive, non_exhaustive)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Error {
    ConversionRange(ConversionRange),
    ComponentRange(Box<ComponentRange>),
    Parse(Parse),
    IndeterminateOffset(IndeterminateOffset),
    #[cfg(not(__time_02_supports_non_exhaustive))]
    #[doc(hidden)]
    __NonExhaustive,
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::ConversionRange(e) => e.fmt(f),
            Error::ComponentRange(e) => e.fmt(f),
            Error::Parse(e) => e.fmt(f),
            Error::IndeterminateOffset(e) => e.fmt(f),
            #[cfg(not(__time_02_supports_non_exhaustive))]
            Error::__NonExhaustive => unreachable!(),
        }
    }
}

#[cfg(feature = "std")]
impl std::error::Error for Error {
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
        match self {
            Error::ConversionRange(err) => Some(err),
            Error::ComponentRange(box_err) => Some(box_err.as_ref()),
            Error::Parse(err) => Some(err),
            Error::IndeterminateOffset(err) => Some(err),
            #[cfg(not(__time_02_supports_non_exhaustive))]
            Error::__NonExhaustive => unreachable!(),
        }
    }
}

/// An error type indicating that a conversion failed because the target type
/// could not store the initial value.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ConversionRange {
    #[allow(clippy::missing_docs_in_private_items)]
    __non_exhaustive: (),
}

impl ConversionRange {
    #[allow(clippy::missing_docs_in_private_items)]
    pub(crate) const fn new() -> Self {
        Self {
            __non_exhaustive: (),
        }
    }
}

impl fmt::Display for ConversionRange {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("Source value is out of range for the target type")
    }
}

#[cfg(feature = "std")]
impl std::error::Error for ConversionRange {}

impl From<ConversionRange> for Error {
    fn from(original: ConversionRange) -> Self {
        Error::ConversionRange(original)
    }
}

/// An error type indicating that a component provided to a method was out of
/// range, causing a failure.
// i64 is the narrowest type fitting all use cases. This eliminates the need
// for a type parameter.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ComponentRange {
    /// Name of the component.
    pub(crate) name: &'static str,
    /// Minimum allowed value, inclusive.
    pub(crate) minimum: i64,
    /// Maximum allowed value, inclusive.
    pub(crate) maximum: i64,
    /// Value that was provided.
    pub(crate) value: i64,
    /// The minimum and/or maximum value is conditional on the value of other
    /// parameters.
    pub(crate) conditional_range: bool,
}

impl fmt::Display for ComponentRange {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{} must be in the range {}..={}",
            self.name, self.minimum, self.maximum
        )?;

        if self.conditional_range {
            write!(f, ", given values of other parameters")?;
        }

        Ok(())
    }
}

impl From<ComponentRange> for Error {
    fn from(original: ComponentRange) -> Self {
        Error::ComponentRange(Box::new(original))
    }
}

#[cfg(feature = "std")]
impl std::error::Error for ComponentRange {}

impl From<Parse> for Error {
    fn from(original: Parse) -> Self {
        Error::Parse(original)
    }
}

/// The system's UTC offset could not be determined at the given datetime.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct IndeterminateOffset {
    #[allow(clippy::missing_docs_in_private_items)]
    __non_exhaustive: (),
}

impl IndeterminateOffset {
    #[allow(clippy::missing_docs_in_private_items, dead_code)]
    pub(crate) const fn new() -> Self {
        Self {
            __non_exhaustive: (),
        }
    }
}

impl fmt::Display for IndeterminateOffset {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("The system's UTC offset could not be determined")
    }
}

#[cfg(feature = "std")]
impl std::error::Error for IndeterminateOffset {}

impl From<IndeterminateOffset> for Error {
    fn from(original: IndeterminateOffset) -> Self {
        Error::IndeterminateOffset(original)
    }
}
<|endoftext|>


<commit_before>use crate::path::Path;
use serde::{de, ser};
use std::error;
use std::fmt::{self, Debug, Display};
use std::io;
use std::result;
use std::str;
use std::string;
use std::sync::Arc;
use yaml_rust::emitter;
use yaml_rust::scanner::{self, Marker, ScanError};

/// An error that happened serializing or deserializing YAML data.
pub struct Error(Box<ErrorImpl>);

/// Alias for a `Result` with the error type `serde_yaml::Error`.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub enum ErrorImpl {
    Message(String, Option<Pos>),

    Emit(emitter::EmitError),
    Scan(scanner::ScanError),
    Io(io::Error),
    Utf8(str::Utf8Error),
    FromUtf8(string::FromUtf8Error),

    EndOfStream,
    MoreThanOneDocument,
    RecursionLimitExceeded,

    Shared(Arc<ErrorImpl>),
}

#[derive(Debug)]
pub struct Pos {
    marker: Marker,
    path: String,
}

/// The input location that an error occured.
#[derive(Debug)]
pub struct Location {
    index: usize,
    line: usize,
    column: usize,
}

impl Location {
    /// The byte index of the error
    pub fn index(&self) -> usize {
        self.index
    }

    /// The line of the error
    pub fn line(&self) -> usize {
        self.line
    }

    /// The column of the error
    pub fn column(&self) -> usize {
        self.column
    }

    // This is to keep decoupled with the yaml crate
    #[doc(hidden)]
    fn from_marker(marker: &Marker) -> Self {
        Location {
            // `col` returned from the `yaml` crate is 0-indexed but all error messages add + 1 to this value
            column: marker.col() + 1,
            index: marker.index(),
            line: marker.line(),
        }
    }
}

impl Error {
    /// Returns the Location from the error if one exists.
    ///
    /// Not all types of errors have a location so this can return `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use serde_yaml::{Value, Error};
    /// #
    /// // The `@` character as the first character makes this invalid yaml
    /// let invalid_yaml: Result<Value, Error> = serde_yaml::from_str("@invalid_yaml");
    ///
    /// let location = invalid_yaml.unwrap_err().location().unwrap();
    ///
    /// assert_eq!(location.line(), 1);
    /// assert_eq!(location.column(), 1);
    /// ```
    pub fn location(&self) -> Option<Location> {
        match self.0.as_ref() {
            ErrorImpl::Message(_, Some(pos)) => Some(Location::from_marker(&pos.marker)),
            ErrorImpl::Scan(scan) => Some(Location::from_marker(scan.marker())),
            _ => None,
        }
    }
}

pub(crate) fn end_of_stream() -> Error {
    Error(Box::new(ErrorImpl::EndOfStream))
}

pub(crate) fn more_than_one_document() -> Error {
    Error(Box::new(ErrorImpl::MoreThanOneDocument))
}

pub(crate) fn io(err: io::Error) -> Error {
    Error(Box::new(ErrorImpl::Io(err)))
}

pub(crate) fn emitter(err: emitter::EmitError) -> Error {
    Error(Box::new(ErrorImpl::Emit(err)))
}

pub(crate) fn scanner(err: scanner::ScanError) -> Error {
    Error(Box::new(ErrorImpl::Scan(err)))
}

pub(crate) fn str_utf8(err: str::Utf8Error) -> Error {
    Error(Box::new(ErrorImpl::Utf8(err)))
}

pub(crate) fn string_utf8(err: string::FromUtf8Error) -> Error {
    Error(Box::new(ErrorImpl::FromUtf8(err)))
}

pub(crate) fn recursion_limit_exceeded() -> Error {
    Error(Box::new(ErrorImpl::RecursionLimitExceeded))
}

pub(crate) fn shared(shared: Arc<ErrorImpl>) -> Error {
    Error(Box::new(ErrorImpl::Shared(shared)))
}

pub(crate) fn fix_marker(mut error: Error, marker: Marker, path: Path) -> Error {
    if let ErrorImpl::Message(_, none @ None) = error.0.as_mut() {
        *none = Some(Pos {
            marker,
            path: path.to_string(),
        });
    }
    error
}

impl Error {
    pub(crate) fn shared(self) -> Arc<ErrorImpl> {
        if let ErrorImpl::Shared(err) = *self.0 {
            err
        } else {
            Arc::from(self.0)
        }
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        self.0.source()
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.display(f)
    }
}

// Remove two layers of verbosity from the debug representation. Humans often
// end up seeing this representation because it is what unwrap() shows.
impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.debug(f)
    }
}

impl ser::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
    }
}

impl de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
    }
}

impl ErrorImpl {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            ErrorImpl::Scan(err) => Some(err),
            ErrorImpl::Io(err) => Some(err),
            ErrorImpl::Utf8(err) => Some(err),
            ErrorImpl::FromUtf8(err) => Some(err),
            ErrorImpl::Shared(err) => err.source(),
            _ => None,
        }
    }

    fn display(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ErrorImpl::Message(msg, None) => Display::fmt(msg, f),
            ErrorImpl::Message(msg, Some(Pos { marker, path })) => {
                if path == "." {
                    write!(f, "{}", ScanError::new(*marker, msg))
                } else {
                    write!(f, "{}: {}", path, ScanError::new(*marker, msg))
                }
            }
            ErrorImpl::Emit(emitter::EmitError::FmtError(_)) => f.write_str("yaml-rust fmt error"),
            ErrorImpl::Emit(emitter::EmitError::BadHashmapKey) => f.write_str("bad hash map key"),
            ErrorImpl::Scan(err) => Display::fmt(err, f),
            ErrorImpl::Io(err) => Display::fmt(err, f),
            ErrorImpl::Utf8(err) => Display::fmt(err, f),
            ErrorImpl::FromUtf8(err) => Display::fmt(err, f),
            ErrorImpl::EndOfStream => f.write_str("EOF while parsing a value"),
            ErrorImpl::MoreThanOneDocument => f.write_str(
                "deserializing from YAML containing more than one document is not supported",
            ),
            ErrorImpl::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
            ErrorImpl::Shared(err) => err.display(f),
        }
    }

    fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ErrorImpl::Message(msg, pos) => f.debug_tuple("Message").field(msg).field(pos).finish(),
            ErrorImpl::Emit(emit) => f.debug_tuple("Emit").field(emit).finish(),
            ErrorImpl::Scan(scan) => f.debug_tuple("Scan").field(scan).finish(),
            ErrorImpl::Io(io) => f.debug_tuple("Io").field(io).finish(),
            ErrorImpl::Utf8(utf8) => f.debug_tuple("Utf8").field(utf8).finish(),
            ErrorImpl::FromUtf8(from_utf8) => f.debug_tuple("FromUtf8").field(from_utf8).finish(),
            ErrorImpl::EndOfStream => f.debug_tuple("EndOfStream").finish(),
            ErrorImpl::MoreThanOneDocument => f.debug_tuple("MoreThanOneDocument").finish(),
            ErrorImpl::RecursionLimitExceeded => f.debug_tuple("RecursionLimitExceeded").finish(),
            ErrorImpl::Shared(err) => err.debug(f),
        }
    }
}
<commit_msg>Reduce visibility of Error internals<commit_after>use crate::path::Path;
use serde::{de, ser};
use std::error;
use std::fmt::{self, Debug, Display};
use std::io;
use std::result;
use std::str;
use std::string;
use std::sync::Arc;
use yaml_rust::emitter;
use yaml_rust::scanner::{self, Marker, ScanError};

/// An error that happened serializing or deserializing YAML data.
pub struct Error(Box<ErrorImpl>);

/// Alias for a `Result` with the error type `serde_yaml::Error`.
pub type Result<T> = result::Result<T, Error>;

#[derive(Debug)]
pub(crate) enum ErrorImpl {
    Message(String, Option<Pos>),

    Emit(emitter::EmitError),
    Scan(scanner::ScanError),
    Io(io::Error),
    Utf8(str::Utf8Error),
    FromUtf8(string::FromUtf8Error),

    EndOfStream,
    MoreThanOneDocument,
    RecursionLimitExceeded,

    Shared(Arc<ErrorImpl>),
}

#[derive(Debug)]
pub(crate) struct Pos {
    marker: Marker,
    path: String,
}

/// The input location that an error occured.
#[derive(Debug)]
pub struct Location {
    index: usize,
    line: usize,
    column: usize,
}

impl Location {
    /// The byte index of the error
    pub fn index(&self) -> usize {
        self.index
    }

    /// The line of the error
    pub fn line(&self) -> usize {
        self.line
    }

    /// The column of the error
    pub fn column(&self) -> usize {
        self.column
    }

    // This is to keep decoupled with the yaml crate
    #[doc(hidden)]
    fn from_marker(marker: &Marker) -> Self {
        Location {
            // `col` returned from the `yaml` crate is 0-indexed but all error messages add + 1 to this value
            column: marker.col() + 1,
            index: marker.index(),
            line: marker.line(),
        }
    }
}

impl Error {
    /// Returns the Location from the error if one exists.
    ///
    /// Not all types of errors have a location so this can return `None`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use serde_yaml::{Value, Error};
    /// #
    /// // The `@` character as the first character makes this invalid yaml
    /// let invalid_yaml: Result<Value, Error> = serde_yaml::from_str("@invalid_yaml");
    ///
    /// let location = invalid_yaml.unwrap_err().location().unwrap();
    ///
    /// assert_eq!(location.line(), 1);
    /// assert_eq!(location.column(), 1);
    /// ```
    pub fn location(&self) -> Option<Location> {
        match self.0.as_ref() {
            ErrorImpl::Message(_, Some(pos)) => Some(Location::from_marker(&pos.marker)),
            ErrorImpl::Scan(scan) => Some(Location::from_marker(scan.marker())),
            _ => None,
        }
    }
}

pub(crate) fn end_of_stream() -> Error {
    Error(Box::new(ErrorImpl::EndOfStream))
}

pub(crate) fn more_than_one_document() -> Error {
    Error(Box::new(ErrorImpl::MoreThanOneDocument))
}

pub(crate) fn io(err: io::Error) -> Error {
    Error(Box::new(ErrorImpl::Io(err)))
}

pub(crate) fn emitter(err: emitter::EmitError) -> Error {
    Error(Box::new(ErrorImpl::Emit(err)))
}

pub(crate) fn scanner(err: scanner::ScanError) -> Error {
    Error(Box::new(ErrorImpl::Scan(err)))
}

pub(crate) fn str_utf8(err: str::Utf8Error) -> Error {
    Error(Box::new(ErrorImpl::Utf8(err)))
}

pub(crate) fn string_utf8(err: string::FromUtf8Error) -> Error {
    Error(Box::new(ErrorImpl::FromUtf8(err)))
}

pub(crate) fn recursion_limit_exceeded() -> Error {
    Error(Box::new(ErrorImpl::RecursionLimitExceeded))
}

pub(crate) fn shared(shared: Arc<ErrorImpl>) -> Error {
    Error(Box::new(ErrorImpl::Shared(shared)))
}

pub(crate) fn fix_marker(mut error: Error, marker: Marker, path: Path) -> Error {
    if let ErrorImpl::Message(_, none @ None) = error.0.as_mut() {
        *none = Some(Pos {
            marker,
            path: path.to_string(),
        });
    }
    error
}

impl Error {
    pub(crate) fn shared(self) -> Arc<ErrorImpl> {
        if let ErrorImpl::Shared(err) = *self.0 {
            err
        } else {
            Arc::from(self.0)
        }
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        self.0.source()
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.display(f)
    }
}

// Remove two layers of verbosity from the debug representation. Humans often
// end up seeing this representation because it is what unwrap() shows.
impl Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.debug(f)
    }
}

impl ser::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
    }
}

impl de::Error for Error {
    fn custom<T: Display>(msg: T) -> Self {
        Error(Box::new(ErrorImpl::Message(msg.to_string(), None)))
    }
}

impl ErrorImpl {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        match self {
            ErrorImpl::Scan(err) => Some(err),
            ErrorImpl::Io(err) => Some(err),
            ErrorImpl::Utf8(err) => Some(err),
            ErrorImpl::FromUtf8(err) => Some(err),
            ErrorImpl::Shared(err) => err.source(),
            _ => None,
        }
    }

    fn display(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ErrorImpl::Message(msg, None) => Display::fmt(msg, f),
            ErrorImpl::Message(msg, Some(Pos { marker, path })) => {
                if path == "." {
                    write!(f, "{}", ScanError::new(*marker, msg))
                } else {
                    write!(f, "{}: {}", path, ScanError::new(*marker, msg))
                }
            }
            ErrorImpl::Emit(emitter::EmitError::FmtError(_)) => f.write_str("yaml-rust fmt error"),
            ErrorImpl::Emit(emitter::EmitError::BadHashmapKey) => f.write_str("bad hash map key"),
            ErrorImpl::Scan(err) => Display::fmt(err, f),
            ErrorImpl::Io(err) => Display::fmt(err, f),
            ErrorImpl::Utf8(err) => Display::fmt(err, f),
            ErrorImpl::FromUtf8(err) => Display::fmt(err, f),
            ErrorImpl::EndOfStream => f.write_str("EOF while parsing a value"),
            ErrorImpl::MoreThanOneDocument => f.write_str(
                "deserializing from YAML containing more than one document is not supported",
            ),
            ErrorImpl::RecursionLimitExceeded => f.write_str("recursion limit exceeded"),
            ErrorImpl::Shared(err) => err.display(f),
        }
    }

    fn debug(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ErrorImpl::Message(msg, pos) => f.debug_tuple("Message").field(msg).field(pos).finish(),
            ErrorImpl::Emit(emit) => f.debug_tuple("Emit").field(emit).finish(),
            ErrorImpl::Scan(scan) => f.debug_tuple("Scan").field(scan).finish(),
            ErrorImpl::Io(io) => f.debug_tuple("Io").field(io).finish(),
            ErrorImpl::Utf8(utf8) => f.debug_tuple("Utf8").field(utf8).finish(),
            ErrorImpl::FromUtf8(from_utf8) => f.debug_tuple("FromUtf8").field(from_utf8).finish(),
            ErrorImpl::EndOfStream => f.debug_tuple("EndOfStream").finish(),
            ErrorImpl::MoreThanOneDocument => f.debug_tuple("MoreThanOneDocument").finish(),
            ErrorImpl::RecursionLimitExceeded => f.debug_tuple("RecursionLimitExceeded").finish(),
            ErrorImpl::Shared(err) => err.debug(f),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;

use syntax;

/// An error that occurred during parsing or compiling a regular expression.
#[derive(Debug)]
pub enum Error {
    /// A syntax error.
    Syntax(String),
    /// The compiled program exceeded the set size limit.
    /// The argument is the size limit imposed.
    CompiledTooBig(usize),
    /// Hints that destructuring should not be exhaustive.
    ///
    /// This enum may grow additional variants, so this makes sure clients
    /// don't count on exhaustive matching. (Otherwise, adding a new variant
    /// could break existing code.)
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Syntax(ref err) => err,
            Error::CompiledTooBig(_) => "compiled program too big",
            Error::__Nonexhaustive => unreachable!(),
        }
    }

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

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Syntax(ref err) => err.fmt(f),
            Error::CompiledTooBig(limit) => {
                write!(f, "Compiled regex exceeds size limit of {} bytes.",
                       limit)
            }
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

impl From<syntax::Error> for Error {
    fn from(err: syntax::Error) -> Error {
        Error::Syntax(err.to_string())
    }
}
<commit_msg>Auto merge of #380 - remexre:impls-for-error, r=BurntSushi<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;

use syntax;

/// An error that occurred during parsing or compiling a regular expression.
#[derive(Clone, Debug, PartialEq)]
pub enum Error {
    /// A syntax error.
    Syntax(String),
    /// The compiled program exceeded the set size limit.
    /// The argument is the size limit imposed.
    CompiledTooBig(usize),
    /// Hints that destructuring should not be exhaustive.
    ///
    /// This enum may grow additional variants, so this makes sure clients
    /// don't count on exhaustive matching. (Otherwise, adding a new variant
    /// could break existing code.)
    #[doc(hidden)]
    __Nonexhaustive,
}

impl ::std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Syntax(ref err) => err,
            Error::CompiledTooBig(_) => "compiled program too big",
            Error::__Nonexhaustive => unreachable!(),
        }
    }

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

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Syntax(ref err) => err.fmt(f),
            Error::CompiledTooBig(limit) => {
                write!(f, "Compiled regex exceeds size limit of {} bytes.",
                       limit)
            }
            Error::__Nonexhaustive => unreachable!(),
        }
    }
}

impl From<syntax::Error> for Error {
    fn from(err: syntax::Error) -> Error {
        Error::Syntax(err.to_string())
    }
}
<|endoftext|>


<commit_before>//! Process window events
use std::borrow::Cow;
use std::fs::File;
use std::io::Write;
use std::sync::mpsc;
use std::time::{Instant};

use serde_json as json;
use parking_lot::MutexGuard;
use glutin::{self, ModifiersState, Event, ElementState};
use copypasta::{Clipboard, Load, Store};

use config::{self, Config};
use cli::Options;
use display::OnResize;
use index::{Line, Column, Side, Point};
use input::{self, MouseBinding, KeyBinding};
use selection::Selection;
use sync::FairMutex;
use term::{Term, SizeInfo, TermMode};
use util::limit;
use util::fmt::Red;
use window::Window;

/// Byte sequences are sent to a `Notify` in response to some events
pub trait Notify {
    /// Notify that an escape sequence should be written to the pty
    ///
    /// TODO this needs to be able to error somehow
    fn notify<B: Into<Cow<'static, [u8]>>>(&mut self, B);
}

pub struct ActionContext<'a, N: 'a> {
    pub notifier: &'a mut N,
    pub terminal: &'a mut Term,
    pub selection: &'a mut Option<Selection>,
    pub size_info: &'a SizeInfo,
    pub mouse: &'a mut Mouse,
    pub selection_modified: bool,
    pub received_count: &'a mut usize,
    pub suppress_chars: &'a mut bool,
    pub last_modifiers: &'a mut ModifiersState,
}

impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> {
    fn write_to_pty<B: Into<Cow<'static, [u8]>>>(&mut self, val: B) {
        self.notifier.notify(val);
    }

    fn terminal_mode(&self) -> TermMode {
        *self.terminal.mode()
    }

    fn size_info(&self) -> SizeInfo {
        *self.size_info
    }

    fn copy_selection(&self, buffer: ::copypasta::Buffer) {
        if let Some(ref selection) = *self.selection {
            selection.to_span(self.terminal)
                .map(|span| {
                    let buf = self.terminal.string_from_selection(&span);
                    if !buf.is_empty() {
                        Clipboard::new()
                            .and_then(|mut clipboard| clipboard.store(buf, buffer))
                            .unwrap_or_else(|err| {
                                warn!("Error storing selection to clipboard. {}", Red(err));
                            });
                    }
                });
        }
    }

    fn clear_selection(&mut self) {
        *self.selection = None;
        self.selection_modified = true;
    }

    fn update_selection(&mut self, point: Point, side: Side) {
        self.selection_modified = true;
        // Update selection if one exists
        if let Some(ref mut selection) = *self.selection {
            selection.update(point, side);
            return;
        }

        // Otherwise, start a regular selection
        self.simple_selection(point, side);
    }

    fn simple_selection(&mut self, point: Point, side: Side) {
        *self.selection = Some(Selection::simple(point, side));
        self.selection_modified = true;
    }

    fn semantic_selection(&mut self, point: Point) {
        *self.selection = Some(Selection::semantic(point, self.terminal));
        self.selection_modified = true;
    }

    fn line_selection(&mut self, point: Point) {
        *self.selection = Some(Selection::lines(point));
        self.selection_modified = true;
    }

    fn mouse_coords(&self) -> Option<Point> {
        self.terminal.pixels_to_coords(self.mouse.x as usize, self.mouse.y as usize)
    }

    fn change_font_size(&mut self, delta: i8) {
        self.terminal.change_font_size(delta);
    }

    fn reset_font_size(&mut self) {
        self.terminal.reset_font_size();
    }

    #[inline]
    fn mouse_mut(&mut self) -> &mut Mouse {
        self.mouse
    }

    #[inline]
    fn received_count(&mut self) -> &mut usize {
        &mut self.received_count
    }

    #[inline]
    fn suppress_chars(&mut self) -> &mut bool {
        &mut self.suppress_chars
    }

    #[inline]
    fn last_modifiers(&mut self) -> &mut ModifiersState {
        &mut self.last_modifiers
    }
}

pub enum ClickState {
    None,
    Click,
    DoubleClick,
    TripleClick,
}

/// State of the mouse
pub struct Mouse {
    pub x: u32,
    pub y: u32,
    pub left_button_state: ElementState,
    pub middle_button_state: ElementState,
    pub right_button_state: ElementState,
    pub last_click_timestamp: Instant,
    pub click_state: ClickState,
    pub scroll_px: i32,
    pub line: Line,
    pub column: Column,
    pub cell_side: Side,
    pub lines_scrolled: f32,
}

impl Default for Mouse {
    fn default() -> Mouse {
        Mouse {
            x: 0,
            y: 0,
            last_click_timestamp: Instant::now(),
            left_button_state: ElementState::Released,
            middle_button_state: ElementState::Released,
            right_button_state: ElementState::Released,
            click_state: ClickState::None,
            scroll_px: 0,
            line: Line(0),
            column: Column(0),
            cell_side: Side::Left,
            lines_scrolled: 0.0,
        }
    }
}

/// The event processor
///
/// Stores some state from received events and dispatches actions when they are
/// triggered.
pub struct Processor<N> {
    key_bindings: Vec<KeyBinding>,
    mouse_bindings: Vec<MouseBinding>,
    mouse_config: config::Mouse,
    print_events: bool,
    wait_for_event: bool,
    notifier: N,
    mouse: Mouse,
    resize_tx: mpsc::Sender<(u32, u32)>,
    ref_test: bool,
    size_info: SizeInfo,
    pub selection: Option<Selection>,
    hide_cursor_when_typing: bool,
    hide_cursor: bool,
    received_count: usize,
    suppress_chars: bool,
    last_modifiers: ModifiersState,
    pending_events: Vec<Event>,
}

/// Notify that the terminal was resized
///
/// Currently this just forwards the notice to the input processor.
impl<N> OnResize for Processor<N> {
    fn on_resize(&mut self, size: &SizeInfo) {
        self.size_info = size.to_owned();
        self.selection = None;
    }
}

impl<N: Notify> Processor<N> {
    /// Create a new event processor
    ///
    /// Takes a writer which is expected to be hooked up to the write end of a
    /// pty.
    pub fn new(
        notifier: N,
        resize_tx: mpsc::Sender<(u32, u32)>,
        options: &Options,
        config: &Config,
        ref_test: bool,
        size_info: SizeInfo,
    ) -> Processor<N> {
        Processor {
            key_bindings: config.key_bindings().to_vec(),
            mouse_bindings: config.mouse_bindings().to_vec(),
            mouse_config: config.mouse().to_owned(),
            print_events: options.print_events,
            wait_for_event: true,
            notifier,
            resize_tx,
            ref_test,
            mouse: Default::default(),
            selection: None,
            size_info,
            hide_cursor_when_typing: config.hide_cursor_when_typing(),
            hide_cursor: false,
            received_count: 0,
            suppress_chars: false,
            last_modifiers: Default::default(),
            pending_events: Vec::with_capacity(4),
        }
    }

    /// Handle events from glutin
    ///
    /// Doesn't take self mutably due to borrow checking. Kinda uggo but w/e.
    fn handle_event<'a>(
        processor: &mut input::Processor<'a, ActionContext<'a, N>>,
        event: Event,
        ref_test: bool,
        resize_tx: &mpsc::Sender<(u32, u32)>,
        hide_cursor: &mut bool,
        window_is_focused: &mut bool,
    ) {
        match event {
            // Pass on device events
            Event::DeviceEvent { .. } | Event::Suspended { .. } => (),
            Event::WindowEvent { event, .. } => {
                use glutin::WindowEvent::*;
                match event {
                    Closed => {
                        if ref_test {
                            // dump grid state
                            let grid = processor.ctx.terminal.grid();

                            let serialized_grid = json::to_string(&grid)
                                .expect("serialize grid");

                            let serialized_size = json::to_string(processor.ctx.terminal.size_info())
                                .expect("serialize size");

                            File::create("./grid.json")
                                .and_then(|mut f| f.write_all(serialized_grid.as_bytes()))
                                .expect("write grid.json");

                            File::create("./size.json")
                                .and_then(|mut f| f.write_all(serialized_size.as_bytes()))
                                .expect("write size.json");
                        }

                        // FIXME should do a more graceful shutdown
                        ::std::process::exit(0);
                    },
                    Resized(w, h) => {
                        resize_tx.send((w, h)).expect("send new size");
                        processor.ctx.terminal.dirty = true;
                    },
                    KeyboardInput { input, .. } => {
                        let glutin::KeyboardInput { state, virtual_keycode, modifiers, .. } = input;
                        processor.process_key(state, virtual_keycode, &modifiers);
                        if state == ElementState::Pressed {
                            // Hide cursor while typing
                            *hide_cursor = true;
                        }
                    },
                    ReceivedCharacter(c) => {
                        processor.received_char(c);
                    },
                    MouseInput { state, button, modifiers, .. } => {
                        *hide_cursor = false;
                        processor.mouse_input(state, button, modifiers);
                        processor.ctx.terminal.dirty = true;
                    },
                    CursorMoved { position: (x, y), modifiers, .. } => {
                        let x = x as i32;
                        let y = y as i32;
                        let x = limit(x, 0, processor.ctx.size_info.width as i32);
                        let y = limit(y, 0, processor.ctx.size_info.height as i32);

                        *hide_cursor = false;
                        processor.mouse_moved(x as u32, y as u32, modifiers);

                        if !processor.ctx.selection.is_none() {
                            processor.ctx.terminal.dirty = true;
                        }
                    },
                    MouseWheel { delta, phase, modifiers, .. } => {
                        *hide_cursor = false;
                        processor.on_mouse_wheel(delta, phase, modifiers);
                    },
                    Refresh => {
                        processor.ctx.terminal.dirty = true;
                    },
                    Focused(is_focused) => {
                        *window_is_focused = is_focused;

                        if is_focused {
                            processor.ctx.terminal.dirty = true;
                            processor.ctx.terminal.next_is_urgent = Some(false);
                        } else {
                            processor.ctx.terminal.dirty = true;
                            *hide_cursor = false;
                        }

                        processor.on_focus_change(is_focused);
                    }
                    _ => (),
                }
            },
            Event::Awakened => {
                processor.ctx.terminal.dirty = true;
            }
        }
    }

    /// Process events. When `wait_for_event` is set, this method is guaranteed
    /// to process at least one event.
    pub fn process_events<'a>(
        &mut self,
        term: &'a FairMutex<Term>,
        window: &mut Window
    ) -> MutexGuard<'a, Term> {
        // Terminal is lazily initialized the first time an event is returned
        // from the blocking WaitEventsIterator. Otherwise, the pty reader would
        // be blocked the entire time we wait for input!
        let mut terminal;

        self.pending_events.clear();

        {
            // Ditto on lazy initialization for context and processor.
            let context;
            let mut processor: input::Processor<ActionContext<N>>;

            let print_events = self.print_events;

            let ref_test = self.ref_test;
            let resize_tx = &self.resize_tx;

            if self.wait_for_event {
                // A Vec is used here since wait_events can potentially yield
                // multiple events before the interrupt is handled. For example,
                // Resize and Moved events.
                let pending_events = &mut self.pending_events;
                window.wait_events(|e| {
                    pending_events.push(e);
                    glutin::ControlFlow::Break
                });
            }

            terminal = term.lock();

            context = ActionContext {
                terminal: &mut terminal,
                notifier: &mut self.notifier,
                selection: &mut self.selection,
                mouse: &mut self.mouse,
                size_info: &self.size_info,
                selection_modified: false,
                received_count: &mut self.received_count,
                suppress_chars: &mut self.suppress_chars,
                last_modifiers: &mut self.last_modifiers,
            };

            processor = input::Processor {
                ctx: context,
                mouse_config: &self.mouse_config,
                key_bindings: &self.key_bindings[..],
                mouse_bindings: &self.mouse_bindings[..],
            };

            let mut window_is_focused = window.is_focused;

            // Scope needed to that hide_cursor isn't borrowed after the scope
            // ends.
            {
                let hide_cursor = &mut self.hide_cursor;
                let mut process = |event| {
                    if print_events {
                        println!("glutin event: {:?}", event);
                    }
                    Processor::handle_event(
                        &mut processor,
                        event,
                        ref_test,
                        resize_tx,
                        hide_cursor,
                        &mut window_is_focused,
                    );
                };

                for event in self.pending_events.drain(..) {
                    process(event);
                }

                window.poll_events(process);
            }

            if self.hide_cursor_when_typing {
                window.set_cursor_visible(!self.hide_cursor);
            }

            window.is_focused = window_is_focused;

            if processor.ctx.selection_modified {
                processor.ctx.terminal.dirty = true;
            }
        }

        self.wait_for_event = !terminal.dirty;

        terminal
    }

    pub fn update_config(&mut self, config: &Config) {
        self.key_bindings = config.key_bindings().to_vec();
        self.mouse_bindings = config.mouse_bindings().to_vec();
        self.mouse_config = config.mouse().to_owned();
    }
}
<commit_msg>Paste path into terminal when drag & dropping file<commit_after>//! Process window events
use std::borrow::Cow;
use std::fs::File;
use std::io::Write;
use std::sync::mpsc;
use std::time::{Instant};

use serde_json as json;
use parking_lot::MutexGuard;
use glutin::{self, ModifiersState, Event, ElementState};
use copypasta::{Clipboard, Load, Store};

use config::{self, Config};
use cli::Options;
use display::OnResize;
use index::{Line, Column, Side, Point};
use input::{self, MouseBinding, KeyBinding};
use selection::Selection;
use sync::FairMutex;
use term::{Term, SizeInfo, TermMode};
use util::limit;
use util::fmt::Red;
use window::Window;

/// Byte sequences are sent to a `Notify` in response to some events
pub trait Notify {
    /// Notify that an escape sequence should be written to the pty
    ///
    /// TODO this needs to be able to error somehow
    fn notify<B: Into<Cow<'static, [u8]>>>(&mut self, B);
}

pub struct ActionContext<'a, N: 'a> {
    pub notifier: &'a mut N,
    pub terminal: &'a mut Term,
    pub selection: &'a mut Option<Selection>,
    pub size_info: &'a SizeInfo,
    pub mouse: &'a mut Mouse,
    pub selection_modified: bool,
    pub received_count: &'a mut usize,
    pub suppress_chars: &'a mut bool,
    pub last_modifiers: &'a mut ModifiersState,
}

impl<'a, N: Notify + 'a> input::ActionContext for ActionContext<'a, N> {
    fn write_to_pty<B: Into<Cow<'static, [u8]>>>(&mut self, val: B) {
        self.notifier.notify(val);
    }

    fn terminal_mode(&self) -> TermMode {
        *self.terminal.mode()
    }

    fn size_info(&self) -> SizeInfo {
        *self.size_info
    }

    fn copy_selection(&self, buffer: ::copypasta::Buffer) {
        if let Some(ref selection) = *self.selection {
            selection.to_span(self.terminal)
                .map(|span| {
                    let buf = self.terminal.string_from_selection(&span);
                    if !buf.is_empty() {
                        Clipboard::new()
                            .and_then(|mut clipboard| clipboard.store(buf, buffer))
                            .unwrap_or_else(|err| {
                                warn!("Error storing selection to clipboard. {}", Red(err));
                            });
                    }
                });
        }
    }

    fn clear_selection(&mut self) {
        *self.selection = None;
        self.selection_modified = true;
    }

    fn update_selection(&mut self, point: Point, side: Side) {
        self.selection_modified = true;
        // Update selection if one exists
        if let Some(ref mut selection) = *self.selection {
            selection.update(point, side);
            return;
        }

        // Otherwise, start a regular selection
        self.simple_selection(point, side);
    }

    fn simple_selection(&mut self, point: Point, side: Side) {
        *self.selection = Some(Selection::simple(point, side));
        self.selection_modified = true;
    }

    fn semantic_selection(&mut self, point: Point) {
        *self.selection = Some(Selection::semantic(point, self.terminal));
        self.selection_modified = true;
    }

    fn line_selection(&mut self, point: Point) {
        *self.selection = Some(Selection::lines(point));
        self.selection_modified = true;
    }

    fn mouse_coords(&self) -> Option<Point> {
        self.terminal.pixels_to_coords(self.mouse.x as usize, self.mouse.y as usize)
    }

    fn change_font_size(&mut self, delta: i8) {
        self.terminal.change_font_size(delta);
    }

    fn reset_font_size(&mut self) {
        self.terminal.reset_font_size();
    }

    #[inline]
    fn mouse_mut(&mut self) -> &mut Mouse {
        self.mouse
    }

    #[inline]
    fn received_count(&mut self) -> &mut usize {
        &mut self.received_count
    }

    #[inline]
    fn suppress_chars(&mut self) -> &mut bool {
        &mut self.suppress_chars
    }

    #[inline]
    fn last_modifiers(&mut self) -> &mut ModifiersState {
        &mut self.last_modifiers
    }
}

pub enum ClickState {
    None,
    Click,
    DoubleClick,
    TripleClick,
}

/// State of the mouse
pub struct Mouse {
    pub x: u32,
    pub y: u32,
    pub left_button_state: ElementState,
    pub middle_button_state: ElementState,
    pub right_button_state: ElementState,
    pub last_click_timestamp: Instant,
    pub click_state: ClickState,
    pub scroll_px: i32,
    pub line: Line,
    pub column: Column,
    pub cell_side: Side,
    pub lines_scrolled: f32,
}

impl Default for Mouse {
    fn default() -> Mouse {
        Mouse {
            x: 0,
            y: 0,
            last_click_timestamp: Instant::now(),
            left_button_state: ElementState::Released,
            middle_button_state: ElementState::Released,
            right_button_state: ElementState::Released,
            click_state: ClickState::None,
            scroll_px: 0,
            line: Line(0),
            column: Column(0),
            cell_side: Side::Left,
            lines_scrolled: 0.0,
        }
    }
}

/// The event processor
///
/// Stores some state from received events and dispatches actions when they are
/// triggered.
pub struct Processor<N> {
    key_bindings: Vec<KeyBinding>,
    mouse_bindings: Vec<MouseBinding>,
    mouse_config: config::Mouse,
    print_events: bool,
    wait_for_event: bool,
    notifier: N,
    mouse: Mouse,
    resize_tx: mpsc::Sender<(u32, u32)>,
    ref_test: bool,
    size_info: SizeInfo,
    pub selection: Option<Selection>,
    hide_cursor_when_typing: bool,
    hide_cursor: bool,
    received_count: usize,
    suppress_chars: bool,
    last_modifiers: ModifiersState,
    pending_events: Vec<Event>,
}

/// Notify that the terminal was resized
///
/// Currently this just forwards the notice to the input processor.
impl<N> OnResize for Processor<N> {
    fn on_resize(&mut self, size: &SizeInfo) {
        self.size_info = size.to_owned();
        self.selection = None;
    }
}

impl<N: Notify> Processor<N> {
    /// Create a new event processor
    ///
    /// Takes a writer which is expected to be hooked up to the write end of a
    /// pty.
    pub fn new(
        notifier: N,
        resize_tx: mpsc::Sender<(u32, u32)>,
        options: &Options,
        config: &Config,
        ref_test: bool,
        size_info: SizeInfo,
    ) -> Processor<N> {
        Processor {
            key_bindings: config.key_bindings().to_vec(),
            mouse_bindings: config.mouse_bindings().to_vec(),
            mouse_config: config.mouse().to_owned(),
            print_events: options.print_events,
            wait_for_event: true,
            notifier,
            resize_tx,
            ref_test,
            mouse: Default::default(),
            selection: None,
            size_info,
            hide_cursor_when_typing: config.hide_cursor_when_typing(),
            hide_cursor: false,
            received_count: 0,
            suppress_chars: false,
            last_modifiers: Default::default(),
            pending_events: Vec::with_capacity(4),
        }
    }

    /// Handle events from glutin
    ///
    /// Doesn't take self mutably due to borrow checking. Kinda uggo but w/e.
    fn handle_event<'a>(
        processor: &mut input::Processor<'a, ActionContext<'a, N>>,
        event: Event,
        ref_test: bool,
        resize_tx: &mpsc::Sender<(u32, u32)>,
        hide_cursor: &mut bool,
        window_is_focused: &mut bool,
    ) {
        match event {
            // Pass on device events
            Event::DeviceEvent { .. } | Event::Suspended { .. } => (),
            Event::WindowEvent { event, .. } => {
                use glutin::WindowEvent::*;
                match event {
                    Closed => {
                        if ref_test {
                            // dump grid state
                            let grid = processor.ctx.terminal.grid();

                            let serialized_grid = json::to_string(&grid)
                                .expect("serialize grid");

                            let serialized_size = json::to_string(processor.ctx.terminal.size_info())
                                .expect("serialize size");

                            File::create("./grid.json")
                                .and_then(|mut f| f.write_all(serialized_grid.as_bytes()))
                                .expect("write grid.json");

                            File::create("./size.json")
                                .and_then(|mut f| f.write_all(serialized_size.as_bytes()))
                                .expect("write size.json");
                        }

                        // FIXME should do a more graceful shutdown
                        ::std::process::exit(0);
                    },
                    Resized(w, h) => {
                        resize_tx.send((w, h)).expect("send new size");
                        processor.ctx.terminal.dirty = true;
                    },
                    KeyboardInput { input, .. } => {
                        let glutin::KeyboardInput { state, virtual_keycode, modifiers, .. } = input;
                        processor.process_key(state, virtual_keycode, &modifiers);
                        if state == ElementState::Pressed {
                            // Hide cursor while typing
                            *hide_cursor = true;
                        }
                    },
                    ReceivedCharacter(c) => {
                        processor.received_char(c);
                    },
                    MouseInput { state, button, modifiers, .. } => {
                        *hide_cursor = false;
                        processor.mouse_input(state, button, modifiers);
                        processor.ctx.terminal.dirty = true;
                    },
                    CursorMoved { position: (x, y), modifiers, .. } => {
                        let x = x as i32;
                        let y = y as i32;
                        let x = limit(x, 0, processor.ctx.size_info.width as i32);
                        let y = limit(y, 0, processor.ctx.size_info.height as i32);

                        *hide_cursor = false;
                        processor.mouse_moved(x as u32, y as u32, modifiers);

                        if !processor.ctx.selection.is_none() {
                            processor.ctx.terminal.dirty = true;
                        }
                    },
                    MouseWheel { delta, phase, modifiers, .. } => {
                        *hide_cursor = false;
                        processor.on_mouse_wheel(delta, phase, modifiers);
                    },
                    Refresh => {
                        processor.ctx.terminal.dirty = true;
                    },
                    Focused(is_focused) => {
                        *window_is_focused = is_focused;

                        if is_focused {
                            processor.ctx.terminal.dirty = true;
                            processor.ctx.terminal.next_is_urgent = Some(false);
                        } else {
                            processor.ctx.terminal.dirty = true;
                            *hide_cursor = false;
                        }

                        processor.on_focus_change(is_focused);
                    },
                    DroppedFile(path) => {
                        use input::ActionContext;
                        let path: String = path.to_string_lossy().into();
                        processor.ctx.write_to_pty(path.into_bytes());
                    }
                    _ => (),
                }
            },
            Event::Awakened => {
                processor.ctx.terminal.dirty = true;
            }
        }
    }

    /// Process events. When `wait_for_event` is set, this method is guaranteed
    /// to process at least one event.
    pub fn process_events<'a>(
        &mut self,
        term: &'a FairMutex<Term>,
        window: &mut Window
    ) -> MutexGuard<'a, Term> {
        // Terminal is lazily initialized the first time an event is returned
        // from the blocking WaitEventsIterator. Otherwise, the pty reader would
        // be blocked the entire time we wait for input!
        let mut terminal;

        self.pending_events.clear();

        {
            // Ditto on lazy initialization for context and processor.
            let context;
            let mut processor: input::Processor<ActionContext<N>>;

            let print_events = self.print_events;

            let ref_test = self.ref_test;
            let resize_tx = &self.resize_tx;

            if self.wait_for_event {
                // A Vec is used here since wait_events can potentially yield
                // multiple events before the interrupt is handled. For example,
                // Resize and Moved events.
                let pending_events = &mut self.pending_events;
                window.wait_events(|e| {
                    pending_events.push(e);
                    glutin::ControlFlow::Break
                });
            }

            terminal = term.lock();

            context = ActionContext {
                terminal: &mut terminal,
                notifier: &mut self.notifier,
                selection: &mut self.selection,
                mouse: &mut self.mouse,
                size_info: &self.size_info,
                selection_modified: false,
                received_count: &mut self.received_count,
                suppress_chars: &mut self.suppress_chars,
                last_modifiers: &mut self.last_modifiers,
            };

            processor = input::Processor {
                ctx: context,
                mouse_config: &self.mouse_config,
                key_bindings: &self.key_bindings[..],
                mouse_bindings: &self.mouse_bindings[..],
            };

            let mut window_is_focused = window.is_focused;

            // Scope needed to that hide_cursor isn't borrowed after the scope
            // ends.
            {
                let hide_cursor = &mut self.hide_cursor;
                let mut process = |event| {
                    if print_events {
                        println!("glutin event: {:?}", event);
                    }
                    Processor::handle_event(
                        &mut processor,
                        event,
                        ref_test,
                        resize_tx,
                        hide_cursor,
                        &mut window_is_focused,
                    );
                };

                for event in self.pending_events.drain(..) {
                    process(event);
                }

                window.poll_events(process);
            }

            if self.hide_cursor_when_typing {
                window.set_cursor_visible(!self.hide_cursor);
            }

            window.is_focused = window_is_focused;

            if processor.ctx.selection_modified {
                processor.ctx.terminal.dirty = true;
            }
        }

        self.wait_for_event = !terminal.dirty;

        terminal
    }

    pub fn update_config(&mut self, config: &Config) {
        self.key_bindings = config.key_bindings().to_vec();
        self.mouse_bindings = config.mouse_bindings().to_vec();
        self.mouse_config = config.mouse().to_owned();
    }
}
<|endoftext|>


<commit_before>
use gfx;
use gfx::DeviceHelper;
use graphics::{
    BackEnd,
};

use Texture;

static VERTEX_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec3 color;
varying vec4 v_Color;
void main() {
    v_Color = vec4(color, 1.0);
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec3 color;
out vec4 v_Color;
void main() {
    v_Color = vec4(color, 1.0);
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
varying vec4 v_Color;
void main() {
    gl_FragColor = v_Color;
}
"
    GLSL_150: b"
#version 150 core
in vec4 v_Color;
out vec4 o_Color;
void main() {
    o_Color = v_Color;
}
"
};

static VERTEX_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec3 color;
attribute vec2 uv;
uniform sampler2D s_texture;
varying vec4 v_Color;
varying vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = a_v4Position;
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec3 color;
in vec2 uv;
uniform sampler2D s_texture;
out vec4 v_Color;
out vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = a_v4Position;
}
"
};

static FRAGMENT_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
uniform sampler2D s_texture;
varying vec2 v_UV;
varying vec4 v_Color;
void main()
{
    gl_FragColor = texture(s_texture, v_UV) * v_Color;
}
"
    GLSL_150: b"
#version 150 core
out vec4 o_Color;
uniform sampler2D s_texture;
in vec2 v_UV;
in vec4 v_Color;
void main()
{
    o_Color = texture(s_texture, v_UV) * v_Color;
}
"
};

#[vertex_format]
struct Vertex {
    pos: [f32, ..2],
    color: [f32, ..4],
}

impl Vertex {
    fn new(pos: [f32, ..2], color: [f32, ..4], uv: [f32, ..2]) -> Vertex {
        Vertex {
            pos: pos,
            color: color,
        }
    }
}

#[vertex_format]
struct VertexUV {
    pos: [f32, ..2],
    color: [f32, ..4],
    uv: [f32, ..2],
}

impl VertexUV {
    fn new(pos: [f32, ..2], color: [f32, ..4], uv: [f32, ..2]) -> VertexUV {
        VertexUV {
            pos: pos,
            color: color,
            uv: uv,
        }
    }
}

/// The graphics back-end.
pub struct Gfx2d {
    state: gfx::DrawState,
    program: gfx::shade::EmptyProgram,
    program_uv: gfx::shade::EmptyProgram,
}

impl Gfx2d {
    /// Creates a new Gfx2d object.
    pub fn new<D: gfx::Device>(device: &mut D) -> Gfx2d {
        Gfx2d {
            state: gfx::DrawState::new(),
            program: device.link_program(
                    VERTEX_SHADER.clone(),
                    FRAGMENT_SHADER.clone()
                ).unwrap(),
            program_uv: device.link_program(
                    VERTEX_SHADER_UV.clone(),
                    FRAGMENT_SHADER_UV.clone()
                ).unwrap()
        }
    }
}

impl BackEnd<Texture> for Gfx2d {

}
<commit_msg>Added vertex buffers<commit_after>
use gfx;
use gfx::DeviceHelper;
use graphics::{
    BackEnd,
};

use Texture;

static BUFFER_SIZE: uint = 1024;

static VERTEX_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec3 color;
varying vec4 v_Color;
void main() {
    v_Color = vec4(color, 1.0);
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec3 color;
out vec4 v_Color;
void main() {
    v_Color = vec4(color, 1.0);
    gl_Position = vec4(pos, 0.0, 1.0);
}
"
};

static FRAGMENT_SHADER: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
varying vec4 v_Color;
void main() {
    gl_FragColor = v_Color;
}
"
    GLSL_150: b"
#version 150 core
in vec4 v_Color;
out vec4 o_Color;
void main() {
    o_Color = v_Color;
}
"
};

static VERTEX_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
attribute vec2 pos;
attribute vec3 color;
attribute vec2 uv;
uniform sampler2D s_texture;
varying vec4 v_Color;
varying vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = a_v4Position;
}
"
    GLSL_150: b"
#version 150 core
in vec2 pos;
in vec3 color;
in vec2 uv;
uniform sampler2D s_texture;
out vec4 v_Color;
out vec2 v_UV;
void main() {
    v_UV = uv;
    v_Color = color;
    gl_Position = a_v4Position;
}
"
};

static FRAGMENT_SHADER_UV: gfx::ShaderSource = shaders!{
    GLSL_120: b"
#version 120
uniform sampler2D s_texture;
varying vec2 v_UV;
varying vec4 v_Color;
void main()
{
    gl_FragColor = texture(s_texture, v_UV) * v_Color;
}
"
    GLSL_150: b"
#version 150 core
out vec4 o_Color;
uniform sampler2D s_texture;
in vec2 v_UV;
in vec4 v_Color;
void main()
{
    o_Color = texture(s_texture, v_UV) * v_Color;
}
"
};

#[vertex_format]
struct Vertex {
    pos: [f32, ..2],
    color: [f32, ..4],
}

impl Vertex {
    fn new(pos: [f32, ..2], color: [f32, ..4], uv: [f32, ..2]) -> Vertex {
        Vertex {
            pos: pos,
            color: color,
        }
    }
}

#[vertex_format]
struct VertexUV {
    pos: [f32, ..2],
    color: [f32, ..4],
    uv: [f32, ..2],
}

impl VertexUV {
    fn new(pos: [f32, ..2], color: [f32, ..4], uv: [f32, ..2]) -> VertexUV {
        VertexUV {
            pos: pos,
            color: color,
            uv: uv,
        }
    }
}

/// The graphics back-end.
pub struct Gfx2d {
    state: gfx::DrawState,
    program: gfx::shade::EmptyProgram,
    program_uv: gfx::shade::EmptyProgram,
    vertex_data: Vec<Vertex>,
    vertex_data_uv: Vec<VertexUV>,
}

impl Gfx2d {
    /// Creates a new Gfx2d object.
    pub fn new<D: gfx::Device>(device: &mut D) -> Gfx2d {
        Gfx2d {
            state: gfx::DrawState::new(),
            program: device.link_program(
                    VERTEX_SHADER.clone(),
                    FRAGMENT_SHADER.clone()
                ).unwrap(),
            program_uv: device.link_program(
                    VERTEX_SHADER_UV.clone(),
                    FRAGMENT_SHADER_UV.clone()
                ).unwrap(),
            vertex_data: Vec::with_capacity(BUFFER_SIZE),
            vertex_data_uv: Vec::with_capacity(BUFFER_SIZE)
        }
    }
}

impl BackEnd<Texture> for Gfx2d {

}
<|endoftext|>


<commit_before>//! Provides a way to link `AudioDevice`s into an acyclic graph.

use std::collections::VecDeque;

use types::{AudioDevice, Sample, Time};
pub use tick::Tick;

pub struct DeviceGraph {
    nodes: Vec<AudioNode>, // the actual nodes
    topology: Vec<usize>, // the order to tick the nodes
    bus: Vec<Sample>, // the audio bus to write samples to
    time: Time // the next timestep
}

impl DeviceGraph {
    pub fn new() -> DeviceGraph {
        DeviceGraph {
            nodes: Vec::new(),
            topology: Vec::new(),
            bus: Vec::new(),
            time: 0
        }
    }

    pub fn add_node<D>(&mut self, device: D) -> AudioNodeIdx
            where D: 'static+AudioDevice {
        let node = AudioNode::new(device, &mut self.bus);
        let idx = self.nodes.len();
        self.nodes.push(node);
        self.topology.push(idx);
        AudioNodeIdx(idx)
    }

    pub fn add_edge(&mut self, from: AudioNodeIdx, from_ch: usize,
                    to: AudioNodeIdx, to_ch: usize) -> Result<(), GraphError> {
        // Check device indices
        let AudioNodeIdx(from_i) = from;
        let AudioNodeIdx(to_i) = to;
        if from_i >= self.nodes.len() {
            return Err(GraphError::FromOutOfRange);
        } else if to_i >= self.nodes.len() {
            return Err(GraphError::ToOutOfRange);
        }

        // Check channels
        if self.nodes[from_i].device.num_outputs() <= from_ch {
            return Err(GraphError::FromChOutOfRange);
        }
        if self.nodes[to_i].device.num_inputs() <= to_ch {
            return Err(GraphError::ToChOutOfRange);
        }
        while self.nodes[to_i].inputs.len() < to_ch {
            self.nodes[to_i].inputs.push(None);
        }

        // Set input
        let (start,_) = self.nodes[from_i].outputs;
        self.nodes[to_i].inputs[to_ch] = Some(start+from_ch);
        self.topological_sort(to_i, to_ch)
    }

    /// Determines the topology of our device graph. If the graph has a cycle,
    /// then we remove the last edge. Otherwise, we set self.topology to
    /// a topologically sorted order.
    fn topological_sort(&mut self, to_i: usize, to_ch: usize) ->
            Result<(), GraphError> {
        // Intialize our set of input edges, and our set of edgeless nodes
        let mut topology = Vec::new();
        let mut inputs: Vec<Vec<_>> = self.nodes.iter().map(
            |node| node.inputs.iter().filter_map(|&o| o).collect()
        ).collect();
        let mut no_inputs: VecDeque<_> = inputs.iter().enumerate().filter_map(
            |(i, ins)| if ins.len() == 0 { Some(i) } else { None }
        ).collect();

        // While there are nodes with no input, we choose one, add it as the
        // next node in our topology, and remove all edges from that node. Any
        // nodes that lose their final edge are added to the edgeless set.
        loop {
            match no_inputs.pop_front() {
                Some(i) => {
                    topology.push(i);
                    let (out_start, out_end) = self.nodes[i].outputs;
                    for out in out_start..out_end {
                        for (j, ins) in inputs.iter_mut().enumerate() {
                            let mut idx = None;
                            for k in 0..ins.len() {
                                if ins[k] == out {
                                    idx = Some(k);
                                    break;
                                }
                            }
                            match idx {
                                Some(k) => {
                                    ins.swap_remove(k);
                                    if ins.len() == 0 {
                                        no_inputs.push_back(j);
                                    }
                                },
                                None => ()
                            }
                        }
                    }
                },
                None => break
            }
        }

        if topology.len() == self.nodes.len() {
            self.topology = topology;
            Ok(())
        } else {
            self.nodes[to_i].inputs[to_ch] = None;
            Err(GraphError::CreatesCycle)
        }
    }
}

impl Tick for DeviceGraph {
    fn tick(&mut self) {
        for &i in self.topology.iter() {
            self.nodes[i].tick(self.time, &mut self.bus);
        }
        self.time += 1;
    }
}

#[derive(Copy, Clone, Debug)]
pub enum GraphError {
    FromOutOfRange, FromChOutOfRange, ToOutOfRange, ToChOutOfRange, CreatesCycle
}

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

struct AudioNode {
    device: Box<AudioDevice>,
    inputs: Vec<Option<usize>>,
    input_buf: Vec<Sample>,
    outputs: (usize, usize)
}

impl AudioNode {
    fn new<D>(device: D, bus: &mut Vec<Sample>) -> AudioNode
            where D: 'static+AudioDevice {
        let num_in = device.num_inputs();
        let num_out = device.num_outputs();
        let start = bus.len();
        for _ in 0..num_out {
            bus.push(0.0);
        }
        let end = bus.len();

        AudioNode {
            device: Box::new(device),
            inputs: vec![None; num_in],
            input_buf: vec![0.0; num_in],
            outputs: (start, end)
        }
    }

    fn tick(&mut self, t: Time, bus: &mut[Sample]) {
        for (i, ch) in self.inputs.iter().enumerate() {
            self.input_buf[i] = ch.map_or(0.0, |j| bus[j]);
        }
        let (start, end) = self.outputs;
        self.device.tick(t, &self.input_buf, &mut bus[start..end]);
    }
}
<commit_msg>Clearer variable names in graph<commit_after>//! Provides a way to link `AudioDevice`s into an acyclic graph.

use std::collections::VecDeque;

use types::{AudioDevice, Sample, Time};
pub use tick::Tick;

pub struct DeviceGraph {
    nodes: Vec<AudioNode>, // the actual nodes
    topology: Vec<usize>, // the order to tick the nodes
    bus: Vec<Sample>, // the audio bus to write samples to
    time: Time // the next timestep
}

impl DeviceGraph {
    pub fn new() -> DeviceGraph {
        DeviceGraph {
            nodes: Vec::new(),
            topology: Vec::new(),
            bus: Vec::new(),
            time: 0
        }
    }

    pub fn add_node<D>(&mut self, device: D) -> AudioNodeIdx
            where D: 'static+AudioDevice {
        let node = AudioNode::new(device, &mut self.bus);
        let idx = self.nodes.len();
        self.nodes.push(node);
        self.topology.push(idx);
        AudioNodeIdx(idx)
    }

    /// Connect two devices in the graph.
    ///
    /// `src` and `dest` are identifiers for the actual devices to connect.
    ///
    /// `src_ch` and `dest_ch` are the channel indices of the two devices.
    ///
    /// If invalid indices are provided, or if the specified edge would create
    /// a cycle in the graph, an Err is returned and no changes dest the graph are
    /// made.
    pub fn add_edge(&mut self, src: AudioNodeIdx, src_ch: usize,
                    dest: AudioNodeIdx, dest_ch: usize) -> Result<(), GraphError> {
        // Check device indices
        let AudioNodeIdx(src_i) = src;
        let AudioNodeIdx(dest_i) = dest;
        if src_i >= self.nodes.len() {
            return Err(GraphError::SrcOutOfRange);
        } else if dest_i >= self.nodes.len() {
            return Err(GraphError::DestOutOfRange);
        }

        // Check channels
        if self.nodes[src_i].device.num_outputs() <= src_ch {
            return Err(GraphError::SrcChOutOfRange);
        }
        if self.nodes[dest_i].device.num_inputs() <= dest_ch {
            return Err(GraphError::DestChOutOfRange);
        }
        while self.nodes[dest_i].inputs.len() < dest_ch {
            self.nodes[dest_i].inputs.push(None);
        }

        // Set input
        let (start,_) = self.nodes[src_i].outputs;
        self.nodes[dest_i].inputs[dest_ch] = Some(start+src_ch);
        self.topological_sort(dest_i, dest_ch)
    }

    /// Determines the topology of our device graph. If the graph has a cycle,
    /// then we remove the last edge. Otherwise, we set self.topology to
    /// a topologically sorted order.
    fn topological_sort(&mut self, dest_i: usize, dest_ch: usize) ->
            Result<(), GraphError> {
        // Intialize our set of input edges, and our set of edgeless nodes
        let mut topology = Vec::new();
        let mut inputs: Vec<Vec<_>> = self.nodes.iter().map(
            |node| node.inputs.iter().filter_map(|&o| o).collect()
        ).collect();
        let mut no_inputs: VecDeque<_> = inputs.iter().enumerate().filter_map(
            |(i, ins)| if ins.len() == 0 { Some(i) } else { None }
        ).collect();

        // While there are nodes with no input, we choose one, add it as the
        // next node in our topology, and remove all edges from that node. Any
        // nodes that lose their final edge are added to the edgeless set.
        loop {
            match no_inputs.pop_front() {
                Some(i) => {
                    topology.push(i);
                    let (out_start, out_end) = self.nodes[i].outputs;
                    for out in out_start..out_end {
                        for (j, ins) in inputs.iter_mut().enumerate() {
                            let mut idx = None;
                            for k in 0..ins.len() {
                                if ins[k] == out {
                                    idx = Some(k);
                                    break;
                                }
                            }
                            match idx {
                                Some(k) => {
                                    ins.swap_remove(k);
                                    if ins.len() == 0 {
                                        no_inputs.push_back(j);
                                    }
                                },
                                None => ()
                            }
                        }
                    }
                },
                None => break
            }
        }

        if topology.len() == self.nodes.len() {
            self.topology = topology;
            Ok(())
        } else {
            self.nodes[to_i].inputs[to_ch] = None;
            Err(GraphError::CreatesCycle)
        }
    }
}

impl Tick for DeviceGraph {
    fn tick(&mut self) {
        for &i in self.topology.iter() {
            self.nodes[i].tick(self.time, &mut self.bus);
        }
        self.time += 1;
    }
}

#[derive(Copy, Clone, Debug)]
pub enum GraphError {
    FromOutOfRange, FromChOutOfRange, ToOutOfRange, ToChOutOfRange, CreatesCycle
}

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

struct AudioNode {
    device: Box<AudioDevice>,
    inputs: Vec<Option<usize>>,
    input_buf: Vec<Sample>,
    outputs: (usize, usize)
}

impl AudioNode {
    fn new<D>(device: D, bus: &mut Vec<Sample>) -> AudioNode
            where D: 'static+AudioDevice {
        let num_in = device.num_inputs();
        let num_out = device.num_outputs();
        let start = bus.len();
        for _ in 0..num_out {
            bus.push(0.0);
        }
        let end = bus.len();

        AudioNode {
            device: Box::new(device),
            inputs: vec![None; num_in],
            input_buf: vec![0.0; num_in],
            outputs: (start, end)
        }
    }

    fn tick(&mut self, t: Time, bus: &mut[Sample]) {
        for (i, ch) in self.inputs.iter().enumerate() {
            self.input_buf[i] = ch.map_or(0.0, |j| bus[j]);
        }
        let (start, end) = self.outputs;
        self.device.tick(t, &self.input_buf, &mut bus[start..end]);
    }
}
<|endoftext|>


<commit_before>/*
src/input.rs, 2017-07-28

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

use sdl2::keyboard::Keycode;

pub struct InputKeyboard {
    up: bool,
    down: bool,
    left: bool,
    right: bool,
    shoot: bool,

    keyhit_up: bool,
    keyhit_down: bool,
    keyhit_left: bool,
    keyhit_right: bool,
    keyhit_enter: bool,
    keyhit_back: bool,
}

impl InputKeyboard {
    pub fn new() -> InputKeyboard {
        InputKeyboard {
            up: false,
            down: false,
            left: false,
            right: false,
            shoot: false,

            keyhit_up: false,
            keyhit_down: false,
            keyhit_left: false,
            keyhit_right: false,
            keyhit_enter: false,
            keyhit_back: false,
        }
    }

    pub fn reset_keyhits(&mut self) {
        let value = false;
        self.keyhit_up = value;
        self.keyhit_down = value;
        self.keyhit_left = value;
        self.keyhit_right = value;
        self.keyhit_enter = value;
        self.keyhit_back = value;
    }

    pub fn update_key_up(&mut self, key: Keycode) {
        self.update_keys(key, false);
        self.update_keyhit(key, true);
    }

    pub fn update_key_down(&mut self, key: Keycode) {
        self.update_keys(key, true);
        self.update_keyhit(key, false);
    }

    fn update_keys(&mut self, key: Keycode, value: bool) {
        match key {
            Keycode::Up     => self.up = value,
            Keycode::Down   => self.down = value,
            Keycode::Left   => self.left = value,
            Keycode::Right  => self.right = value,
            Keycode::Space  => self.shoot = value,
            _ => (),
        }
    }

    fn update_keyhit(&mut self, key: Keycode, value: bool) {
        match key {
            Keycode::Up         => self.keyhit_up = value,
            Keycode::Down       => self.keyhit_down = value,
            Keycode::Left       => self.keyhit_left = value,
            Keycode::Right      => self.keyhit_right = value,
            Keycode::Return     => self.keyhit_enter = value,
            Keycode::Backspace  => self.keyhit_back = value,
            _ => (),
        }
    }
}

fn return_and_reset(value: &mut bool) -> bool {
    let original_value: bool = *value;
    *value = false;
    original_value
}

pub trait Input {
    fn up(&self) -> bool;
    fn down(&self) -> bool;
    fn left(&self) -> bool;
    fn right(&self) -> bool;
    fn shoot(&self) -> bool;

    fn keyhit_up(&mut self) -> bool;
    fn keyhit_down(&mut self) -> bool;
    fn keyhit_left(&mut self) -> bool;
    fn keyhit_right(&mut self) -> bool;
    fn keyhit_enter(&mut self) -> bool;
    fn keyhit_back(&mut self) -> bool;
}

impl Input for InputKeyboard {
    fn up(&self) -> bool    { self.up    }
    fn down(&self) -> bool  { self.down  }
    fn left(&self) -> bool  { self.left  }
    fn right(&self) -> bool { self.right }
    fn shoot(&self) -> bool { self.shoot }

    fn keyhit_up(&mut self) -> bool     { return_and_reset(&mut self.keyhit_up)    }
    fn keyhit_down(&mut self) -> bool   { return_and_reset(&mut self.keyhit_down)  }
    fn keyhit_left(&mut self) -> bool   { return_and_reset(&mut self.keyhit_left)  }
    fn keyhit_right(&mut self) -> bool  { return_and_reset(&mut self.keyhit_right) }
    fn keyhit_enter(&mut self) -> bool  { return_and_reset(&mut self.keyhit_enter) }
    fn keyhit_back(&mut self) -> bool   { return_and_reset(&mut self.keyhit_back) }
}<commit_msg>up and down keys make multiple key hits when they are kept down<commit_after>/*
src/input.rs, 2017-07-29

Copyright (c) 2017 Juuso Tuononen

This file is licensed under

Apache License, Version 2.0

or

MIT License
*/

use sdl2::keyboard::Keycode;

use Timer;
use time::PreciseTime;

pub struct InputKeyboard {
    up: bool,
    down: bool,
    left: bool,
    right: bool,
    shoot: bool,

    keyhit_left: bool,
    keyhit_right: bool,
    keyhit_enter: bool,
    keyhit_back: bool,

    keyhit_up_timer: KeyhitTimer,
    keyhit_down_timer: KeyhitTimer,
}

impl InputKeyboard {
    pub fn new() -> InputKeyboard {
        InputKeyboard {
            up: false,
            down: false,
            left: false,
            right: false,
            shoot: false,

            keyhit_left: false,
            keyhit_right: false,
            keyhit_enter: false,
            keyhit_back: false,

            keyhit_up_timer: KeyhitTimer::new(Keycode::Up),
            keyhit_down_timer: KeyhitTimer::new(Keycode::Down),
        }
    }

    pub fn reset_keyhits(&mut self) {
        let value = false;
        self.keyhit_left = value;
        self.keyhit_right = value;
        self.keyhit_enter = value;
        self.keyhit_back = value;

        self.keyhit_up_timer.reset();
        self.keyhit_down_timer.reset();
    }

    pub fn update_key_up(&mut self, key: Keycode) {
        self.update_keys(key, false);
        self.update_keyhit(key, true);

        self.keyhit_up_timer.event_key_up(key);
        self.keyhit_down_timer.event_key_up(key);
    }

    pub fn update_key_down(&mut self, key: Keycode) {
        self.update_keys(key, true);

        let current_time = PreciseTime::now();
        self.keyhit_up_timer.event_key_down(key, current_time);
        self.keyhit_down_timer.event_key_down(key, current_time);
    }

    fn update_keys(&mut self, key: Keycode, value: bool) {
        match key {
            Keycode::Up     => self.up = value,
            Keycode::Down   => self.down = value,
            Keycode::Left   => self.left = value,
            Keycode::Right  => self.right = value,
            Keycode::Space  => self.shoot = value,
            _ => (),
        }
    }

    fn update_keyhit(&mut self, key: Keycode, value: bool) {
        match key {
            Keycode::Left       => self.keyhit_left = value,
            Keycode::Right      => self.keyhit_right = value,
            Keycode::Return     => self.keyhit_enter = value,
            Keycode::Backspace  => self.keyhit_back = value,
            _ => (),
        }
    }
}

fn return_and_reset(value: &mut bool) -> bool {
    let original_value: bool = *value;
    *value = false;
    original_value
}

pub trait Input {
    fn up(&self) -> bool;
    fn down(&self) -> bool;
    fn left(&self) -> bool;
    fn right(&self) -> bool;
    fn shoot(&self) -> bool;

    fn keyhit_up(&mut self) -> bool;
    fn keyhit_down(&mut self) -> bool;
    fn keyhit_left(&mut self) -> bool;
    fn keyhit_right(&mut self) -> bool;
    fn keyhit_enter(&mut self) -> bool;
    fn keyhit_back(&mut self) -> bool;
}

impl Input for InputKeyboard {
    fn up(&self) -> bool    { self.up    }
    fn down(&self) -> bool  { self.down  }
    fn left(&self) -> bool  { self.left  }
    fn right(&self) -> bool { self.right }
    fn shoot(&self) -> bool { self.shoot }

    fn keyhit_up(&mut self) -> bool     { self.keyhit_up_timer.return_and_reset()    }
    fn keyhit_down(&mut self) -> bool   { self.keyhit_down_timer.return_and_reset()  }
    fn keyhit_left(&mut self) -> bool   { return_and_reset(&mut self.keyhit_left)  }
    fn keyhit_right(&mut self) -> bool  { return_and_reset(&mut self.keyhit_right) }
    fn keyhit_enter(&mut self) -> bool  { return_and_reset(&mut self.keyhit_enter) }
    fn keyhit_back(&mut self) -> bool   { return_and_reset(&mut self.keyhit_back) }
}

enum KeyhitState {
    NormalMode,
    ScrollMode,
}

struct KeyhitTimer {
    timer: Timer,
    state: Option<KeyhitState>,
    key: Keycode,
    keyhit: bool,
}

impl KeyhitTimer {
    fn new(key: Keycode) -> KeyhitTimer {
        KeyhitTimer {
            timer: Timer::new(),
            state: None,
            key: key,
            keyhit: false,
        }
    }

    fn event_key_down(&mut self, key: Keycode, current_time: PreciseTime) {
        if self.key != key {
            return;
        }

        match self.state {
            None => {
                self.state = Some(KeyhitState::NormalMode);
                self.timer.reset(current_time);
            },
            Some(KeyhitState::NormalMode) => {
                if self.timer.check(current_time, 400) {
                    self.state = Some(KeyhitState::ScrollMode);
                    self.keyhit = true;
                }
            },
            Some(KeyhitState::ScrollMode) => {
                if self.timer.check(current_time, 400) {
                    self.keyhit = true;
                }
            }
        }
    }

    fn event_key_up(&mut self, key: Keycode) {
        if self.key != key {
            return;
        }

        match self.state {
            Some(KeyhitState::NormalMode) => {
                self.keyhit = true;
            },
            _ => {
                self.keyhit = false;
                self.state = None;
            },
        }
    }

    fn return_and_reset(&mut self) -> bool {
        if self.keyhit {
            self.keyhit = false;
            true
        } else {
            false
        }
    }

    fn reset(&mut self) {
        self.keyhit = false;
    }
}<|endoftext|>


<commit_before>//! Some item definitions used in instances to provide a virtual representative
//! structure of `.cnf` or `.sat` files and their associated clauses or formula.

/// Represents a variable within a SAT instance.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Var(pub u64);

impl Var {
	/// Converts a variable into its representative `u64` value.
	pub fn to_u64(self) -> u64 { self.0 }
}

/// Represents the sign of a literal.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Sign {
	/// Positive sign.
	Pos,

	/// Negative sign.
	Neg
}

/// Represents a literal within clauses of formulas of a SAT instance.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Lit(i64);

impl Lit {
	/// Returns the underlying `i64` representant of this literal.
	pub fn from_i64(val: i64) -> Lit { Lit(val) }

	/// Returns the associated variable for this literal.
	pub fn var(self) -> Var { Var(self.0.abs() as u64) }

	/// Returns the sign of this literal.
	pub fn sign(self) -> Sign {
		match self.0 >= 0 {
			true => Sign::Pos,
			_    => Sign::Neg
		}
	}
}

/// Represents a clause instance within a `.cnf` file.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Clause {
	lits: Box<[Lit]>
}

impl Clause {
	/// Creates a new clause from a vector of literals.
	pub fn from_vec(lits: Vec<Lit>) -> Clause {
		Clause{
			lits: lits.into_boxed_slice()
		}
	}

	/// Returns the number of literals of this clause.
	pub fn len(&self) -> usize {
		self.lits.len()
	}

	/// Returns a slice over the literals of this clause.
	pub fn lits(&self) -> &[Lit] {
		&self.lits
	}
}

/// An indirection to a `Formula` via `Box`.
pub type FormulaBox  = Box<Formula>;

/// An immutable list of `Formula`s.
pub type FormulaList = Box<[Formula]>;

/// Represents the structure of formulas of `.sat` files.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Formula {
	/// A single literal. This is the leaf node type of sat formulas.
	Lit(Lit),

	/// Represents `(f)` if `f` is a valid formula.
	Paren(FormulaBox),

	/// Represents `-(f)` if `f` is a valid formula.
	/// This negates the result of the inner `f`.
	Neg(FormulaBox),

	/// Represents `*(f_1 .. f_k)` if `f_1, .., f_k` are valid formulas.
	/// The effect is a logical and of its inner formulas.
	And(FormulaList),

	/// Represents `+(f_1 .. f_k)` if `f_1, .., f_k` are valid formulas.
	/// The effect is a logical or of its inner formulas.
	Or(FormulaList),

	/// Represents `xor(f_1 .. f_k)` if `f_1, .., f_k` are valid formulas.
	/// The effect is a logical xor of its inner formulas.
	Xor(FormulaList),

	/// Represents `=(f_1 .. f_k)` if `f_1, .., f_k` are valid formulas.
	/// The effect is a logical equals of its inner formulas.
	Eq(FormulaList)
}

impl Formula {
	/// Creates a new literal leaf formula with the given literal.
	pub fn lit(lit: Lit) -> Formula {
		Formula::Lit(lit)
	}

	/// Wraps the inner formula within parentheses.
	pub fn paren(inner: Formula) -> Formula {
		Formula::Paren(Box::new(inner))
	}

	/// Negates the inner formula.
	pub fn neg(inner: Formula) -> Formula {
		Formula::Neg(Box::new(inner))
	}

	/// Creates a logical and formula of all given formulas in `param`.
	pub fn and(params: Vec<Formula>) -> Formula {
		Formula::And(params.into_boxed_slice())
	}

	/// Creates a logical or formula of all given formulas in `param`.
	pub fn or(params: Vec<Formula>) -> Formula {
		Formula::Or(params.into_boxed_slice())
	}

	/// Creates a logical xor formula of all given formulas in `param`.
	pub fn xor(params: Vec<Formula>) -> Formula {
		Formula::Xor(params.into_boxed_slice())
	}

	/// Creates a logical equality formula of all given formulas in `param`.
	pub fn eq(params: Vec<Formula>) -> Formula {
		Formula::Eq(params.into_boxed_slice())
	}
}

/// Represents a SAT instance for `.cnf` or `.sat` files.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Instance {
	/// A `.cnf` SAT instance with clauses.
	Cnf{
		/// The number of unique variables used within this `.cnf` SAT instance.
		num_vars: u64,

		/// The clauses within this `.cnf` SAT instance formula.
		clauses: Box<[Clause]>
	},

	/// A `.sat` SAT instance with an underlying formula and extensions.
	Sat{
		/// The number of unique variables used within this `.sat` SAT instance.
		num_vars: u64,

		/// Extensions (e.g. `XOR` or `EQ`) being used in this SAT instance.
		extensions: Extensions,

		/// The underlying formula of this SAT instance.
		formula: Formula
	}
}

impl Instance {
	/// Creates a new SAT instance for `.cnf` files with given clauses.
	pub fn cnf(num_vars: u64, clauses: Vec<Clause>) -> Instance {
		Instance::Cnf{num_vars: num_vars, clauses: clauses.into_boxed_slice()}
	}

	/// Creates a new SAT instance for `.sat` files with given extensions and an underlying formula.
	pub fn sat(num_vars: u64, extensions: Extensions, formula: Formula) -> Instance {
		Instance::Sat{num_vars: num_vars, extensions: extensions, formula: formula}
	}
}

bitflags! {
	/// Possible extensions for `.sat` file SAT instances.
    pub flags Extensions: u32 {
    	/// If no extensions are being used.
    	const NONE = 0b00000000,
    	/// If the XOR-Extension is being used to allow for `xor(..)` formulas.
        const XOR  = 0b00000001,
        /// If the EQ-Extension is being used to allow for `=(..)` formulas.
        const EQ   = 0b00000010
    }
}
<commit_msg>Add Lit::to_i64 method<commit_after>//! Some item definitions used in instances to provide a virtual representative
//! structure of `.cnf` or `.sat` files and their associated clauses or formula.

/// Represents a variable within a SAT instance.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Var(pub u64);

impl Var {
	/// Converts a variable into its representative `u64` value.
	pub fn to_u64(self) -> u64 { self.0 }
}

/// Represents the sign of a literal.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Sign {
	/// Positive sign.
	Pos,

	/// Negative sign.
	Neg
}

/// Represents a literal within clauses of formulas of a SAT instance.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Lit(i64);

impl Lit {
	/// Returns the underlying `i64` representant of this literal.
	pub fn from_i64(val: i64) -> Lit { Lit(val) }

	/// Returns the associated variable for this literal.
	pub fn var(self) -> Var { Var(self.0.abs() as u64) }

	/// Returns the inner `i64` value.
	pub fn to_i64(self) -> i64 { self.0 }

	/// Returns the sign of this literal.
	pub fn sign(self) -> Sign {
		match self.0 >= 0 {
			true => Sign::Pos,
			_    => Sign::Neg
		}
	}
}

/// Represents a clause instance within a `.cnf` file.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Clause {
	lits: Box<[Lit]>
}

impl Clause {
	/// Creates a new clause from a vector of literals.
	pub fn from_vec(lits: Vec<Lit>) -> Clause {
		Clause{
			lits: lits.into_boxed_slice()
		}
	}

	/// Returns the number of literals of this clause.
	pub fn len(&self) -> usize {
		self.lits.len()
	}

	/// Returns a slice over the literals of this clause.
	pub fn lits(&self) -> &[Lit] {
		&self.lits
	}
}

/// An indirection to a `Formula` via `Box`.
pub type FormulaBox  = Box<Formula>;

/// An immutable list of `Formula`s.
pub type FormulaList = Box<[Formula]>;

/// Represents the structure of formulas of `.sat` files.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Formula {
	/// A single literal. This is the leaf node type of sat formulas.
	Lit(Lit),

	/// Represents `(f)` if `f` is a valid formula.
	Paren(FormulaBox),

	/// Represents `-(f)` if `f` is a valid formula.
	/// This negates the result of the inner `f`.
	Neg(FormulaBox),

	/// Represents `*(f_1 .. f_k)` if `f_1, .., f_k` are valid formulas.
	/// The effect is a logical and of its inner formulas.
	And(FormulaList),

	/// Represents `+(f_1 .. f_k)` if `f_1, .., f_k` are valid formulas.
	/// The effect is a logical or of its inner formulas.
	Or(FormulaList),

	/// Represents `xor(f_1 .. f_k)` if `f_1, .., f_k` are valid formulas.
	/// The effect is a logical xor of its inner formulas.
	Xor(FormulaList),

	/// Represents `=(f_1 .. f_k)` if `f_1, .., f_k` are valid formulas.
	/// The effect is a logical equals of its inner formulas.
	Eq(FormulaList)
}

impl Formula {
	/// Creates a new literal leaf formula with the given literal.
	pub fn lit(lit: Lit) -> Formula {
		Formula::Lit(lit)
	}

	/// Wraps the inner formula within parentheses.
	pub fn paren(inner: Formula) -> Formula {
		Formula::Paren(Box::new(inner))
	}

	/// Negates the inner formula.
	pub fn neg(inner: Formula) -> Formula {
		Formula::Neg(Box::new(inner))
	}

	/// Creates a logical and formula of all given formulas in `param`.
	pub fn and(params: Vec<Formula>) -> Formula {
		Formula::And(params.into_boxed_slice())
	}

	/// Creates a logical or formula of all given formulas in `param`.
	pub fn or(params: Vec<Formula>) -> Formula {
		Formula::Or(params.into_boxed_slice())
	}

	/// Creates a logical xor formula of all given formulas in `param`.
	pub fn xor(params: Vec<Formula>) -> Formula {
		Formula::Xor(params.into_boxed_slice())
	}

	/// Creates a logical equality formula of all given formulas in `param`.
	pub fn eq(params: Vec<Formula>) -> Formula {
		Formula::Eq(params.into_boxed_slice())
	}
}

/// Represents a SAT instance for `.cnf` or `.sat` files.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Instance {
	/// A `.cnf` SAT instance with clauses.
	Cnf{
		/// The number of unique variables used within this `.cnf` SAT instance.
		num_vars: u64,

		/// The clauses within this `.cnf` SAT instance formula.
		clauses: Box<[Clause]>
	},

	/// A `.sat` SAT instance with an underlying formula and extensions.
	Sat{
		/// The number of unique variables used within this `.sat` SAT instance.
		num_vars: u64,

		/// Extensions (e.g. `XOR` or `EQ`) being used in this SAT instance.
		extensions: Extensions,

		/// The underlying formula of this SAT instance.
		formula: Formula
	}
}

impl Instance {
	/// Creates a new SAT instance for `.cnf` files with given clauses.
	pub fn cnf(num_vars: u64, clauses: Vec<Clause>) -> Instance {
		Instance::Cnf{num_vars: num_vars, clauses: clauses.into_boxed_slice()}
	}

	/// Creates a new SAT instance for `.sat` files with given extensions and an underlying formula.
	pub fn sat(num_vars: u64, extensions: Extensions, formula: Formula) -> Instance {
		Instance::Sat{num_vars: num_vars, extensions: extensions, formula: formula}
	}
}

bitflags! {
	/// Possible extensions for `.sat` file SAT instances.
    pub flags Extensions: u32 {
    	/// If no extensions are being used.
    	const NONE = 0b00000000,
    	/// If the XOR-Extension is being used to allow for `xor(..)` formulas.
        const XOR  = 0b00000001,
        /// If the EQ-Extension is being used to allow for `=(..)` formulas.
        const EQ   = 0b00000010
    }
}
<|endoftext|>