<commit_before>//! This module defines different errors occurring during communication with MPD.
//!
//! There're following kinds of possible errors:
//!
//!   - IO errors (due to network communication failures),
//!   - parsing errors (because of bugs in parsing server response),
//!   - protocol errors (happen when we get unexpected data from server,
//!     mostly because protocol version mismatch, network data corruption
//!     or just bugs in the client),
//!   - server errors (run-time errors coming from MPD due to some MPD
//!     errors, like database failures or sound problems)
//!
//! This module defines all necessary infrastructure to represent these kinds or errors.

use time::ParseError as TimeParseError;
use std::convert::From;
use std::io::Error as IoError;
use std::error::Error as StdError;
use std::str::FromStr;
use std::fmt;
use std::num::{ParseIntError, ParseFloatError};
use std::result;

// Server errors {{{
/// Server error codes, as defined in [libmpdclient](http://www.musicpd.org/doc/libmpdclient/protocol_8h_source.html)
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, RustcEncodable)]
pub enum ErrorCode {
    /// not a list
    NotList = 1,
    /// bad command arguments
    Argument = 2,
    /// invalid password
    Password = 3,
    /// insufficient permissions
    Permission = 4,
    /// unknown command
    UnknownCmd = 5,
    /// object doesn't exist
    NoExist = 50,
    /// maximum playlist size exceeded
    PlaylistMax = 51,
    /// general system error
    System = 52,
    /// error loading playlist
    PlaylistLoad = 53,
    /// update database is already in progress
    UpdateAlready = 54,
    /// player synchronization error
    PlayerSync = 55,
    /// object already exists
    Exist = 56,
}

impl FromStr for ErrorCode {
    type Err = ParseError;
    fn from_str(s: &str) -> result::Result<ErrorCode, ParseError> {
        use self::ErrorCode::*;
        match try!(s.parse()) {
            1 => Ok(NotList),
            2 => Ok(Argument),
            3 => Ok(Password),
            4 => Ok(Permission),
            5 => Ok(UnknownCmd),

            50 => Ok(NoExist),
            51 => Ok(PlaylistMax),
            52 => Ok(System),
            53 => Ok(PlaylistLoad),
            54 => Ok(UpdateAlready),
            55 => Ok(PlayerSync),
            56 => Ok(Exist),

            v => Err(ParseError::BadErrorCode(v)),
        }
    }
}

impl StdError for ErrorCode {
    fn description(&self) -> &str {
        use self::ErrorCode::*;
        match *self {
            NotList => "not a list",
            Argument => "invalid argument",
            Password => "invalid password",
            Permission => "permission",
            UnknownCmd => "unknown command",

            NoExist => "item not found",
            PlaylistMax => "playlist overflow",
            System => "system",
            PlaylistLoad => "playload load",
            UpdateAlready => "already updating",
            PlayerSync => "player syncing",
            Exist => "already exists",
        }
    }
}

impl fmt::Display for ErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

/// Server error
#[derive(Debug, Clone, PartialEq, RustcEncodable)]
pub struct ServerError {
    /// server error code
    pub code: ErrorCode,
    /// command position in command list
    pub pos: u16,
    /// command name, which caused the error
    pub command: String,
    /// detailed error description
    pub detail: String
}

impl fmt::Display for ServerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} error (`{}') at {}", self.code, self.detail, self.pos)
    }
}

impl StdError for ServerError {
    fn description(&self) -> &str {
        self.code.description()
    }
}

impl FromStr for ServerError {
    type Err = ParseError;
    fn from_str(s: &str) -> result::Result<ServerError, ParseError> {
        // ACK [<code>@<index>] {<command>} <description>
        if s.starts_with("ACK [") {
            let s = &s[5..];
            if let (Some(atsign), Some(right_bracket)) = (s.find('@'), s.find(']')) {
                match (s[..atsign].parse(), s[atsign + 1..right_bracket].parse()) {
                    (Ok(code), Ok(pos)) => {
                        let s = &s[right_bracket + 1..];
                        if let (Some(left_brace), Some(right_brace)) = (s.find('{'), s.find('}')) {
                            let command = s[left_brace + 1..right_brace].to_string();
                            let detail = s[right_brace + 1..].trim().to_string();
                            Ok(ServerError {
                                code: code,
                                pos: pos,
                                command: command,
                                detail: detail
                            })
                        } else {
                            Err(ParseError::NoMessage)
                        }
                    }
                    (Err(_), _) => Err(ParseError::BadCode),
                    (_, Err(_)) => Err(ParseError::BadPos),
                }
            } else {
                Err(ParseError::NoCodePos)
            }
        } else {
            Err(ParseError::NotAck)
        }
    }
}
// }}}

// Error {{{
/// Main error type, describing all possible error classes for the crate
#[derive(Debug)]
pub enum Error {
    /// IO errors (low-level network communication failures)
    Io(IoError),
    /// parsing errors (unknown data came from server)
    Parse(ParseError),
    /// protocol errors (e.g. missing required fields in server response, no handshake message etc.)
    Proto(ProtoError),
    /// server errors (a.k.a. `ACK` responses from server)
    Server(ServerError)
}

/// Shortcut type for MPD results
pub type Result<T> = result::Result<T, Error>;

impl StdError for Error {
    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::Io(ref err) => Some(err),
            Error::Parse(ref err) => Some(err),
            Error::Proto(ref err) => Some(err),
            Error::Server(ref err) => Some(err),
        }
    }
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::Parse(ref err) => err.description(),
            Error::Proto(ref err) => err.description(),
            Error::Server(ref err) => err.description(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref err) => err.fmt(f),
            Error::Parse(ref err) => err.fmt(f),
            Error::Proto(ref err) => err.fmt(f),
            Error::Server(ref err) => err.fmt(f),
        }
    }
}

impl From<IoError> for Error {
    fn from(e: IoError) -> Error { Error::Io(e) }
}
impl From<ParseError> for Error {
    fn from(e: ParseError) -> Error { Error::Parse(e) }
}
impl From<ProtoError> for Error {
    fn from(e: ProtoError) -> Error { Error::Proto(e) }
}
impl From<ParseIntError> for Error {
    fn from(e: ParseIntError) -> Error { Error::Parse(ParseError::BadInteger(e)) }
}
impl From<ParseFloatError> for Error {
    fn from(e: ParseFloatError) -> Error { Error::Parse(ParseError::BadFloat(e)) }
}
impl From<TimeParseError> for Error {
    fn from(e: TimeParseError) -> Error { Error::Parse(ParseError::BadTime(e)) }
}

impl From<ServerError> for Error {
    fn from(e: ServerError) -> Error { Error::Server(e) }
}
// }}}

// Parse errors {{{
/// Parsing error kinds
#[derive(Debug, Clone, PartialEq)]
pub enum ParseError {
    /// invalid integer
    BadInteger(ParseIntError),
    /// invalid float
    BadFloat(ParseFloatError),
    /// some other invalid value
    BadValue(String),
    /// date/time parsing error
    BadTime(TimeParseError),
    /// invalid version format (should be x.y.z)
    BadVersion,
    /// the response is not an `ACK` (not an error)
    /// (this is not actually an error, just a marker
    /// to try to parse the response as some other type,
    /// like a pair)
    NotAck,
    /// invalid pair
    BadPair,
    /// invalid error code in `ACK` response
    BadCode,
    /// invalid command position in `ACK` response
    BadPos,
    /// missing command position and/or error code in `ACK` response
    NoCodePos,
    /// missing error message in `ACK` response
    NoMessage,
    /// missing bitrate in audio format field
    NoRate,
    /// missing bits in audio format field
    NoBits,
    /// missing channels in audio format field
    NoChans,
    /// invalid bitrate in audio format field
    BadRate(ParseIntError),
    /// invalid bits in audio format field
    BadBits(ParseIntError),
    /// invalid channels in audio format field
    BadChans(ParseIntError),
    /// unknown state in state status field
    BadState(String),
    /// unknown error code in `ACK` response
    BadErrorCode(usize)

}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl StdError for ParseError {
    fn description(&self) -> &str {
        use self::ParseError::*;
        match *self {
            BadInteger(_) => "invalid integer",
            BadFloat(_) => "invalid float",
            BadValue(_) => "invalid value",
            BadTime(_) => "invalid date/time",
            BadVersion => "invalid version",
            NotAck => "not an ACK",
            BadPair => "invalid pair",
            BadCode => "invalid code",
            BadPos => "invalid position",
            NoCodePos => "missing code and position",
            NoMessage => "missing position",
            NoRate => "missing audio format rate",
            NoBits => "missing audio format bits",
            NoChans => "missing audio format channels",
            BadRate(_) => "invalid audio format rate",
            BadBits(_) => "invalid audio format bits",
            BadChans(_) => "invalid audio format channels",
            BadState(_) => "invalid playing state",
            BadErrorCode(_) => "unknown error code",
        }
    }
}

impl From<TimeParseError> for ParseError {
    fn from(e: TimeParseError) -> ParseError {
        ParseError::BadTime(e)
    }
}

impl From<ParseIntError> for ParseError {
    fn from(e: ParseIntError) -> ParseError {
        ParseError::BadInteger(e)
    }
}

impl From<ParseFloatError> for ParseError {
    fn from(e: ParseFloatError) -> ParseError {
        ParseError::BadFloat(e)
    }
}
// }}}

// Protocol errors {{{
/// Protocol errors
///
/// They usually occur when server violate expected command response format,
/// like missing fields in answer to some command, missing closing `OK`
/// line after data stream etc.
#[derive(Debug, Clone, PartialEq, RustcEncodable)]
pub enum ProtoError {
    /// `OK` was expected, but it was missing
    NotOk,
    /// a data pair was expected
    NotPair,
    /// invalid handshake banner received
    BadBanner,
    /// expected some field, but it was missing
    NoField(&'static str)
}

impl fmt::Display for ProtoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl StdError for ProtoError {
    fn description(&self) -> &str {
        match *self {
            ProtoError::NotOk => "OK expected",
            ProtoError::NotPair => "pair expected",
            ProtoError::BadBanner => "banner error",
            ProtoError::NoField(_) => "missing field",
        }
    }
}
//}}}

<commit_msg>remove encodable impls from errors<commit_after>//! This module defines different errors occurring during communication with MPD.
//!
//! There're following kinds of possible errors:
//!
//!   - IO errors (due to network communication failures),
//!   - parsing errors (because of bugs in parsing server response),
//!   - protocol errors (happen when we get unexpected data from server,
//!     mostly because protocol version mismatch, network data corruption
//!     or just bugs in the client),
//!   - server errors (run-time errors coming from MPD due to some MPD
//!     errors, like database failures or sound problems)
//!
//! This module defines all necessary infrastructure to represent these kinds or errors.

use time::ParseError as TimeParseError;
use std::convert::From;
use std::io::Error as IoError;
use std::error::Error as StdError;
use std::str::FromStr;
use std::fmt;
use std::num::{ParseIntError, ParseFloatError};
use std::result;

// Server errors {{{
/// Server error codes, as defined in [libmpdclient](http://www.musicpd.org/doc/libmpdclient/protocol_8h_source.html)
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub enum ErrorCode {
    /// not a list
    NotList = 1,
    /// bad command arguments
    Argument = 2,
    /// invalid password
    Password = 3,
    /// insufficient permissions
    Permission = 4,
    /// unknown command
    UnknownCmd = 5,
    /// object doesn't exist
    NoExist = 50,
    /// maximum playlist size exceeded
    PlaylistMax = 51,
    /// general system error
    System = 52,
    /// error loading playlist
    PlaylistLoad = 53,
    /// update database is already in progress
    UpdateAlready = 54,
    /// player synchronization error
    PlayerSync = 55,
    /// object already exists
    Exist = 56,
}

impl FromStr for ErrorCode {
    type Err = ParseError;
    fn from_str(s: &str) -> result::Result<ErrorCode, ParseError> {
        use self::ErrorCode::*;
        match try!(s.parse()) {
            1 => Ok(NotList),
            2 => Ok(Argument),
            3 => Ok(Password),
            4 => Ok(Permission),
            5 => Ok(UnknownCmd),

            50 => Ok(NoExist),
            51 => Ok(PlaylistMax),
            52 => Ok(System),
            53 => Ok(PlaylistLoad),
            54 => Ok(UpdateAlready),
            55 => Ok(PlayerSync),
            56 => Ok(Exist),

            v => Err(ParseError::BadErrorCode(v)),
        }
    }
}

impl StdError for ErrorCode {
    fn description(&self) -> &str {
        use self::ErrorCode::*;
        match *self {
            NotList => "not a list",
            Argument => "invalid argument",
            Password => "invalid password",
            Permission => "permission",
            UnknownCmd => "unknown command",

            NoExist => "item not found",
            PlaylistMax => "playlist overflow",
            System => "system",
            PlaylistLoad => "playload load",
            UpdateAlready => "already updating",
            PlayerSync => "player syncing",
            Exist => "already exists",
        }
    }
}

impl fmt::Display for ErrorCode {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(self.description())
    }
}

/// Server error
#[derive(Debug, Clone, PartialEq)]
pub struct ServerError {
    /// server error code
    pub code: ErrorCode,
    /// command position in command list
    pub pos: u16,
    /// command name, which caused the error
    pub command: String,
    /// detailed error description
    pub detail: String
}

impl fmt::Display for ServerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} error (`{}') at {}", self.code, self.detail, self.pos)
    }
}

impl StdError for ServerError {
    fn description(&self) -> &str {
        self.code.description()
    }
}

impl FromStr for ServerError {
    type Err = ParseError;
    fn from_str(s: &str) -> result::Result<ServerError, ParseError> {
        // ACK [<code>@<index>] {<command>} <description>
        if s.starts_with("ACK [") {
            let s = &s[5..];
            if let (Some(atsign), Some(right_bracket)) = (s.find('@'), s.find(']')) {
                match (s[..atsign].parse(), s[atsign + 1..right_bracket].parse()) {
                    (Ok(code), Ok(pos)) => {
                        let s = &s[right_bracket + 1..];
                        if let (Some(left_brace), Some(right_brace)) = (s.find('{'), s.find('}')) {
                            let command = s[left_brace + 1..right_brace].to_string();
                            let detail = s[right_brace + 1..].trim().to_string();
                            Ok(ServerError {
                                code: code,
                                pos: pos,
                                command: command,
                                detail: detail
                            })
                        } else {
                            Err(ParseError::NoMessage)
                        }
                    }
                    (Err(_), _) => Err(ParseError::BadCode),
                    (_, Err(_)) => Err(ParseError::BadPos),
                }
            } else {
                Err(ParseError::NoCodePos)
            }
        } else {
            Err(ParseError::NotAck)
        }
    }
}
// }}}

// Error {{{
/// Main error type, describing all possible error classes for the crate
#[derive(Debug)]
pub enum Error {
    /// IO errors (low-level network communication failures)
    Io(IoError),
    /// parsing errors (unknown data came from server)
    Parse(ParseError),
    /// protocol errors (e.g. missing required fields in server response, no handshake message etc.)
    Proto(ProtoError),
    /// server errors (a.k.a. `ACK` responses from server)
    Server(ServerError)
}

/// Shortcut type for MPD results
pub type Result<T> = result::Result<T, Error>;

impl StdError for Error {
    fn cause(&self) -> Option<&StdError> {
        match *self {
            Error::Io(ref err) => Some(err),
            Error::Parse(ref err) => Some(err),
            Error::Proto(ref err) => Some(err),
            Error::Server(ref err) => Some(err),
        }
    }
    fn description(&self) -> &str {
        match *self {
            Error::Io(ref err) => err.description(),
            Error::Parse(ref err) => err.description(),
            Error::Proto(ref err) => err.description(),
            Error::Server(ref err) => err.description(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Error::Io(ref err) => err.fmt(f),
            Error::Parse(ref err) => err.fmt(f),
            Error::Proto(ref err) => err.fmt(f),
            Error::Server(ref err) => err.fmt(f),
        }
    }
}

impl From<IoError> for Error {
    fn from(e: IoError) -> Error { Error::Io(e) }
}
impl From<ParseError> for Error {
    fn from(e: ParseError) -> Error { Error::Parse(e) }
}
impl From<ProtoError> for Error {
    fn from(e: ProtoError) -> Error { Error::Proto(e) }
}
impl From<ParseIntError> for Error {
    fn from(e: ParseIntError) -> Error { Error::Parse(ParseError::BadInteger(e)) }
}
impl From<ParseFloatError> for Error {
    fn from(e: ParseFloatError) -> Error { Error::Parse(ParseError::BadFloat(e)) }
}
impl From<TimeParseError> for Error {
    fn from(e: TimeParseError) -> Error { Error::Parse(ParseError::BadTime(e)) }
}

impl From<ServerError> for Error {
    fn from(e: ServerError) -> Error { Error::Server(e) }
}
// }}}

// Parse errors {{{
/// Parsing error kinds
#[derive(Debug, Clone, PartialEq)]
pub enum ParseError {
    /// invalid integer
    BadInteger(ParseIntError),
    /// invalid float
    BadFloat(ParseFloatError),
    /// some other invalid value
    BadValue(String),
    /// date/time parsing error
    BadTime(TimeParseError),
    /// invalid version format (should be x.y.z)
    BadVersion,
    /// the response is not an `ACK` (not an error)
    /// (this is not actually an error, just a marker
    /// to try to parse the response as some other type,
    /// like a pair)
    NotAck,
    /// invalid pair
    BadPair,
    /// invalid error code in `ACK` response
    BadCode,
    /// invalid command position in `ACK` response
    BadPos,
    /// missing command position and/or error code in `ACK` response
    NoCodePos,
    /// missing error message in `ACK` response
    NoMessage,
    /// missing bitrate in audio format field
    NoRate,
    /// missing bits in audio format field
    NoBits,
    /// missing channels in audio format field
    NoChans,
    /// invalid bitrate in audio format field
    BadRate(ParseIntError),
    /// invalid bits in audio format field
    BadBits(ParseIntError),
    /// invalid channels in audio format field
    BadChans(ParseIntError),
    /// unknown state in state status field
    BadState(String),
    /// unknown error code in `ACK` response
    BadErrorCode(usize)

}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl StdError for ParseError {
    fn description(&self) -> &str {
        use self::ParseError::*;
        match *self {
            BadInteger(_) => "invalid integer",
            BadFloat(_) => "invalid float",
            BadValue(_) => "invalid value",
            BadTime(_) => "invalid date/time",
            BadVersion => "invalid version",
            NotAck => "not an ACK",
            BadPair => "invalid pair",
            BadCode => "invalid code",
            BadPos => "invalid position",
            NoCodePos => "missing code and position",
            NoMessage => "missing position",
            NoRate => "missing audio format rate",
            NoBits => "missing audio format bits",
            NoChans => "missing audio format channels",
            BadRate(_) => "invalid audio format rate",
            BadBits(_) => "invalid audio format bits",
            BadChans(_) => "invalid audio format channels",
            BadState(_) => "invalid playing state",
            BadErrorCode(_) => "unknown error code",
        }
    }
}

impl From<TimeParseError> for ParseError {
    fn from(e: TimeParseError) -> ParseError {
        ParseError::BadTime(e)
    }
}

impl From<ParseIntError> for ParseError {
    fn from(e: ParseIntError) -> ParseError {
        ParseError::BadInteger(e)
    }
}

impl From<ParseFloatError> for ParseError {
    fn from(e: ParseFloatError) -> ParseError {
        ParseError::BadFloat(e)
    }
}
// }}}

// Protocol errors {{{
/// Protocol errors
///
/// They usually occur when server violate expected command response format,
/// like missing fields in answer to some command, missing closing `OK`
/// line after data stream etc.
#[derive(Debug, Clone, PartialEq)]
pub enum ProtoError {
    /// `OK` was expected, but it was missing
    NotOk,
    /// a data pair was expected
    NotPair,
    /// invalid handshake banner received
    BadBanner,
    /// expected some field, but it was missing
    NoField(&'static str)
}

impl fmt::Display for ProtoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.description())
    }
}

impl StdError for ProtoError {
    fn description(&self) -> &str {
        match *self {
            ProtoError::NotOk => "OK expected",
            ProtoError::NotPair => "pair expected",
            ProtoError::BadBanner => "banner error",
            ProtoError::NoField(_) => "missing field",
        }
    }
}
//}}}

<|endoftext|>


<commit_before>// Copyright 2016 Serde YAML Developers
//
// 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::error;
use std::fmt::{self, Display, Debug};
use std::io;
use std::result;
use std::str;
use std::string;

use yaml_rust::emitter;
use yaml_rust::scanner::{self, Marker, ScanError};

use serde::{de, ser};

use path::Path;
/// deserializing YAML data.
pub struct Error(Box<ErrorImpl>);

#[derive(Clone, Debug)]
pub struct ErrorPos {
    pub message: String,
    pub marker: Option<ErrorMarker>,
}

#[derive(Clone, Copy, PartialEq, Debug, Eq)]
pub struct ErrorMarker {
    index: usize,
    line: usize,
    col: usize,
}

impl ErrorMarker {
    pub fn index(&self) -> usize {
        self.index
    }

    pub fn line(&self) -> usize {
        self.line
    }

    pub fn col(&self) -> usize {
        self.col
    }

    fn from_marker(marker: &Marker) -> Self {
        ErrorMarker {
            col: marker.col(),
            index: marker.index(),
            line: marker.line(),
        }
    }
}

impl From<Error> for ErrorPos {
    fn from(error: Error) -> Self {
        let message = error.to_string();

        let marker = match *error.0 {
            ErrorImpl::Message(_, pos) => pos.map(|pos| ErrorMarker::from_marker(pos.marker())),
            ErrorImpl::Scan(scan) => Some(ErrorMarker::from_marker(scan.marker())),
            _ => None
        };

        ErrorPos {
            message,
            marker
        }
    }
}

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

/// This type represents all possible errors that can occur when serializing or
/// deserializing a value using YAML.
#[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,
}

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

impl Pos {
    pub fn marker(&self) -> &Marker {
        &self.marker
    }
}

impl Error {
    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn end_of_stream() -> Self {
        Error(Box::new(ErrorImpl::EndOfStream))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn more_than_one_document() -> Self {
        Error(Box::new(ErrorImpl::MoreThanOneDocument))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn io(err: io::Error) -> Error {
        Error(Box::new(ErrorImpl::Io(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn emitter(err: emitter::EmitError) -> Error {
        Error(Box::new(ErrorImpl::Emit(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn scanner(err: scanner::ScanError) -> Error {
        Error(Box::new(ErrorImpl::Scan(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn str_utf8(err: str::Utf8Error) -> Error {
        Error(Box::new(ErrorImpl::Utf8(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn string_utf8(err: string::FromUtf8Error) -> Error {
        Error(Box::new(ErrorImpl::FromUtf8(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn fix_marker(mut self, marker: Marker, path: Path) -> Self {
        if let ErrorImpl::Message(_, ref mut none @ None) = *self.0.as_mut() {
            *none = Some(Pos {
                             marker: marker,
                             path: path.to_string(),
                         });
        }
        self
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self.0 {
            ErrorImpl::Message(ref msg, _) => msg,
            ErrorImpl::Emit(_) => "emit error",
            ErrorImpl::Scan(_) => "scan error",
            ErrorImpl::Io(ref err) => err.description(),
            ErrorImpl::Utf8(ref err) => err.description(),
            ErrorImpl::FromUtf8(ref err) => err.description(),
            ErrorImpl::EndOfStream => "EOF while parsing a value",
            ErrorImpl::MoreThanOneDocument => "deserializing from YAML containing more than one document is not supported",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self.0 {
            ErrorImpl::Scan(ref err) => Some(err),
            ErrorImpl::Io(ref err) => Some(err),
            ErrorImpl::Utf8(ref err) => Some(err),
            ErrorImpl::FromUtf8(ref err) => Some(err),
            _ => None,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self.0 {
            ErrorImpl::Message(ref msg, None) => Display::fmt(msg, f),
            ErrorImpl::Message(ref msg, Some(Pos { marker, ref 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(ref err) => Display::fmt(err, f),
            ErrorImpl::Io(ref err) => Display::fmt(err, f),
            ErrorImpl::Utf8(ref err) => Display::fmt(err, f),
            ErrorImpl::FromUtf8(ref 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")
            }
        }
    }
}

// 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, formatter: &mut fmt::Formatter) -> fmt::Result {
        match *self.0 {
            ErrorImpl::Message(ref msg, ref pos) => {
                formatter.debug_tuple("Message")
                    .field(msg)
                    .field(pos)
                    .finish()
            }
            ErrorImpl::Emit(ref emit) => formatter.debug_tuple("Emit").field(emit).finish(),
            ErrorImpl::Scan(ref scan) => formatter.debug_tuple("Scan").field(scan).finish(),
            ErrorImpl::Io(ref io) => formatter.debug_tuple("Io").field(io).finish(),
            ErrorImpl::Utf8(ref utf8) => formatter.debug_tuple("Utf8").field(utf8).finish(),
            ErrorImpl::FromUtf8(ref from_utf8) => {
                formatter.debug_tuple("FromUtf8").field(from_utf8).finish()
            }
            ErrorImpl::EndOfStream => formatter.debug_tuple("EndOfStream").finish(),
            ErrorImpl::MoreThanOneDocument => formatter.debug_tuple("MoreThanOneDocument").finish(),
        }
    }
}

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)))
    }
}
<commit_msg>Hide Pos impl<commit_after>// Copyright 2016 Serde YAML Developers
//
// 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::error;
use std::fmt::{self, Display, Debug};
use std::io;
use std::result;
use std::str;
use std::string;

use yaml_rust::emitter;
use yaml_rust::scanner::{self, Marker, ScanError};

use serde::{de, ser};

use path::Path;
/// deserializing YAML data.
pub struct Error(Box<ErrorImpl>);

#[derive(Clone, Debug)]
pub struct ErrorPos {
    pub message: String,
    pub marker: Option<ErrorMarker>,
}

#[derive(Clone, Copy, PartialEq, Debug, Eq)]
pub struct ErrorMarker {
    index: usize,
    line: usize,
    col: usize,
}

impl ErrorMarker {
    pub fn index(&self) -> usize {
        self.index
    }

    pub fn line(&self) -> usize {
        self.line
    }

    pub fn col(&self) -> usize {
        self.col
    }

    fn from_marker(marker: &Marker) -> Self {
        ErrorMarker {
            col: marker.col(),
            index: marker.index(),
            line: marker.line(),
        }
    }
}

impl From<Error> for ErrorPos {
    fn from(error: Error) -> Self {
        let message = error.to_string();

        let marker = match *error.0 {
            ErrorImpl::Message(_, pos) => pos.map(|pos| ErrorMarker::from_marker(pos.marker())),
            ErrorImpl::Scan(scan) => Some(ErrorMarker::from_marker(scan.marker())),
            _ => None
        };

        ErrorPos {
            message,
            marker
        }
    }
}

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

/// This type represents all possible errors that can occur when serializing or
/// deserializing a value using YAML.
#[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,
}

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

impl Pos {
    fn marker(&self) -> &Marker {
        &self.marker
    }
}

impl Error {
    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn end_of_stream() -> Self {
        Error(Box::new(ErrorImpl::EndOfStream))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn more_than_one_document() -> Self {
        Error(Box::new(ErrorImpl::MoreThanOneDocument))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn io(err: io::Error) -> Error {
        Error(Box::new(ErrorImpl::Io(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn emitter(err: emitter::EmitError) -> Error {
        Error(Box::new(ErrorImpl::Emit(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn scanner(err: scanner::ScanError) -> Error {
        Error(Box::new(ErrorImpl::Scan(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn str_utf8(err: str::Utf8Error) -> Error {
        Error(Box::new(ErrorImpl::Utf8(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn string_utf8(err: string::FromUtf8Error) -> Error {
        Error(Box::new(ErrorImpl::FromUtf8(err)))
    }

    // Not public API. Should be pub(crate).
    #[doc(hidden)]
    pub fn fix_marker(mut self, marker: Marker, path: Path) -> Self {
        if let ErrorImpl::Message(_, ref mut none @ None) = *self.0.as_mut() {
            *none = Some(Pos {
                             marker: marker,
                             path: path.to_string(),
                         });
        }
        self
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self.0 {
            ErrorImpl::Message(ref msg, _) => msg,
            ErrorImpl::Emit(_) => "emit error",
            ErrorImpl::Scan(_) => "scan error",
            ErrorImpl::Io(ref err) => err.description(),
            ErrorImpl::Utf8(ref err) => err.description(),
            ErrorImpl::FromUtf8(ref err) => err.description(),
            ErrorImpl::EndOfStream => "EOF while parsing a value",
            ErrorImpl::MoreThanOneDocument => "deserializing from YAML containing more than one document is not supported",
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self.0 {
            ErrorImpl::Scan(ref err) => Some(err),
            ErrorImpl::Io(ref err) => Some(err),
            ErrorImpl::Utf8(ref err) => Some(err),
            ErrorImpl::FromUtf8(ref err) => Some(err),
            _ => None,
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self.0 {
            ErrorImpl::Message(ref msg, None) => Display::fmt(msg, f),
            ErrorImpl::Message(ref msg, Some(Pos { marker, ref 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(ref err) => Display::fmt(err, f),
            ErrorImpl::Io(ref err) => Display::fmt(err, f),
            ErrorImpl::Utf8(ref err) => Display::fmt(err, f),
            ErrorImpl::FromUtf8(ref 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")
            }
        }
    }
}

// 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, formatter: &mut fmt::Formatter) -> fmt::Result {
        match *self.0 {
            ErrorImpl::Message(ref msg, ref pos) => {
                formatter.debug_tuple("Message")
                    .field(msg)
                    .field(pos)
                    .finish()
            }
            ErrorImpl::Emit(ref emit) => formatter.debug_tuple("Emit").field(emit).finish(),
            ErrorImpl::Scan(ref scan) => formatter.debug_tuple("Scan").field(scan).finish(),
            ErrorImpl::Io(ref io) => formatter.debug_tuple("Io").field(io).finish(),
            ErrorImpl::Utf8(ref utf8) => formatter.debug_tuple("Utf8").field(utf8).finish(),
            ErrorImpl::FromUtf8(ref from_utf8) => {
                formatter.debug_tuple("FromUtf8").field(from_utf8).finish()
            }
            ErrorImpl::EndOfStream => formatter.debug_tuple("EndOfStream").finish(),
            ErrorImpl::MoreThanOneDocument => formatter.debug_tuple("MoreThanOneDocument").finish(),
        }
    }
}

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)))
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Handlers and types for agent's actions.
//!
//! The basic functionality that a GRR agent exposes is called an _action_.
//! Actions are invoked by the server (when running a _flow_), should gather
//! requested information and report back to the server.
//!
//! In RRG each action consists of three components: a request type, a response
//! type and an action handler. Request and response types wrap lower-level
//! Protocol Buffer messages sent by and to the GRR server. Handlers accept one
//! instance of the corresponding request type and send some (zero or more)
//! instances of the corresponding response type.

mod error;

#[cfg(feature = "action-filesystems")]
#[cfg(target_os = "linux")]
pub mod filesystems;

#[cfg(feature = "action-interfaces")]
#[cfg(target_family = "unix")]
pub mod interfaces;

#[cfg(feature = "action-metadata")]
pub mod metadata;

#[cfg(feature = "action-listdir")]
pub mod listdir;

#[cfg(feature = "action-timeline")]
pub mod timeline;

#[cfg(feature = "action-network")]
pub mod network;

#[cfg(feature = "action-stat")]
pub mod stat;

#[cfg(feature = "action-insttime")]
pub mod insttime;

#[cfg(feature = "action-memsize")]
pub mod memsize;

#[cfg(feature = "action-finder")]
pub mod finder;

pub use error::{
    ParseArgsError, ParseArgsErrorKind,
    DispatchError, DispatchErrorKind,
};
use crate::session::{self, Session};

/// Abstraction for action-specific requests.
///
/// Protocol Buffer messages received from the GRR server are not necessarily
/// easy to work with and are hardly idiomatic to Rust. For this reason, actions
/// should define more structured data types to represent their input and should
/// be able to parse raw messages into them.
pub trait Request: Sized {

    /// A type of the corresponding raw proto message.
    type Proto: protobuf::Message + Default;

    /// A method for converting raw proto messages into structured requests.
    fn from_proto(proto: Self::Proto) -> Result<Self, session::ParseError>;
}

/// Abstraction for action-specific responses.
///
/// Like with the [`Request`] type, Protocol Buffer messages sent to the GRR
/// server are very idiomatic to Rust. For this reason, actions should define
/// more structured data types to represent responses and provide a way to
/// convert them into the wire format.
///
/// Note that because of the design flaws in the protocol, actions also need to
/// specify a name of the wrapper RDF class from the Python implementation.
/// Hopefully, one day this issue would be fixed and class names will not leak
/// into the specification.
///
/// [`Request`]: trait.Request.html
pub trait Response: Sized {

    /// A name of the corresponding RDF class.
    const RDF_NAME: Option<&'static str>;

    /// A type of the corresponding raw proto message.
    type Proto: protobuf::Message + Default;

    /// A method for converting structured responses into raw proto messages.
    fn into_proto(self) -> Self::Proto;
}

impl Request for () {

    type Proto = protobuf::well_known_types::Empty;

    fn from_proto(_: protobuf::well_known_types::Empty) -> Result<(), session::ParseError> {
        Ok(())
    }
}

impl Response for () {

    const RDF_NAME: Option<&'static str> = None;

    type Proto = protobuf::well_known_types::Empty;

    fn into_proto(self) -> protobuf::well_known_types::Empty {
        protobuf::well_known_types::Empty::new()
    }
}

/// Dispatches the given `request` to an appropriate action handler.
///
/// This method is a mapping between action names (as specified in the protocol)
/// and action handlers (implemented on the agent).
///
/// # Errors
///
/// This function will return an error if the given action is unknown (or not
/// yet implemented).
///
/// It will also error out if the action execution itself fails for whatever
/// reason.
pub fn dispatch<'s, S>(session: &mut S, request: crate::message::Request) -> session::Result<()>
where
    S: Session,
{
    match request.action_name() {
        #[cfg(feature = "action-metadata")]
        "GetClientInfo" => handle(session, request, self::metadata::handle),

        #[cfg(feature = "action-listdir")]
        "ListDirectory" => handle(session, request, self::listdir::handle),

        #[cfg(feature = "action-timeline")]
        "Timeline" => handle(session, request, self::timeline::handle),

        #[cfg(feature = "action-network")]
        "ListNetworkConnections" => handle(session, request, self::network::handle),

        #[cfg(feature = "action-stat")]
        "GetFileStat" => handle(session, request, self::stat::handle),

        #[cfg(feature = "action-insttime")]
        "GetInstallDate" => handle(session, request, self::insttime::handle),

        #[cfg(feature = "action-interfaces")]
        #[cfg(target_family = "unix")]
        "EnumerateInterfaces" => handle(session, request, self::interfaces::handle),

        #[cfg(feature = "action-filesystems")]
        #[cfg(target_os = "linux")]
        "EnumerateFilesystems" => handle(session, request, self::filesystems::handle),

        #[cfg(feature = "action-memsize")]
        "GetMemorySize" => handle(session, request, self::memsize::handle),

        action => return Err(session::Error::Dispatch(String::from(action))),
    }
}

/// Handles a `request` using the specified `handler`.
///
/// This method will attempt to interpret request arguments for the specific
/// action and execute the handler with them.
///
/// # Errors
///
/// This function will return an error if the request arguments cannot be parsed
/// for the specific action or if the action execution fails.
fn handle<S, A, H>(session: &mut S, request: crate::message::Request, handler: H) -> session::Result<()>
where
    S: crate::session::Session,
    A: Args,
    H: FnOnce(&mut S, A) -> session::Result<()>,
{
    let args = request.parse_args()?;
    handler(session, args)
}

// TODO(panhania@): Remove all usages of the `Request` trait and replace it with
// `Args`.
pub trait Args: Sized {
    /// Low-level Protocol Buffers type representing the action arguments.
    type Proto: protobuf::Message + Default;

    /// Converts a low-level type to a structured request arguments.
    fn from_proto(proto: Self::Proto) -> Result<Self, ParseArgsError>;
}

impl Args for () {

    type Proto = protobuf::well_known_types::Empty;

    fn from_proto(_: protobuf::well_known_types::Empty) -> Result<(), ParseArgsError> {
        Ok(())
    }
}

pub trait Item: Sized {
    /// Low-level Protocol Buffers type representing the action results.
    type Proto: protobuf::Message + Default;

    /// A name of the corresponding RDF class in GRR.
    const RDF_NAME: &'static str;

    /// Converts an action result ot its low-level representation.
    fn into_proto(self) -> Self::Proto;
}

impl Item for () {

    // This implementation is intended to be used only in tests and we do not
    // really care about the `RDF_NAME` field there. And since GRR does not have
    // any RDF wrapper for empty type (except maybe `EmptyFlowArgs`, but this is
    // semantically different), we just leave it blank.
    const RDF_NAME: &'static str = "";

    type Proto = protobuf::well_known_types::Empty;

    fn into_proto(self) -> protobuf::well_known_types::Empty {
        protobuf::well_known_types::Empty::new()
    }
}
<commit_msg>Remove old action types.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

//! Handlers and types for agent's actions.
//!
//! The basic functionality that a GRR agent exposes is called an _action_.
//! Actions are invoked by the server (when running a _flow_), should gather
//! requested information and report back to the server.
//!
//! In RRG each action consists of three components: a request type, a response
//! type and an action handler. Request and response types wrap lower-level
//! Protocol Buffer messages sent by and to the GRR server. Handlers accept one
//! instance of the corresponding request type and send some (zero or more)
//! instances of the corresponding response type.

mod error;

#[cfg(feature = "action-filesystems")]
#[cfg(target_os = "linux")]
pub mod filesystems;

#[cfg(feature = "action-interfaces")]
#[cfg(target_family = "unix")]
pub mod interfaces;

#[cfg(feature = "action-metadata")]
pub mod metadata;

#[cfg(feature = "action-listdir")]
pub mod listdir;

#[cfg(feature = "action-timeline")]
pub mod timeline;

#[cfg(feature = "action-network")]
pub mod network;

#[cfg(feature = "action-stat")]
pub mod stat;

#[cfg(feature = "action-insttime")]
pub mod insttime;

#[cfg(feature = "action-memsize")]
pub mod memsize;

#[cfg(feature = "action-finder")]
pub mod finder;

pub use error::{
    ParseArgsError, ParseArgsErrorKind,
    DispatchError, DispatchErrorKind,
};
use crate::session::{self, Session};

/// Dispatches the given `request` to an appropriate action handler.
///
/// This method is a mapping between action names (as specified in the protocol)
/// and action handlers (implemented on the agent).
///
/// # Errors
///
/// This function will return an error if the given action is unknown (or not
/// yet implemented).
///
/// It will also error out if the action execution itself fails for whatever
/// reason.
pub fn dispatch<'s, S>(session: &mut S, request: crate::message::Request) -> session::Result<()>
where
    S: Session,
{
    match request.action_name() {
        #[cfg(feature = "action-metadata")]
        "GetClientInfo" => handle(session, request, self::metadata::handle),

        #[cfg(feature = "action-listdir")]
        "ListDirectory" => handle(session, request, self::listdir::handle),

        #[cfg(feature = "action-timeline")]
        "Timeline" => handle(session, request, self::timeline::handle),

        #[cfg(feature = "action-network")]
        "ListNetworkConnections" => handle(session, request, self::network::handle),

        #[cfg(feature = "action-stat")]
        "GetFileStat" => handle(session, request, self::stat::handle),

        #[cfg(feature = "action-insttime")]
        "GetInstallDate" => handle(session, request, self::insttime::handle),

        #[cfg(feature = "action-interfaces")]
        #[cfg(target_family = "unix")]
        "EnumerateInterfaces" => handle(session, request, self::interfaces::handle),

        #[cfg(feature = "action-filesystems")]
        #[cfg(target_os = "linux")]
        "EnumerateFilesystems" => handle(session, request, self::filesystems::handle),

        #[cfg(feature = "action-memsize")]
        "GetMemorySize" => handle(session, request, self::memsize::handle),

        action => return Err(session::Error::Dispatch(String::from(action))),
    }
}

/// Handles a `request` using the specified `handler`.
///
/// This method will attempt to interpret request arguments for the specific
/// action and execute the handler with them.
///
/// # Errors
///
/// This function will return an error if the request arguments cannot be parsed
/// for the specific action or if the action execution fails.
fn handle<S, A, H>(session: &mut S, request: crate::message::Request, handler: H) -> session::Result<()>
where
    S: crate::session::Session,
    A: Args,
    H: FnOnce(&mut S, A) -> session::Result<()>,
{
    let args = request.parse_args()?;
    handler(session, args)
}

// TODO(panhania@): Remove all usages of the `Request` trait and replace it with
// `Args`.
pub trait Args: Sized {
    /// Low-level Protocol Buffers type representing the action arguments.
    type Proto: protobuf::Message + Default;

    /// Converts a low-level type to a structured request arguments.
    fn from_proto(proto: Self::Proto) -> Result<Self, ParseArgsError>;
}

impl Args for () {

    type Proto = protobuf::well_known_types::Empty;

    fn from_proto(_: protobuf::well_known_types::Empty) -> Result<(), ParseArgsError> {
        Ok(())
    }
}

pub trait Item: Sized {
    /// Low-level Protocol Buffers type representing the action results.
    type Proto: protobuf::Message + Default;

    /// A name of the corresponding RDF class in GRR.
    const RDF_NAME: &'static str;

    /// Converts an action result ot its low-level representation.
    fn into_proto(self) -> Self::Proto;
}

impl Item for () {

    // This implementation is intended to be used only in tests and we do not
    // really care about the `RDF_NAME` field there. And since GRR does not have
    // any RDF wrapper for empty type (except maybe `EmptyFlowArgs`, but this is
    // semantically different), we just leave it blank.
    const RDF_NAME: &'static str = "";

    type Proto = protobuf::well_known_types::Empty;

    fn into_proto(self) -> protobuf::well_known_types::Empty {
        protobuf::well_known_types::Empty::new()
    }
}
<|endoftext|>


<commit_before>use std::cmp;

extern crate unicode_segmentation;
use self::unicode_segmentation::UnicodeSegmentation;

fn edit_distance(str1: &str, str2: &str) -> usize {
    let str1_vec = UnicodeSegmentation::graphemes(str1, true).collect::<Vec<&str>>();
    let str2_vec = UnicodeSegmentation::graphemes(str2, true).collect::<Vec<&str>>();
    let str1_size = str1_vec.len() + 1;
    let str2_size = str2_vec.len() + 1;
    let mut dp = vec![vec![0; str2_size]; str1_size];
    for i in 0..str1_size {
        for j in 0..str2_size {
            if i == 0 {
                dp[i][j] = j;
            } else if j == 0 {
                dp[i][j] = i;
            } else if str1_vec[i - 1] == str2_vec[j - 1] {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = 1 + cmp::min(
                    dp[i][j - 1],
                    cmp::min(dp[i - 1][j],
                        dp[i - 1][j - 1]));
            }
        }
    }
    dp[str1_size - 1 as usize][str2_size - 1 as usize]
}

#[cfg(test)]
mod test {
    use fdupe;

    #[test]
    fn test_edit_distance() {
        assert_eq!(2, fdupe::edit_distance("hello", "holla"));
        assert_eq!(2, fdupe::edit_distance("hell", "holla"));
        assert_eq!(3, fdupe::edit_distance("abc", "def"));
        assert_eq!(1, fdupe::edit_distance("忠犬ハチ公", "忠犬ハチ"));
        assert_eq!(2, fdupe::edit_distance("犬ハチ公", "忠犬ハチ"));
    }
}<commit_msg>Add some walkdir<commit_after>extern crate walkdir;
extern crate unicode_segmentation;

use std::cmp;
use std::path::Path;
use self::unicode_segmentation::UnicodeSegmentation;
use self::walkdir::WalkDir;

fn edit_distance(str1: &str, str2: &str) -> usize {
    let str1_vec = UnicodeSegmentation::graphemes(str1, true).collect::<Vec<&str>>();
    let str2_vec = UnicodeSegmentation::graphemes(str2, true).collect::<Vec<&str>>();
    let str1_size = str1_vec.len() + 1;
    let str2_size = str2_vec.len() + 1;
    let mut dp = vec![vec![0; str2_size]; str1_size];
    for i in 0..str1_size {
        for j in 0..str2_size {
            if i == 0 {
                dp[i][j] = j;
            } else if j == 0 {
                dp[i][j] = i;
            } else if str1_vec[i - 1] == str2_vec[j - 1] {
                dp[i][j] = dp[i - 1][j - 1];
            } else {
                dp[i][j] = 1 + cmp::min(
                    dp[i][j - 1],
                    cmp::min(dp[i - 1][j],
                        dp[i - 1][j - 1]));
            }
        }
    }
    dp[str1_size - 1 as usize][str2_size - 1 as usize]
}

fn get_paths<'a>(dir: &str) {
    let walker = WalkDir::new(dir).into_iter();
    for entry in walker.filter_map(|e| e.ok()) {
        let path = entry.path();
        println!("{:?}", path.file_name())
    }
}

#[cfg(test)]
mod test {
    use fdupe;

    #[test]
    fn test_edit_distance() {
        assert_eq!(2, fdupe::edit_distance("hello", "holla"));
        assert_eq!(2, fdupe::edit_distance("hell", "holla"));
        assert_eq!(3, fdupe::edit_distance("abc", "def"));
        assert_eq!(1, fdupe::edit_distance("忠犬ハチ公", "忠犬ハチ"));
        assert_eq!(2, fdupe::edit_distance("犬ハチ公", "忠犬ハチ"));
    }

    #[test]
    fn test_get_paths() {
        fdupe::get_paths("/tmp");
    }
}<|endoftext|>


<commit_before>//! Http client api
//!
//! ```rust
//! # extern crate actix_web;
//! # extern crate actix;
//! # extern crate futures;
//! # extern crate tokio;
//! # use futures::Future;
//! # use std::process;
//! use actix_web::client;
//!
//! fn main() {
//!     actix::run(
//!         || client::get("http://www.rust-lang.org")   // <- Create request builder
//!             .header("User-Agent", "Actix-web")
//!             .finish().unwrap()
//!             .send()                               // <- Send http request
//!             .map_err(|_| ())
//!             .and_then(|response| {                // <- server http response
//!                 println!("Response: {:?}", response);
//! #               actix::System::current().stop();
//!                 Ok(())
//!             })
//!     );
//! }
//! ```
mod connector;
mod parser;
mod pipeline;
mod request;
mod response;
mod writer;

pub use self::connector::{
    ClientConnector, ClientConnectorError, ClientConnectorStats, Connect, Connection,
    Pause, Resume,
};
pub(crate) use self::parser::{HttpResponseParser, HttpResponseParserError};
pub(crate) use self::pipeline::Pipeline;
pub use self::pipeline::{SendRequest, SendRequestError};
pub use self::request::{ClientRequest, ClientRequestBuilder};
pub use self::response::ClientResponse;
pub(crate) use self::writer::HttpClientWriter;

use error::ResponseError;
use http::Method;
use httpresponse::HttpResponse;

/// Convert `SendRequestError` to a `HttpResponse`
impl ResponseError for SendRequestError {
    fn error_response(&self) -> HttpResponse {
        match *self {
            SendRequestError::Timeout => HttpResponse::GatewayTimeout(),
            SendRequestError::Connector(_) => HttpResponse::BadGateway(),
            _ => HttpResponse::InternalServerError(),
        }.into()
    }
}

/// Create request builder for `GET` requests
///
///
/// ```rust
/// # extern crate actix_web;
/// # extern crate actix;
/// # extern crate futures;
/// # extern crate tokio;
/// # extern crate env_logger;
/// # use futures::Future;
/// # use std::process;
/// use actix_web::client;
///
/// fn main() {
///     actix::run(
///         || client::get("http://www.rust-lang.org")   // <- Create request builder
///             .header("User-Agent", "Actix-web")
///             .finish().unwrap()
///             .send()                               // <- Send http request
///             .map_err(|_| ())
///             .and_then(|response| {                // <- server http response
///                 println!("Response: {:?}", response);
/// #               actix::System::current().stop();
///                 Ok(())
///             }),
///     );
/// }
/// ```
pub fn get<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::GET).uri(uri);
    builder
}

/// Create request builder for `HEAD` requests
pub fn head<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::HEAD).uri(uri);
    builder
}

/// Create request builder for `POST` requests
pub fn post<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::POST).uri(uri);
    builder
}

/// Create request builder for `PUT` requests
pub fn put<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::PUT).uri(uri);
    builder
}

/// Create request builder for `DELETE` requests
pub fn delete<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::DELETE).uri(uri);
    builder
}
<commit_msg>Fixed example in client documentation. This closes #665.<commit_after>//! Http client api
//!
//! ```rust
//! # extern crate actix_web;
//! # extern crate actix;
//! # extern crate futures;
//! # extern crate tokio;
//! # use std::process;
//! use actix_web::client;
//! use futures::Future;
//!
//! fn main() {
//!     actix::run(
//!         || client::get("http://www.rust-lang.org")   // <- Create request builder
//!             .header("User-Agent", "Actix-web")
//!             .finish().unwrap()
//!             .send()                               // <- Send http request
//!             .map_err(|_| ())
//!             .and_then(|response| {                // <- server http response
//!                 println!("Response: {:?}", response);
//! #               actix::System::current().stop();
//!                 Ok(())
//!             })
//!     );
//! }
//! ```
mod connector;
mod parser;
mod pipeline;
mod request;
mod response;
mod writer;

pub use self::connector::{
    ClientConnector, ClientConnectorError, ClientConnectorStats, Connect, Connection,
    Pause, Resume,
};
pub(crate) use self::parser::{HttpResponseParser, HttpResponseParserError};
pub(crate) use self::pipeline::Pipeline;
pub use self::pipeline::{SendRequest, SendRequestError};
pub use self::request::{ClientRequest, ClientRequestBuilder};
pub use self::response::ClientResponse;
pub(crate) use self::writer::HttpClientWriter;

use error::ResponseError;
use http::Method;
use httpresponse::HttpResponse;

/// Convert `SendRequestError` to a `HttpResponse`
impl ResponseError for SendRequestError {
    fn error_response(&self) -> HttpResponse {
        match *self {
            SendRequestError::Timeout => HttpResponse::GatewayTimeout(),
            SendRequestError::Connector(_) => HttpResponse::BadGateway(),
            _ => HttpResponse::InternalServerError(),
        }.into()
    }
}

/// Create request builder for `GET` requests
///
///
/// ```rust
/// # extern crate actix_web;
/// # extern crate actix;
/// # extern crate futures;
/// # extern crate tokio;
/// # extern crate env_logger;
/// # use std::process;
/// use actix_web::client;
/// use futures::Future;
///
/// fn main() {
///     actix::run(
///         || client::get("http://www.rust-lang.org")   // <- Create request builder
///             .header("User-Agent", "Actix-web")
///             .finish().unwrap()
///             .send()                               // <- Send http request
///             .map_err(|_| ())
///             .and_then(|response| {                // <- server http response
///                 println!("Response: {:?}", response);
/// #               actix::System::current().stop();
///                 Ok(())
///             }),
///     );
/// }
/// ```
pub fn get<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::GET).uri(uri);
    builder
}

/// Create request builder for `HEAD` requests
pub fn head<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::HEAD).uri(uri);
    builder
}

/// Create request builder for `POST` requests
pub fn post<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::POST).uri(uri);
    builder
}

/// Create request builder for `PUT` requests
pub fn put<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::PUT).uri(uri);
    builder
}

/// Create request builder for `DELETE` requests
pub fn delete<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
    let mut builder = ClientRequest::build();
    builder.method(Method::DELETE).uri(uri);
    builder
}
<|endoftext|>


<commit_before>pub mod model;

use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};

use std::collections::HashMap;

use std::sync::{Arc, Mutex};
use std::thread;

#[derive(Debug)]
pub struct Client
{
    listener: TcpListener,
    list: Arc<Mutex<Vec<model::Request>>>,
}

impl Client
{
    pub fn new(listener: TcpListener) -> Client
    {
        Client {
            listener: listener,
            list: Arc::new(Mutex::new(Vec::new())),
        }
    }

    pub fn init(&self)
    {
        let list = self.list.clone();
        let listener = self.listener.try_clone().unwrap();

        thread::spawn(move|| {
            for stream in listener.incoming() {
                match stream {
                    Ok(stream) => {
                        let http_request = Stream::new(stream);

                        for request in http_request {
                            let mut list = list.lock().unwrap();
                            list.push(request);
                        }
                    },
                    Err(msg) => panic!("{}", msg),
                }
            }
        });
    }
}

impl Iterator for Client
{
    type Item = model::Request;

    fn next(&mut self) -> Option<model::Request>
    {
        let list = self.list.clone();

        loop {
            {
                let mut list = list.lock().unwrap();
                match list.pop() {
                    Some(request) => return Some(request),
                    None => (),
                }
            }
        }
    }

}

#[derive(Debug)]
pub struct Stream
{
    _stream: TcpStream,
    request_list: HashMap<u16, model::Request>,
    readable: bool,
}

impl Stream
{
    pub fn new (stream: TcpStream) -> Stream
    {
        Stream {
            _stream: stream,
            request_list: HashMap::new(),
            readable: true,
        }
    }

    pub fn write(&mut self, response: &model::Response)
    {
        match self._stream.write(&response.get_data()) {
            Ok(_) => (),
            _ => panic!("fcgi: failed sending response"),
        }
    }
}

impl Iterator for Stream
{
    type Item = model::Request;

    fn next(&mut self) -> Option<model::Request>
    {
        let mut result: Option<model::Request> = None;

        'read: while self.readable {

            let mut buf: [u8; model::HEADER_LEN] = [0; model::HEADER_LEN];

            match self._stream.read(&mut buf) {
                Ok(model::HEADER_LEN) => (),
                _ => panic!("FCGI header mismatch"),
            };

            let header = model::Header::read(&buf);
            let request_id = header.request_id.clone();

            match self.request_list.get(&request_id) {
                Some(..) => (),
                None => {
                    self.request_list.insert(request_id.clone(), model::Request::new(request_id.clone()));
                },
            };

            if header.content_length == 0 {
                match header.type_ {
                    model::STDIN => {
                        result = self.request_list.remove(&request_id);
                        break;
                    },
                    model::PARAMS | model::DATA => continue 'read,
                    _ => (),
                };
            }

            let len: usize = header.content_length as usize;
            let mut body_data: Vec<u8> = Vec::with_capacity(len);
            unsafe {
                body_data.set_len(len);
            }

            match self._stream.read(&mut body_data) {
                Ok(readed_len) if readed_len == len =>
                    self.request_list.get_mut(&request_id).unwrap().add_record(&header, body_data),
                _  => panic!("Wrong body length"),
            }
        };

        if self.request_list.is_empty() {
            self.readable = false;
        }

        result
    }
}
<commit_msg>now use channels<commit_after>pub mod model;

use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream};

use std::collections::HashMap;

use std::thread;
use std::sync::mpsc;

pub struct Client
{
    listener: TcpListener,
    list: Vec<model::Request>,
    request_tx: mpsc::Sender<model::Request>,
    request_rx: mpsc::Receiver<model::Request>,
}

impl Client
{
    pub fn new(listener: TcpListener) -> Client
    {
        let (tx, rx) = mpsc::channel();
        Client {
            listener: listener,
            list: Vec::new(),
            request_tx: tx,
            request_rx: rx,
        }
    }

    pub fn init(&self)
    {
        let request_tx = self.request_tx.clone();
        let listener = self.listener.try_clone().unwrap();

        thread::spawn(move || {
            for stream in listener.incoming() {
                match stream {
                    Ok(stream) => {
                        let fcgi_stream = Stream::new(stream);
                        for request in fcgi_stream {
                            request_tx.send(request).unwrap();
                        }
                    },
                    Err(msg) => panic!("{}", msg),
                }
            }
        });
    }
}

impl Iterator for Client
{
    type Item = model::Request;

    fn next(&mut self) -> Option<model::Request>
    {
        Some(self.request_rx.recv().unwrap())
    }

}

#[derive(Debug)]
pub struct Stream
{
    _stream: TcpStream,
    request_list: HashMap<u16, model::Request>,
    readable: bool,
}

impl Stream
{
    pub fn new (stream: TcpStream) -> Stream
    {
        Stream {
            _stream: stream,
            request_list: HashMap::new(),
            readable: true,
        }
    }

    pub fn write(&mut self, response: &model::Response)
    {
        match self._stream.write(&response.get_data()) {
            Ok(_) => (),
            _ => panic!("fcgi: failed sending response"),
        }
    }
}

impl Iterator for Stream
{
    type Item = model::Request;

    fn next(&mut self) -> Option<model::Request>
    {
        let mut result: Option<model::Request> = None;

        'read: while self.readable {

            let mut buf: [u8; model::HEADER_LEN] = [0; model::HEADER_LEN];

            match self._stream.read(&mut buf) {
                Ok(model::HEADER_LEN) => (),
                _ => panic!("FCGI header mismatch"),
            };

            let header = model::Header::read(&buf);
            let request_id = header.request_id.clone();

            match self.request_list.get(&request_id) {
                Some(..) => (),
                None => {
                    self.request_list.insert(request_id.clone(), model::Request::new(request_id.clone()));
                },
            };

            if header.content_length == 0 {
                match header.type_ {
                    model::STDIN => {
                        result = self.request_list.remove(&request_id);
                        break;
                    },
                    model::PARAMS | model::DATA => continue 'read,
                    _ => (),
                };
            }

            let len: usize = header.content_length as usize;
            let mut body_data: Vec<u8> = Vec::with_capacity(len);
            unsafe {
                body_data.set_len(len);
            }

            match self._stream.read(&mut body_data) {
                Ok(readed_len) if readed_len == len =>
                    self.request_list.get_mut(&request_id).unwrap().add_record(&header, body_data),
                _  => panic!("Wrong body length"),
            }
        };

        if self.request_list.is_empty() {
            self.readable = false;
        }

        result
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::mem::transmute;
use std::io::{Cursor, Read, Write, ErrorKind};
use std::default::Default;

use rand;
use byteorder::{BigEndian, ReadBytesExt};

use result::{Result, Error, Kind};
use protocol::{OpCode, CloseCode};
use stream::TryReadBuf;

fn apply_mask(buf: &mut [u8], mask: &[u8; 4]) {
    let iter = buf.iter_mut().zip(mask.iter().cycle());
    for (byte, &key) in iter {
        *byte ^= key
    }
}

/// A struct representing a WebSocket frame.
#[derive(Debug, Clone)]
pub struct Frame {
    finished: bool,
    rsv1: bool,
    rsv2: bool,
    rsv3: bool,
    opcode: OpCode,

    mask: Option<[u8; 4]>,

    payload: Vec<u8>,
}

impl Frame {

    /// Get the length of the frame.
    /// This is the length of the header + the length of the payload.
    #[inline]
    pub fn len(&self) -> usize {
        let mut header_length = 2;
        let payload_len = self.payload().len();
        if payload_len > 125 {
            if payload_len <= u16::max_value() as usize {
                header_length += 2;
            } else {
                header_length += 8;
            }
        }

        if self.is_masked() {
            header_length += 4;
        }

        header_length + payload_len
    }

    /// Test whether the frame is a final frame.
    #[inline]
    pub fn is_final(&self) -> bool {
        self.finished
    }

    /// Test whether the first reserved bit is set.
    #[inline]
    pub fn has_rsv1(&self) -> bool {
        self.rsv1
    }

    /// Test whether the second reserved bit is set.
    #[inline]
    pub fn has_rsv2(&self) -> bool {
        self.rsv2
    }

    /// Test whether the third reserved bit is set.
    #[inline]
    pub fn has_rsv3(&self) -> bool {
        self.rsv3
    }

    /// Get the OpCode of the frame.
    #[inline]
    pub fn opcode(&self) -> OpCode {
        self.opcode
    }

    /// Test whether this is a control frame.
    #[inline]
    pub fn is_control(&self) -> bool {
        self.opcode.is_control()
    }

    /// Get a reference to the frame's payload.
    #[inline]
    pub fn payload(&self) -> &Vec<u8> {
        &self.payload
    }

    // Test whether the frame is masked.
    #[doc(hidden)]
    #[inline]
    pub fn is_masked(&self) -> bool {
        self.mask.is_some()
    }

    // Get an optional reference to the frame's mask.
    #[doc(hidden)]
    #[allow(dead_code)]
    #[inline]
    pub fn mask(&self) -> Option<&[u8; 4]> {
        self.mask.as_ref()
    }

    /// Make this frame a final frame.
    #[allow(dead_code)]
    #[inline]
    pub fn set_final(&mut self, is_final: bool) -> &mut Frame {
        self.finished = is_final;
        self
    }

    /// Set the first reserved bit.
    #[inline]
    pub fn set_rsv1(&mut self, has_rsv1: bool) -> &mut Frame {
        self.rsv1 = has_rsv1;
        self
    }

    /// Set the second reserved bit.
    #[inline]
    pub fn set_rsv2(&mut self, has_rsv2: bool) -> &mut Frame {
        self.rsv2 = has_rsv2;
        self
    }

    /// Set the third reserved bit.
    #[inline]
    pub fn set_rsv3(&mut self, has_rsv3: bool) -> &mut Frame {
        self.rsv3 = has_rsv3;
        self
    }

    /// Set the OpCode.
    #[allow(dead_code)]
    #[inline]
    pub fn set_opcode(&mut self, opcode: OpCode) -> &mut Frame {
        self.opcode = opcode;
        self
    }

    /// Edit the frame's payload.
    #[allow(dead_code)]
    #[inline]
    pub fn payload_mut(&mut self) -> &mut Vec<u8> {
        &mut self.payload
    }

    // Generate a new mask for this frame.
    //
    // This method simply generates and stores the mask. It does not change the payload data.
    // Instead, the payload data will be masked with the generated mask when the frame is sent
    // to the other endpoint.
    #[doc(hidden)]
    #[inline]
    pub fn set_mask(&mut self) -> &mut Frame {
        self.mask = Some(rand::random());
        self
    }

    // This method unmasks the payload and should only be called on frames that are actually
    // masked. In other words, those frames that have just been received from a client endpoint.
    #[doc(hidden)]
    #[inline]
    pub fn remove_mask(&mut self) -> &mut Frame {
        self.mask.and_then(|mask| {
            Some(apply_mask(&mut self.payload, &mask))
        });
        self.mask = None;
        self
    }

    /// Consume the frame into its payload.
    pub fn into_data(self) -> Vec<u8> {
        self.payload
    }

    /// Create a new data frame.
    #[inline]
    pub fn message(data: Vec<u8>, code: OpCode, finished: bool) -> Frame {
        debug_assert!(match code {
            OpCode::Text | OpCode::Binary | OpCode::Continue => true,
            _ => false,
        }, "Invalid opcode for data frame.");

        Frame {
            finished: finished,
            opcode: code,
            payload: data,
            .. Frame::default()
        }
    }

    /// Create a new Pong control frame.
    #[inline]
    pub fn pong(data: Vec<u8>) -> Frame {
        Frame {
            opcode: OpCode::Pong,
            payload: data,
            .. Frame::default()
        }
    }

    /// Create a new Ping control frame.
    #[inline]
    pub fn ping(data: Vec<u8>) -> Frame {
        Frame {
            opcode: OpCode::Ping,
            payload: data,
            .. Frame::default()
        }
    }

    /// Create a new Close control frame.
    #[inline]
    pub fn close(code: CloseCode, reason: &str) -> Frame {
        let payload = if let CloseCode::Empty = code {
            Vec::new()
        } else {
            let u: u16 = code.into();
            let raw = [(u >> 8) as u8, u as u8];
            [&raw, reason.as_bytes()].concat()
        };

        Frame {
            payload: payload,
            .. Frame::default()
        }
    }

    /// Parse the input stream into a frame.
    pub fn parse(cursor: &mut Cursor<Vec<u8>>) -> Result<Option<Frame>> {
        let size = cursor.get_ref().len() as u64 - cursor.position();
        let initial = cursor.position();
        trace!("Position in buffer {}", initial);

        let mut head = [0u8; 2];
        if try!(cursor.read(&mut head)) != 2 {
            cursor.set_position(initial);
            return Ok(None)
        }

        trace!("Parsed headers {:?}", head);

        let first = head[0];
        let second = head[1];
        trace!("First: {:b}", first);
        trace!("Second: {:b}", second);

        let finished = first & 0x80 != 0;

        let rsv1 = first & 0x40 != 0;
        let rsv2 = first & 0x20 != 0;
        let rsv3 = first & 0x10 != 0;

        let opcode = OpCode::from(first & 0x0F);
        trace!("Opcode: {:?}", opcode);

        let masked = second & 0x80 != 0;
        trace!("Masked: {:?}", masked);

        let mut header_length = 2;

        let mut length = (second & 0x7F) as u64;

        if let Some(length_nbytes) = match length {
            126 => Some(2),
            127 => Some(8),
            _ => None,
        } {
            match cursor.read_uint::<BigEndian>(length_nbytes) {
                Err(ref err) if err.kind() == ErrorKind::UnexpectedEof => {
                    cursor.set_position(initial);
                    return Ok(None);
                }
                Err(err) => {
                    return Err(Error::from(err));
                }
                Ok(read) => {
                    length = read;
                }
            };
            header_length += length_nbytes as u64;
        }
        trace!("Payload length: {}", length);

        let mask = if masked {
            let mut mask_bytes = [0u8; 4];
            if try!(cursor.read(&mut mask_bytes)) != 4 {
                cursor.set_position(initial);
                return Ok(None)
            } else {
                header_length += 4;
                Some(mask_bytes)
            }
        } else {
            None
        };

        if size < length + header_length {
            cursor.set_position(initial);
            return Ok(None)
        }

        let mut data = Vec::with_capacity(length as usize);
        if length > 0 {
            if let Some(read) = try!(cursor.try_read_buf(&mut data)) {
                debug_assert!(read == length as usize, "Read incorrect payload length!");
            }
        }

        // Disallow bad opcode
        if let OpCode::Bad = opcode {
            return Err(Error::new(Kind::Protocol, format!("Encountered invalid opcode: {}", first & 0x0F)))
        }

        // control frames must have length <= 125
        match opcode {
            OpCode::Ping | OpCode::Pong if length > 125 => {
                return Err(Error::new(Kind::Protocol, format!("Rejected WebSocket handshake.Received control frame with length: {}.", length)))
            }
            OpCode::Close if length > 125 => {
                debug!("Received close frame with payload length exceeding 125. Morphing to protocol close frame.");
                return Ok(Some(Frame::close(CloseCode::Protocol, "Received close frame with payload length exceeding 125.")))
            }
            _ => ()
        }

        let frame = Frame {
            finished: finished,
            rsv1: rsv1,
            rsv2: rsv2,
            rsv3: rsv3,
            opcode: opcode,
            mask: mask,
            payload: data,
        };

        Ok(Some(frame))
    }

    /// Write a frame out to a buffer
    pub fn format<W>(&mut self, w: &mut W) -> Result<()>
        where W: Write
    {
        let mut one = 0u8;
        let code: u8 = self.opcode.into();
        if self.is_final() {
            one |= 0x80;
        }
        if self.has_rsv1() {
            one |= 0x40;
        }
        if self.has_rsv2() {
            one |= 0x20;
        }
        if self.has_rsv3() {
            one |= 0x10;
        }
        one |= code;

        let mut two = 0u8;

        if self.is_masked() {
            two |= 0x80;
        }

        if self.payload.len() < 126 {
            two |= self.payload.len() as u8;
            let headers = [one, two];
            try!(w.write(&headers));
        } else if self.payload.len() <= 65535 {
            two |= 126;
            let length_bytes: [u8; 2] = unsafe {
                let short = self.payload.len() as u16;
                transmute(short.to_be())
            };
            let headers = [one, two, length_bytes[0], length_bytes[1]];
            try!(w.write(&headers));
        } else {
            two |= 127;
            let length_bytes: [u8; 8] = unsafe {
                let long = self.payload.len() as u64;
                transmute(long.to_be())
            };
            let headers = [
                one,
                two,
                length_bytes[0],
                length_bytes[1],
                length_bytes[2],
                length_bytes[3],
                length_bytes[4],
                length_bytes[5],
                length_bytes[6],
                length_bytes[7],
            ];
            try!(w.write(&headers));
        }

        if self.is_masked() {
            let mask = self.mask.take().unwrap();
            apply_mask(&mut self.payload, &mask);
            try!(w.write(&mask));
        }

        try!(w.write(&self.payload));
        Ok(())
    }
}

impl Default for Frame {
    fn default() -> Frame {
        Frame {
            finished: true,
            rsv1: false,
            rsv2: false,
            rsv3: false,
            opcode: OpCode::Close,
            mask: None,
            payload: Vec::new(),
        }
    }
}

impl fmt::Display for Frame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            "
<FRAME>
final: {}
reserved: {} {} {}
opcode: {}
length: {}
payload length: {}
payload: 0x{}
            ",
            self.finished,
            self.rsv1,
            self.rsv2,
            self.rsv3,
            self.opcode,
            // self.mask.map(|mask| format!("{:?}", mask)).unwrap_or("NONE".into()),
            self.len(),
            self.payload.len(),
            self.payload.iter().map(|byte| format!("{:x}", byte)).collect::<String>())
    }
}

mod test {
    #![allow(unused_imports, unused_variables, dead_code)]
    use super::*;
    use protocol::OpCode;

    #[test]
    fn display_frame() {
        let f = Frame::message("hi there".into(), OpCode::Text, true);
        let view = format!("{}", f);
        view.contains("payload:");
    }
}
<commit_msg>refactor(frame): Use byteorder to write frame length<commit_after>use std::fmt;
use std::io::{Cursor, Read, Write, ErrorKind};
use std::default::Default;

use rand;
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};

use result::{Result, Error, Kind};
use protocol::{OpCode, CloseCode};
use stream::TryReadBuf;

fn apply_mask(buf: &mut [u8], mask: &[u8; 4]) {
    let iter = buf.iter_mut().zip(mask.iter().cycle());
    for (byte, &key) in iter {
        *byte ^= key
    }
}

/// A struct representing a WebSocket frame.
#[derive(Debug, Clone)]
pub struct Frame {
    finished: bool,
    rsv1: bool,
    rsv2: bool,
    rsv3: bool,
    opcode: OpCode,

    mask: Option<[u8; 4]>,

    payload: Vec<u8>,
}

impl Frame {

    /// Get the length of the frame.
    /// This is the length of the header + the length of the payload.
    #[inline]
    pub fn len(&self) -> usize {
        let mut header_length = 2;
        let payload_len = self.payload().len();
        if payload_len > 125 {
            if payload_len <= u16::max_value() as usize {
                header_length += 2;
            } else {
                header_length += 8;
            }
        }

        if self.is_masked() {
            header_length += 4;
        }

        header_length + payload_len
    }

    /// Test whether the frame is a final frame.
    #[inline]
    pub fn is_final(&self) -> bool {
        self.finished
    }

    /// Test whether the first reserved bit is set.
    #[inline]
    pub fn has_rsv1(&self) -> bool {
        self.rsv1
    }

    /// Test whether the second reserved bit is set.
    #[inline]
    pub fn has_rsv2(&self) -> bool {
        self.rsv2
    }

    /// Test whether the third reserved bit is set.
    #[inline]
    pub fn has_rsv3(&self) -> bool {
        self.rsv3
    }

    /// Get the OpCode of the frame.
    #[inline]
    pub fn opcode(&self) -> OpCode {
        self.opcode
    }

    /// Test whether this is a control frame.
    #[inline]
    pub fn is_control(&self) -> bool {
        self.opcode.is_control()
    }

    /// Get a reference to the frame's payload.
    #[inline]
    pub fn payload(&self) -> &Vec<u8> {
        &self.payload
    }

    // Test whether the frame is masked.
    #[doc(hidden)]
    #[inline]
    pub fn is_masked(&self) -> bool {
        self.mask.is_some()
    }

    // Get an optional reference to the frame's mask.
    #[doc(hidden)]
    #[allow(dead_code)]
    #[inline]
    pub fn mask(&self) -> Option<&[u8; 4]> {
        self.mask.as_ref()
    }

    /// Make this frame a final frame.
    #[allow(dead_code)]
    #[inline]
    pub fn set_final(&mut self, is_final: bool) -> &mut Frame {
        self.finished = is_final;
        self
    }

    /// Set the first reserved bit.
    #[inline]
    pub fn set_rsv1(&mut self, has_rsv1: bool) -> &mut Frame {
        self.rsv1 = has_rsv1;
        self
    }

    /// Set the second reserved bit.
    #[inline]
    pub fn set_rsv2(&mut self, has_rsv2: bool) -> &mut Frame {
        self.rsv2 = has_rsv2;
        self
    }

    /// Set the third reserved bit.
    #[inline]
    pub fn set_rsv3(&mut self, has_rsv3: bool) -> &mut Frame {
        self.rsv3 = has_rsv3;
        self
    }

    /// Set the OpCode.
    #[allow(dead_code)]
    #[inline]
    pub fn set_opcode(&mut self, opcode: OpCode) -> &mut Frame {
        self.opcode = opcode;
        self
    }

    /// Edit the frame's payload.
    #[allow(dead_code)]
    #[inline]
    pub fn payload_mut(&mut self) -> &mut Vec<u8> {
        &mut self.payload
    }

    // Generate a new mask for this frame.
    //
    // This method simply generates and stores the mask. It does not change the payload data.
    // Instead, the payload data will be masked with the generated mask when the frame is sent
    // to the other endpoint.
    #[doc(hidden)]
    #[inline]
    pub fn set_mask(&mut self) -> &mut Frame {
        self.mask = Some(rand::random());
        self
    }

    // This method unmasks the payload and should only be called on frames that are actually
    // masked. In other words, those frames that have just been received from a client endpoint.
    #[doc(hidden)]
    #[inline]
    pub fn remove_mask(&mut self) -> &mut Frame {
        self.mask.and_then(|mask| {
            Some(apply_mask(&mut self.payload, &mask))
        });
        self.mask = None;
        self
    }

    /// Consume the frame into its payload.
    pub fn into_data(self) -> Vec<u8> {
        self.payload
    }

    /// Create a new data frame.
    #[inline]
    pub fn message(data: Vec<u8>, code: OpCode, finished: bool) -> Frame {
        debug_assert!(match code {
            OpCode::Text | OpCode::Binary | OpCode::Continue => true,
            _ => false,
        }, "Invalid opcode for data frame.");

        Frame {
            finished: finished,
            opcode: code,
            payload: data,
            .. Frame::default()
        }
    }

    /// Create a new Pong control frame.
    #[inline]
    pub fn pong(data: Vec<u8>) -> Frame {
        Frame {
            opcode: OpCode::Pong,
            payload: data,
            .. Frame::default()
        }
    }

    /// Create a new Ping control frame.
    #[inline]
    pub fn ping(data: Vec<u8>) -> Frame {
        Frame {
            opcode: OpCode::Ping,
            payload: data,
            .. Frame::default()
        }
    }

    /// Create a new Close control frame.
    #[inline]
    pub fn close(code: CloseCode, reason: &str) -> Frame {
        let payload = if let CloseCode::Empty = code {
            Vec::new()
        } else {
            let u: u16 = code.into();
            let raw = [(u >> 8) as u8, u as u8];
            [&raw, reason.as_bytes()].concat()
        };

        Frame {
            payload: payload,
            .. Frame::default()
        }
    }

    /// Parse the input stream into a frame.
    pub fn parse(cursor: &mut Cursor<Vec<u8>>) -> Result<Option<Frame>> {
        let size = cursor.get_ref().len() as u64 - cursor.position();
        let initial = cursor.position();
        trace!("Position in buffer {}", initial);

        let mut head = [0u8; 2];
        if try!(cursor.read(&mut head)) != 2 {
            cursor.set_position(initial);
            return Ok(None)
        }

        trace!("Parsed headers {:?}", head);

        let first = head[0];
        let second = head[1];
        trace!("First: {:b}", first);
        trace!("Second: {:b}", second);

        let finished = first & 0x80 != 0;

        let rsv1 = first & 0x40 != 0;
        let rsv2 = first & 0x20 != 0;
        let rsv3 = first & 0x10 != 0;

        let opcode = OpCode::from(first & 0x0F);
        trace!("Opcode: {:?}", opcode);

        let masked = second & 0x80 != 0;
        trace!("Masked: {:?}", masked);

        let mut header_length = 2;

        let mut length = (second & 0x7F) as u64;

        if let Some(length_nbytes) = match length {
            126 => Some(2),
            127 => Some(8),
            _ => None,
        } {
            match cursor.read_uint::<BigEndian>(length_nbytes) {
                Err(ref err) if err.kind() == ErrorKind::UnexpectedEof => {
                    cursor.set_position(initial);
                    return Ok(None);
                }
                Err(err) => {
                    return Err(Error::from(err));
                }
                Ok(read) => {
                    length = read;
                }
            };
            header_length += length_nbytes as u64;
        }
        trace!("Payload length: {}", length);

        let mask = if masked {
            let mut mask_bytes = [0u8; 4];
            if try!(cursor.read(&mut mask_bytes)) != 4 {
                cursor.set_position(initial);
                return Ok(None)
            } else {
                header_length += 4;
                Some(mask_bytes)
            }
        } else {
            None
        };

        if size < length + header_length {
            cursor.set_position(initial);
            return Ok(None)
        }

        let mut data = Vec::with_capacity(length as usize);
        if length > 0 {
            if let Some(read) = try!(cursor.try_read_buf(&mut data)) {
                debug_assert!(read == length as usize, "Read incorrect payload length!");
            }
        }

        // Disallow bad opcode
        if let OpCode::Bad = opcode {
            return Err(Error::new(Kind::Protocol, format!("Encountered invalid opcode: {}", first & 0x0F)))
        }

        // control frames must have length <= 125
        match opcode {
            OpCode::Ping | OpCode::Pong if length > 125 => {
                return Err(Error::new(Kind::Protocol, format!("Rejected WebSocket handshake.Received control frame with length: {}.", length)))
            }
            OpCode::Close if length > 125 => {
                debug!("Received close frame with payload length exceeding 125. Morphing to protocol close frame.");
                return Ok(Some(Frame::close(CloseCode::Protocol, "Received close frame with payload length exceeding 125.")))
            }
            _ => ()
        }

        let frame = Frame {
            finished: finished,
            rsv1: rsv1,
            rsv2: rsv2,
            rsv3: rsv3,
            opcode: opcode,
            mask: mask,
            payload: data,
        };

        Ok(Some(frame))
    }

    /// Write a frame out to a buffer
    pub fn format<W>(&mut self, w: &mut W) -> Result<()>
        where W: Write
    {
        let mut one = 0u8;
        let code: u8 = self.opcode.into();
        if self.is_final() {
            one |= 0x80;
        }
        if self.has_rsv1() {
            one |= 0x40;
        }
        if self.has_rsv2() {
            one |= 0x20;
        }
        if self.has_rsv3() {
            one |= 0x10;
        }
        one |= code;

        let mut two = 0u8;
        if self.is_masked() {
            two |= 0x80;
        }

        match self.payload.len() {
            len if len < 126 => {
                two |= len as u8;
            }
            len if len <= 65535 => {
                two |= 126;
            }
            _ => {
                two |= 127;
            }
        }
        try!(w.write(&[one, two]));

        if let Some(length_bytes) = match self.payload.len() {
            len if len < 126 => None,
            len if len <= 65535 => Some(2),
            _ => Some(8),
        } {
            try!(w.write_uint::<BigEndian>(self.payload.len() as u64, length_bytes));
        }

        if self.is_masked() {
            let mask = self.mask.take().unwrap();
            apply_mask(&mut self.payload, &mask);
            try!(w.write(&mask));
        }

        try!(w.write(&self.payload));
        Ok(())
    }
}

impl Default for Frame {
    fn default() -> Frame {
        Frame {
            finished: true,
            rsv1: false,
            rsv2: false,
            rsv3: false,
            opcode: OpCode::Close,
            mask: None,
            payload: Vec::new(),
        }
    }
}

impl fmt::Display for Frame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
            "
<FRAME>
final: {}
reserved: {} {} {}
opcode: {}
length: {}
payload length: {}
payload: 0x{}
            ",
            self.finished,
            self.rsv1,
            self.rsv2,
            self.rsv3,
            self.opcode,
            // self.mask.map(|mask| format!("{:?}", mask)).unwrap_or("NONE".into()),
            self.len(),
            self.payload.len(),
            self.payload.iter().map(|byte| format!("{:x}", byte)).collect::<String>())
    }
}

mod test {
    #![allow(unused_imports, unused_variables, dead_code)]
    use super::*;
    use protocol::OpCode;

    #[test]
    fn display_frame() {
        let f = Frame::message("hi there".into(), OpCode::Text, true);
        let view = format!("{}", f);
        view.contains("payload:");
    }
}
<|endoftext|>