<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{HashValue, Transaction, U64};
use poem_openapi::Object;
use serde::{Deserialize, Serialize};

// TODO: Consider including this in the API.
// If we do that, change these u64s to U64.

#[derive(Debug, Clone, Serialize, Deserialize, Object)]
pub struct Block {
    pub block_height: U64,
    pub block_hash: HashValue,
    pub block_timestamp: U64,
    pub first_version: U64,
    pub last_version: U64,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transactions: Option<Vec<Transaction>>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Object)]
pub struct BcsBlock {
    pub block_height: U64,
    pub block_hash: HashValue,
    pub block_timestamp: U64,
    pub first_version: U64,
    pub last_version: U64,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transactions: Option<Vec<Transaction>>,
}
<commit_msg>[api] Add BCS type for block output<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{HashValue, Transaction, TransactionOnChainData, U64};
use poem_openapi::Object;
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Serialize, Deserialize, Object)]
pub struct Block {
    pub block_height: U64,
    pub block_hash: HashValue,
    pub block_timestamp: U64,
    pub first_version: U64,
    pub last_version: U64,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transactions: Option<Vec<Transaction>>,
}

#[derive(Debug, Clone, Serialize, Deserialize, Object)]
pub struct BcsBlock {
    pub block_height: u64,
    pub block_hash: aptos_crypto::HashValue,
    pub block_timestamp: u64,
    pub first_version: u64,
    pub last_version: u64,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub transactions: Option<Vec<TransactionOnChainData>>,
}
<|endoftext|>


<commit_before>//! Provides drilldown related procedures.
//! This module will be used with `SelectCommand` type by `+` operation
//! to concatinate `select` and `drilldown` queries.
//!
//! Also this module support `pseudo_table` and `staged_columns` manupilation.
pub mod drilldown;
pub mod labeled_drilldown;
pub mod drilldownable;
pub mod labeled_drilldownable;
pub mod labeled_drilldown_sequencable;
pub mod drilldown_builder;
pub mod labeled_drilldown_builder;
pub mod labeled_drilldown_sequence_builder;
/// `fragmentable` module provides making query fragment operation.
/// It is useful to make composable query elements.
/// It makes `select` query to be composable against drilldown related query and `staged_columns` query.
pub mod fragmentable;
/// `pseudo_table` is used for tablable state which is appeared in "drilldown in drilldown".
pub mod pseudo_table;
pub mod staged_columns;
pub mod staged_columns_builder;
pub mod staged_columnable;
<commit_msg>rustdoc: Use `trait` to make more clarify<commit_after>//! Provides drilldown related procedures.
//! This module will be used with `SelectCommand` type by `+` operation
//! to concatinate `select` and `drilldown` queries.
//!
//! Also this module support `pseudo_table` and `staged_columns` manupilation.
pub mod drilldown;
pub mod labeled_drilldown;
pub mod drilldownable;
pub mod labeled_drilldownable;
pub mod labeled_drilldown_sequencable;
pub mod drilldown_builder;
pub mod labeled_drilldown_builder;
pub mod labeled_drilldown_sequence_builder;
/// `fragmentable` module provides making query fragment operation.
/// It is useful to make composable query elements.
/// It makes `select` query to be composable against drilldown related query and `staged_columns` query.
pub mod fragmentable;
/// `pseudo_table` is a trait to be used for tablable state which is appeared in "drilldown in drilldown".
pub mod pseudo_table;
pub mod staged_columns;
pub mod staged_columns_builder;
pub mod staged_columnable;
<|endoftext|>


<commit_before>use std::result;
use std::str;
use std::str::FromStr;
use std::fmt;
use std::iter::FromIterator;
use std::collections::HashSet;

use req_resp::RequestOrResponse;

use result::Result;
use error::Error;

use assert_types::*;

use bytes::Bytes;

#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub enum PseudoHeaderName {
    // 8.1.2.3 Request Pseudo-Header Fields
    Method,
    Scheme,
    Authority,
    Path,

    // 8.1.2.4 Response Pseudo-Header Fields
    Status,
}

impl PseudoHeaderName {
    pub fn name(&self) -> &'static str {
        match *self {
            PseudoHeaderName::Method =>    ":method",
            PseudoHeaderName::Scheme =>    ":scheme",
            PseudoHeaderName::Authority => ":authority",
            PseudoHeaderName::Path =>      ":path",
            PseudoHeaderName::Status =>    ":status",
        }
    }

    pub fn parse(value: &[u8]) -> Result<PseudoHeaderName> {
        match value {
            b":method"    => Ok(PseudoHeaderName::Method),
            b":scheme"    => Ok(PseudoHeaderName::Scheme),
            b":authority" => Ok(PseudoHeaderName::Authority),
            b":path"      => Ok(PseudoHeaderName::Path),
            b":status"    => Ok(PseudoHeaderName::Status),
            _             => Err(Error::Other("invalid pseudo header")),
        }
    }

    pub fn req_or_resp(&self) -> RequestOrResponse {
        match *self {
            PseudoHeaderName::Method    => RequestOrResponse::Request,
            PseudoHeaderName::Scheme    => RequestOrResponse::Request,
            PseudoHeaderName::Authority => RequestOrResponse::Request,
            PseudoHeaderName::Path      => RequestOrResponse::Request,
            PseudoHeaderName::Status    => RequestOrResponse::Response,
        }
    }

    pub fn name_bytes(&self) -> Bytes {
        Bytes::from_static(self.name().as_bytes())
    }

    pub fn names(request_or_response: RequestOrResponse) -> &'static [PseudoHeaderName] {
        static REQUEST_HEADERS: &[PseudoHeaderName] = &[
            PseudoHeaderName::Method,
            PseudoHeaderName::Scheme,
            PseudoHeaderName::Authority,
            PseudoHeaderName::Path,
        ];
        static RESPONSE_HEADERS: &[PseudoHeaderName] = &[
            PseudoHeaderName::Status,
        ];
        match request_or_response {
            RequestOrResponse::Request => REQUEST_HEADERS,
            RequestOrResponse::Response => RESPONSE_HEADERS,
        }
    }

    pub fn all_names() -> &'static [PseudoHeaderName] {
        static ALL_HEADERS: &[PseudoHeaderName] = &[
            PseudoHeaderName::Method,
            PseudoHeaderName::Scheme,
            PseudoHeaderName::Authority,
            PseudoHeaderName::Path,
            PseudoHeaderName::Status,
        ];
        ALL_HEADERS
    }
}

#[allow(dead_code)]
pub struct HeaderName(Bytes);

impl<'a> From<&'a str> for HeaderName {
    fn from(_name: &'a str) -> HeaderName {
        unimplemented!()
    }
}

/// A convenience struct representing a part of a header (either the name or the value).
pub struct HeaderPart(Bytes);

impl fmt::Debug for HeaderPart {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<Vec<u8>> for HeaderPart {
    fn from(vec: Vec<u8>) -> HeaderPart {
        HeaderPart(Bytes::from(vec))
    }
}

impl From<Bytes> for HeaderPart {
    fn from(bytes: Bytes) -> HeaderPart {
        HeaderPart(bytes)
    }
}

impl<'a> From<&'a [u8]> for HeaderPart {
    fn from(buf: &'a [u8]) -> HeaderPart {
        HeaderPart(Bytes::from(buf))
    }
}

macro_rules! from_static_size_array {
    ($N:expr) => (
        impl<'a> From<&'a [u8; $N]> for HeaderPart {
            fn from(buf: &'a [u8; $N]) -> HeaderPart {
                buf[..].into()
            }
        }
    );
}

macro_rules! impl_from_static_size_array {
    ($($N:expr,)+) => {
        $(
            from_static_size_array!($N);
        )+
    }
}

impl_from_static_size_array!(
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
);

impl From<String> for HeaderPart {
    fn from(s: String) -> HeaderPart {
        From::from(s.into_bytes())
    }
}

impl<'a> From<&'a str> for HeaderPart {
    fn from(s: &'a str) -> HeaderPart {
        From::from(s.as_bytes())
    }
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Header {
    pub name: Bytes,
    pub value: Bytes,
}

fn _assert_header_sync_send() {
    assert_sync::<Header>();
    assert_send::<Header>();
}

#[derive(Debug)]
pub enum HeaderError {
    UnknownPseudoHeader,
    EmptyName,
    EmptyValue(PseudoHeaderName),
    IncorrectCharInName,
    UnexpectedPseudoHeader(PseudoHeaderName),
    PseudoHeadersNotInFirstHeaders,
    PseudoHeadersAfterRegularHeaders,
    MoreThanOnePseudoHeader(PseudoHeaderName),
    MissingPseudoHeader(PseudoHeaderName),
}

pub type HeaderResult<T> = result::Result<T, HeaderError>;

impl Header {
    /// Creates a new `Header` with the given name and value.
    ///
    /// The name and value need to be convertible into a `HeaderPart`.
    pub fn new<N: Into<HeaderPart>, V: Into<HeaderPart>>(name: N,
                                                                 value: V)
                                                                 -> Header {
        Header {
            name: name.into().0,
            value: value.into().0,
        }
    }

    /// Return a borrowed representation of the `Header` name.
    pub fn name(&self) -> &[u8] {
        &self.name
    }
    /// Return a borrowed representation of the `Header` value.
    pub fn value(&self) -> &[u8] {
        &self.value
    }

    /// name: value
    pub fn format(&self) -> String {
        format!("{}: {}", String::from_utf8_lossy(&self.name), String::from_utf8_lossy(&self.value))
    }

    pub fn is_preudo_header(&self) -> bool {
        self.name.len() != 0 && self.name[0] == b':'
    }

    pub fn pseudo_header_name(&self) -> HeaderResult<Option<PseudoHeaderName>> {
        if self.is_preudo_header() {
            for &h in PseudoHeaderName::all_names() {
                if self.name.as_ref() == h.name().as_bytes() {
                    return Ok(Some(h));
                }
            }
            Err(HeaderError::UnknownPseudoHeader)
        } else {
            Ok(None)
        }
    }

    fn validate_header_name_char(b: u8) -> HeaderResult<()> {
        // TODO: restrict more
        if b >= b'A' && b <= b'Z' {
            return Err(HeaderError::IncorrectCharInName);
        }
        Ok(())
    }

    pub fn validate(&self, req_or_resp: RequestOrResponse) -> HeaderResult<()> {
        if self.name.len() == 0 {
            return Err(HeaderError::EmptyName);
        }

        if let Some(h) = self.pseudo_header_name()? {
            if h.req_or_resp() != req_or_resp {
                return Err(HeaderError::UnexpectedPseudoHeader(h));
            }
        }

        for c in &self.name {
            Header::validate_header_name_char(c)?;
        }

        Ok(())
    }
}

impl<N: Into<HeaderPart>, V: Into<HeaderPart>> From<(N, V)> for Header {
    fn from(p: (N, V)) -> Header {
        Header::new(p.0, p.1)
    }
}

#[derive(Default, Debug, PartialEq, Eq, Clone)]
pub struct Headers(pub Vec<Header>);

impl Headers {
    pub fn new() -> Headers {
        Default::default()
    }

    /// Multiline string
    pub fn dump(&self) -> String {
        let mut r = String::new();
        for h in &self.0 {
            r.push_str(&h.format());
            r.push_str("\n");
        }
        r
    }

    pub fn new_get(path: &str) -> Headers {
        Headers(vec![
            Header::new(":method", "GET"),
            Header::new(":path", path),
        ])
    }

    pub fn new_post(path: &str) -> Headers {
        Headers(vec![
            Header::new(":method", "POST"),
            Header::new(":path", path),
        ])
    }

    pub fn from_status(code: u32) -> Headers {
        Headers(vec![
            Header::new(":status", format!("{}", code)),
        ])
    }

    pub fn ok_200() -> Headers {
        Headers::from_status(200)
    }

    pub fn not_found_404() -> Headers {
        Headers::from_status(404)
    }

    pub fn internal_error_500() -> Headers {
        Headers::from_status(500)
    }

    pub fn contains_preudo_headers(&self) -> bool {
        self.0.iter().any(|h| h.is_preudo_header())
    }

    pub fn validate(&self, req_or_resp: RequestOrResponse, first: bool)
        -> HeaderResult<()>
    {
        let mut saw_regular_header = false;

        // TODO: array is enough
        let mut pseudo_headers_met = HashSet::new();

        for header in &self.0 {
            header.validate(req_or_resp)?;

            // 8.1.2.1.  Pseudo-Header Fields
            // All pseudo-header fields MUST appear in the header block before
            // regular header fields.  Any request or response that contains a
            // pseudo-header field that appears in a header block after a regular
            // header field MUST be treated as malformed (Section 8.1.2.6).
            if let Some(header_name) = header.pseudo_header_name()? {
                if !first {
                    return Err(HeaderError::PseudoHeadersNotInFirstHeaders);
                }

                if saw_regular_header {
                    return Err(HeaderError::PseudoHeadersAfterRegularHeaders);
                }

                if !pseudo_headers_met.insert(header_name) {
                    return Err(HeaderError::MoreThanOnePseudoHeader(header_name));
                }

                if header_name == PseudoHeaderName::Path {
                    if header.value.is_empty() {
                        return Err(HeaderError::EmptyValue(header_name));
                    }
                }
            } else {
                saw_regular_header = true;
            }
        }

        if first {
            match req_or_resp {
                // All HTTP/2 requests MUST include exactly one valid value for the
                // ":method", ":scheme", and ":path" pseudo-header fields, unless it is
                // a CONNECT request (Section 8.3).  An HTTP request that omits
                // mandatory pseudo-header fields is malformed (Section 8.1.2.6).
                RequestOrResponse::Request => {
                    let required_headers = [
                        PseudoHeaderName::Method,
                        PseudoHeaderName::Scheme,
                        PseudoHeaderName::Path,
                    ];
                    for required in &required_headers {
                        if pseudo_headers_met.get(required).is_none() {
                            return Err(HeaderError::MissingPseudoHeader(*required));
                        }
                    }
                }
                // For HTTP/2 responses, a single ":status" pseudo-header field is
                // defined that carries the HTTP status code field (see [RFC7231],
                // Section 6).  This pseudo-header field MUST be included in all
                // responses; otherwise, the response is malformed (Section 8.1.2.6).
                RequestOrResponse::Response => {
                    let required = PseudoHeaderName::Status;
                    if pseudo_headers_met.get(&required).is_none() {
                        return Err(HeaderError::MissingPseudoHeader(required));
                    }
                }
            }
        }

        Ok(())
    }

    pub fn get_opt<'a>(&'a self, name: &str) -> Option<&'a str> {
        self.0.iter()
            .find(|h| h.name() == name.as_bytes())
            .and_then(|h| str::from_utf8(h.value()).ok())
    }

    pub fn get<'a>(&'a self, name: &str) -> &'a str {
        self.get_opt(name).unwrap()
    }

    pub fn get_opt_parse<I : FromStr>(&self, name: &str) -> Option<I> {
        self.get_opt(name)
            .and_then(|h| h.parse().ok())
    }

    pub fn status(&self) -> u32 {
        self.get_opt_parse(":status").unwrap()
    }

    pub fn path(&self) -> &str {
        self.get(":path")
    }

    pub fn method(&self) -> &str {
        self.get(":method")
    }

    pub fn content_length(&self) -> Option<u64> {
        match self.get_opt("content-length") {
            Some(v) => v.parse().ok(),
            None => None,
        }
    }

    pub fn add(&mut self, name: &str, value: &str) {
        self.0.push(Header::new(name, value));
    }

    pub fn extend(&mut self, headers: Headers) {
        self.0.extend(headers.0);
    }
}

impl FromIterator<Header> for Headers {
    fn from_iter<T : IntoIterator<Item=Header>>(iter: T) -> Headers {
        Headers(iter.into_iter().collect())
    }
}

#[cfg(test)]
mod test {
    use solicit::header::Header;

    #[test]
    fn test_partial_eq_of_headers() {
        let fully_static = Header::new(b":method", b"GET");
        let static_name = Header::new(b":method", b"GET".to_vec());
        let other = Header::new(b":path", b"/");

        assert!(fully_static == static_name);
        assert!(fully_static != other);
        assert!(static_name != other);
    }

    #[test]
    fn test_debug() {
        assert_eq!(
            "Header { name: b\":method\", value: b\"GET\" }",
            format!("{:?}", Header::new(b":method", b"GET")));
        assert_eq!(
            "Header { name: b\":method\", value: b\"\\xcd\" }",
            format!("{:?}", Header::new(b":method", b"\xcd")));
    }
}
<commit_msg>Fix h2spec test http2/8.1.2.2/1<commit_after>use std::result;
use std::str;
use std::str::FromStr;
use std::fmt;
use std::iter::FromIterator;
use std::collections::HashSet;

use req_resp::RequestOrResponse;

use result::Result;
use error::Error;

use assert_types::*;

use bytes::Bytes;

#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub enum PseudoHeaderName {
    // 8.1.2.3 Request Pseudo-Header Fields
    Method,
    Scheme,
    Authority,
    Path,

    // 8.1.2.4 Response Pseudo-Header Fields
    Status,
}

impl PseudoHeaderName {
    pub fn name(&self) -> &'static str {
        match *self {
            PseudoHeaderName::Method =>    ":method",
            PseudoHeaderName::Scheme =>    ":scheme",
            PseudoHeaderName::Authority => ":authority",
            PseudoHeaderName::Path =>      ":path",
            PseudoHeaderName::Status =>    ":status",
        }
    }

    pub fn parse(value: &[u8]) -> Result<PseudoHeaderName> {
        match value {
            b":method"    => Ok(PseudoHeaderName::Method),
            b":scheme"    => Ok(PseudoHeaderName::Scheme),
            b":authority" => Ok(PseudoHeaderName::Authority),
            b":path"      => Ok(PseudoHeaderName::Path),
            b":status"    => Ok(PseudoHeaderName::Status),
            _             => Err(Error::Other("invalid pseudo header")),
        }
    }

    pub fn req_or_resp(&self) -> RequestOrResponse {
        match *self {
            PseudoHeaderName::Method    => RequestOrResponse::Request,
            PseudoHeaderName::Scheme    => RequestOrResponse::Request,
            PseudoHeaderName::Authority => RequestOrResponse::Request,
            PseudoHeaderName::Path      => RequestOrResponse::Request,
            PseudoHeaderName::Status    => RequestOrResponse::Response,
        }
    }

    pub fn name_bytes(&self) -> Bytes {
        Bytes::from_static(self.name().as_bytes())
    }

    pub fn names(request_or_response: RequestOrResponse) -> &'static [PseudoHeaderName] {
        static REQUEST_HEADERS: &[PseudoHeaderName] = &[
            PseudoHeaderName::Method,
            PseudoHeaderName::Scheme,
            PseudoHeaderName::Authority,
            PseudoHeaderName::Path,
        ];
        static RESPONSE_HEADERS: &[PseudoHeaderName] = &[
            PseudoHeaderName::Status,
        ];
        match request_or_response {
            RequestOrResponse::Request => REQUEST_HEADERS,
            RequestOrResponse::Response => RESPONSE_HEADERS,
        }
    }

    pub fn all_names() -> &'static [PseudoHeaderName] {
        static ALL_HEADERS: &[PseudoHeaderName] = &[
            PseudoHeaderName::Method,
            PseudoHeaderName::Scheme,
            PseudoHeaderName::Authority,
            PseudoHeaderName::Path,
            PseudoHeaderName::Status,
        ];
        ALL_HEADERS
    }
}

#[allow(dead_code)]
pub struct HeaderName(Bytes);

impl<'a> From<&'a str> for HeaderName {
    fn from(_name: &'a str) -> HeaderName {
        unimplemented!()
    }
}

/// A convenience struct representing a part of a header (either the name or the value).
pub struct HeaderPart(Bytes);

impl fmt::Debug for HeaderPart {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<Vec<u8>> for HeaderPart {
    fn from(vec: Vec<u8>) -> HeaderPart {
        HeaderPart(Bytes::from(vec))
    }
}

impl From<Bytes> for HeaderPart {
    fn from(bytes: Bytes) -> HeaderPart {
        HeaderPart(bytes)
    }
}

impl<'a> From<&'a [u8]> for HeaderPart {
    fn from(buf: &'a [u8]) -> HeaderPart {
        HeaderPart(Bytes::from(buf))
    }
}

macro_rules! from_static_size_array {
    ($N:expr) => (
        impl<'a> From<&'a [u8; $N]> for HeaderPart {
            fn from(buf: &'a [u8; $N]) -> HeaderPart {
                buf[..].into()
            }
        }
    );
}

macro_rules! impl_from_static_size_array {
    ($($N:expr,)+) => {
        $(
            from_static_size_array!($N);
        )+
    }
}

impl_from_static_size_array!(
    0,
    1,
    2,
    3,
    4,
    5,
    6,
    7,
    8,
    9,
    10,
    11,
    12,
    13,
    14,
    15,
    16,
    17,
    18,
    19,
    20,
    21,
    22,
    23,
);

impl From<String> for HeaderPart {
    fn from(s: String) -> HeaderPart {
        From::from(s.into_bytes())
    }
}

impl<'a> From<&'a str> for HeaderPart {
    fn from(s: &'a str) -> HeaderPart {
        From::from(s.as_bytes())
    }
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Header {
    pub name: Bytes,
    pub value: Bytes,
}

fn _assert_header_sync_send() {
    assert_sync::<Header>();
    assert_send::<Header>();
}

#[derive(Debug)]
pub enum HeaderError {
    UnknownPseudoHeader,
    EmptyName,
    EmptyValue(PseudoHeaderName),
    IncorrectCharInName,
    UnexpectedPseudoHeader(PseudoHeaderName),
    PseudoHeadersNotInFirstHeaders,
    PseudoHeadersAfterRegularHeaders,
    MoreThanOnePseudoHeader(PseudoHeaderName),
    MissingPseudoHeader(PseudoHeaderName),
    ConnectionSpecificHeader(&'static str),
}

pub type HeaderResult<T> = result::Result<T, HeaderError>;

impl Header {
    /// Creates a new `Header` with the given name and value.
    ///
    /// The name and value need to be convertible into a `HeaderPart`.
    pub fn new<N: Into<HeaderPart>, V: Into<HeaderPart>>(name: N,
                                                                 value: V)
                                                                 -> Header {
        Header {
            name: name.into().0,
            value: value.into().0,
        }
    }

    /// Return a borrowed representation of the `Header` name.
    pub fn name(&self) -> &[u8] {
        &self.name
    }
    /// Return a borrowed representation of the `Header` value.
    pub fn value(&self) -> &[u8] {
        &self.value
    }

    /// name: value
    pub fn format(&self) -> String {
        format!("{}: {}", String::from_utf8_lossy(&self.name), String::from_utf8_lossy(&self.value))
    }

    pub fn is_preudo_header(&self) -> bool {
        self.name.len() != 0 && self.name[0] == b':'
    }

    pub fn pseudo_header_name(&self) -> HeaderResult<Option<PseudoHeaderName>> {
        if self.is_preudo_header() {
            for &h in PseudoHeaderName::all_names() {
                if self.name.as_ref() == h.name().as_bytes() {
                    return Ok(Some(h));
                }
            }
            Err(HeaderError::UnknownPseudoHeader)
        } else {
            Ok(None)
        }
    }

    fn validate_header_name_char(b: u8) -> HeaderResult<()> {
        // TODO: restrict more
        if b >= b'A' && b <= b'Z' {
            return Err(HeaderError::IncorrectCharInName);
        }
        Ok(())
    }

    pub fn validate(&self, req_or_resp: RequestOrResponse) -> HeaderResult<()> {
        if self.name.len() == 0 {
            return Err(HeaderError::EmptyName);
        }

        if let Some(h) = self.pseudo_header_name()? {
            if h.req_or_resp() != req_or_resp {
                return Err(HeaderError::UnexpectedPseudoHeader(h));
            }
        }

        for c in &self.name {
            Header::validate_header_name_char(c)?;
        }

        // HTTP/2 does not use the Connection header field to indicate
        // connection-specific header fields; in this protocol, connection-
        // specific metadata is conveyed by other means.  An endpoint MUST NOT
        // generate an HTTP/2 message containing connection-specific header
        // fields; any message containing connection-specific header fields MUST
        // be treated as malformed (Section 8.1.2.6).
        let connection_specific_headers = [
            "connection",
            "keep-alive",
            "proxy-connection",
            "transfer-encoding",
            "upgrade",
        ];
        for s in &connection_specific_headers {
            if self.name == s.as_bytes() {
                return Err(HeaderError::ConnectionSpecificHeader(s));
            }
        }

        Ok(())
    }
}

impl<N: Into<HeaderPart>, V: Into<HeaderPart>> From<(N, V)> for Header {
    fn from(p: (N, V)) -> Header {
        Header::new(p.0, p.1)
    }
}

#[derive(Default, Debug, PartialEq, Eq, Clone)]
pub struct Headers(pub Vec<Header>);

impl Headers {
    pub fn new() -> Headers {
        Default::default()
    }

    /// Multiline string
    pub fn dump(&self) -> String {
        let mut r = String::new();
        for h in &self.0 {
            r.push_str(&h.format());
            r.push_str("\n");
        }
        r
    }

    pub fn new_get(path: &str) -> Headers {
        Headers(vec![
            Header::new(":method", "GET"),
            Header::new(":path", path),
        ])
    }

    pub fn new_post(path: &str) -> Headers {
        Headers(vec![
            Header::new(":method", "POST"),
            Header::new(":path", path),
        ])
    }

    pub fn from_status(code: u32) -> Headers {
        Headers(vec![
            Header::new(":status", format!("{}", code)),
        ])
    }

    pub fn ok_200() -> Headers {
        Headers::from_status(200)
    }

    pub fn not_found_404() -> Headers {
        Headers::from_status(404)
    }

    pub fn internal_error_500() -> Headers {
        Headers::from_status(500)
    }

    pub fn contains_preudo_headers(&self) -> bool {
        self.0.iter().any(|h| h.is_preudo_header())
    }

    pub fn validate(&self, req_or_resp: RequestOrResponse, first: bool)
        -> HeaderResult<()>
    {
        let mut saw_regular_header = false;

        // TODO: array is enough
        let mut pseudo_headers_met = HashSet::new();

        for header in &self.0 {
            header.validate(req_or_resp)?;

            // 8.1.2.1.  Pseudo-Header Fields
            // All pseudo-header fields MUST appear in the header block before
            // regular header fields.  Any request or response that contains a
            // pseudo-header field that appears in a header block after a regular
            // header field MUST be treated as malformed (Section 8.1.2.6).
            if let Some(header_name) = header.pseudo_header_name()? {
                if !first {
                    return Err(HeaderError::PseudoHeadersNotInFirstHeaders);
                }

                if saw_regular_header {
                    return Err(HeaderError::PseudoHeadersAfterRegularHeaders);
                }

                if !pseudo_headers_met.insert(header_name) {
                    return Err(HeaderError::MoreThanOnePseudoHeader(header_name));
                }

                if header_name == PseudoHeaderName::Path {
                    if header.value.is_empty() {
                        return Err(HeaderError::EmptyValue(header_name));
                    }
                }
            } else {
                saw_regular_header = true;
            }
        }

        if first {
            match req_or_resp {
                // All HTTP/2 requests MUST include exactly one valid value for the
                // ":method", ":scheme", and ":path" pseudo-header fields, unless it is
                // a CONNECT request (Section 8.3).  An HTTP request that omits
                // mandatory pseudo-header fields is malformed (Section 8.1.2.6).
                RequestOrResponse::Request => {
                    let required_headers = [
                        PseudoHeaderName::Method,
                        PseudoHeaderName::Scheme,
                        PseudoHeaderName::Path,
                    ];
                    for required in &required_headers {
                        if pseudo_headers_met.get(required).is_none() {
                            return Err(HeaderError::MissingPseudoHeader(*required));
                        }
                    }
                }
                // For HTTP/2 responses, a single ":status" pseudo-header field is
                // defined that carries the HTTP status code field (see [RFC7231],
                // Section 6).  This pseudo-header field MUST be included in all
                // responses; otherwise, the response is malformed (Section 8.1.2.6).
                RequestOrResponse::Response => {
                    let required = PseudoHeaderName::Status;
                    if pseudo_headers_met.get(&required).is_none() {
                        return Err(HeaderError::MissingPseudoHeader(required));
                    }
                }
            }
        }

        Ok(())
    }

    pub fn get_opt<'a>(&'a self, name: &str) -> Option<&'a str> {
        self.0.iter()
            .find(|h| h.name() == name.as_bytes())
            .and_then(|h| str::from_utf8(h.value()).ok())
    }

    pub fn get<'a>(&'a self, name: &str) -> &'a str {
        self.get_opt(name).unwrap()
    }

    pub fn get_opt_parse<I : FromStr>(&self, name: &str) -> Option<I> {
        self.get_opt(name)
            .and_then(|h| h.parse().ok())
    }

    pub fn status(&self) -> u32 {
        self.get_opt_parse(":status").unwrap()
    }

    pub fn path(&self) -> &str {
        self.get(":path")
    }

    pub fn method(&self) -> &str {
        self.get(":method")
    }

    pub fn content_length(&self) -> Option<u64> {
        match self.get_opt("content-length") {
            Some(v) => v.parse().ok(),
            None => None,
        }
    }

    pub fn add(&mut self, name: &str, value: &str) {
        self.0.push(Header::new(name, value));
    }

    pub fn extend(&mut self, headers: Headers) {
        self.0.extend(headers.0);
    }
}

impl FromIterator<Header> for Headers {
    fn from_iter<T : IntoIterator<Item=Header>>(iter: T) -> Headers {
        Headers(iter.into_iter().collect())
    }
}

#[cfg(test)]
mod test {
    use solicit::header::Header;

    #[test]
    fn test_partial_eq_of_headers() {
        let fully_static = Header::new(b":method", b"GET");
        let static_name = Header::new(b":method", b"GET".to_vec());
        let other = Header::new(b":path", b"/");

        assert!(fully_static == static_name);
        assert!(fully_static != other);
        assert!(static_name != other);
    }

    #[test]
    fn test_debug() {
        assert_eq!(
            "Header { name: b\":method\", value: b\"GET\" }",
            format!("{:?}", Header::new(b":method", b"GET")));
        assert_eq!(
            "Header { name: b\":method\", value: b\"\\xcd\" }",
            format!("{:?}", Header::new(b":method", b"\xcd")));
    }
}
<|endoftext|>


<commit_before>use solitaire::card::*;

use std::cmp;

#[deriving(PartialEq, Show)]
pub struct Deck {
    pub d: Vec<Card>,
}

impl Iterator<uint> for Deck {
    fn next(&mut self) -> Option<uint> {
        Some(self.gen_keystream_letter())
    }
}

impl Deck {
    pub fn new() -> Deck {
        let per_suit = 13;
        let mut deck = Deck { d: Vec::new() };
        for i in range(0, per_suit) {
            deck.d.push(Clubs(i+1));
        }
        for i in range(0, per_suit) {
            deck.d.push(Diamonds(i+1));
        }
        for i in range(0, per_suit) {
            deck.d.push(Hearts(i+1));
        }
        for i in range(0, per_suit) {
            deck.d.push(Spades(i+1));
        }

        deck.d.push(JokerA);
        deck.d.push(JokerB);
        return deck;
    }

    pub fn gen_keystream_letter(&mut self) -> uint {
        self.move_joker(JokerA, 1);
        self.move_joker(JokerB, 2);
        self.triple_cut();
        let i = self.d.last().unwrap().count_index();
        self.count_cut(i);
        let i = self.d[0].count_index();
        let output_card = self.d[i];
        match output_card {
            Clubs(i) => i,
            Diamonds(i) => i + 13,
            Hearts(i) => i,
            Spades(i) => i + 13,
            _ => self.gen_keystream_letter(),
        }
    }

    pub fn move_joker(&mut self, j: Card, count: int) {
        let mut i = index_of(self.d.as_slice(), j).unwrap();
        for _ in range(0i, count) {
            if i < self.d.len()-1 {
                let temp = self.d[i];
                *self.d.get_mut(i) = self.d[i+1];
                *self.d.get_mut(i+1) = temp;
            } else {
                // if card is the last card in the deck, move below the first card of the deck
                // every card needs to be moved... maybe this should have been a linked list
                let mut new = Vec::with_capacity(self.d.len());
                new.push(self.d[0]);
                new.push(*self.d.last().unwrap());
                new.push_all(self.d.slice(1, self.d.len()-1));
                self.d = new;
            }
            i = if i != self.d.len()-1 {
                i + 1
            } else {
                1
            };
        }
    }

    pub fn triple_cut(&mut self) {
        let mut new = Vec::with_capacity(self.d.len());
        let ai = index_of(self.d.as_slice(), JokerA).unwrap();
        let bi = index_of(self.d.as_slice(), JokerB).unwrap();
        let first = cmp::min(ai, bi);
        let secnd = cmp::max(ai, bi);
        new.push_all(self.d.slice(secnd+1, self.d.len()));
        new.push_all(self.d.slice(first, secnd + 1));
        new.push_all(self.d.slice(0, first));
        self.d = new;
    }

    pub fn count_cut(&mut self, c: uint) {
        // cut after c
        let mut new = Vec::with_capacity(self.d.len());
        for i in range(c, self.d.len()) {
            new.push(self.d[i]);
        }

        for i in range(0, c) {
            new.push(self.d[i]);
        }
        self.d = new;
    }

}

fn index_of<T: PartialEq>(a: &[T], x: T) -> Option<uint> {
    match a.iter().enumerate().find(|&(_, q)| *q == x) {
        Some((i, _)) => Some(i),
        None => None,
    }
}

#[test]
fn new_deck() {
    let d = Deck::new();
    assert_eq!(d, Deck { d: vec![Clubs(1), Clubs(2), Clubs(3), Clubs(4), Clubs(5), Clubs(6), Clubs(7), Clubs(8), Clubs(9), Clubs(10), Clubs(11), Clubs(12), Clubs(13), Diamonds(1), Diamonds(2), Diamonds(3), Diamonds(4), Diamonds(5), Diamonds(6), Diamonds(7), Diamonds(8), Diamonds(9), Diamonds(10), Diamonds(11), Diamonds(12), Diamonds(13), Hearts(1), Hearts(2), Hearts(3), Hearts(4), Hearts(5), Hearts(6), Hearts(7), Hearts(8), Hearts(9), Hearts(10), Hearts(11), Hearts(12), Hearts(13), Spades(1), Spades(2), Spades(3), Spades(4), Spades(5), Spades(6), Spades(7), Spades(8), Spades(9), Spades(10), Spades(11), Spades(12), Spades(13), JokerA, JokerB] });
}

#[test]
fn move_joker() {
    let mut d = Deck{ d: vec![Clubs(1), Clubs(2), JokerA] };
    d.move_joker(JokerA, 1);
    assert_eq!(d.d, vec![Clubs(1), JokerA, Clubs(2)]);

    let mut d = Deck{ d: vec![Clubs(1), Clubs(2), Hearts(3), JokerA, JokerB] };
    d.move_joker(JokerA, 1);
    d.move_joker(JokerB, 2);
    assert_eq!(d.d, vec![Clubs(1), JokerB, Clubs(2), Hearts(3), JokerA]);
}

#[test]
fn triple_cut() {
    let tests = vec![
        (vec![Clubs(1), JokerA, Clubs(2), JokerB, Clubs(3)], vec![Clubs(3), JokerA, Clubs(2), JokerB, Clubs(1)]),
        (vec![Clubs(1), Hearts(1), JokerA, Clubs(2), JokerB, Clubs(3), Hearts(3)], vec![Clubs(3), Hearts(3), JokerA, Clubs(2), JokerB, Clubs(1), Hearts(1)]),
        (vec![JokerA, JokerB], vec![JokerA, JokerB]),
        ];

    for test in tests.iter() {
        let (initial, expect) = test.clone();
        let mut got = Deck{ d: initial };
        got.triple_cut();
        assert_eq!(got.d, expect);
    }
}

#[test]
fn gen_keystream_letter() {
    let mut d = Deck::new();

    assert_eq!(d.gen_keystream_letter(), 4);
}
<commit_msg>Fix things that are in stdlib<commit_after>use solitaire::card::*;

use std::cmp;
use std::iter::range_inclusive;

#[deriving(PartialEq, Show)]
pub struct Deck {
    pub d: Vec<Card>,
}

impl Iterator<uint> for Deck {
    fn next(&mut self) -> Option<uint> {
        Some(self.gen_keystream_letter())
    }
}

impl Deck {
    pub fn new() -> Deck {
        let per_suit = 13;
        let mut deck = Deck { d: Vec::new() };
        for i in range_inclusive(1, per_suit) {
            deck.d.push(Clubs(i));
        }
        for i in range_inclusive(1, per_suit) {
            deck.d.push(Diamonds(i));
        }
        for i in range_inclusive(1, per_suit) {
            deck.d.push(Hearts(i));
        }
        for i in range_inclusive(1, per_suit) {
            deck.d.push(Spades(i));
        }

        deck.d.push(JokerA);
        deck.d.push(JokerB);
        return deck;
    }

    pub fn gen_keystream_letter(&mut self) -> uint {
        self.move_joker(JokerA, 1);
        self.move_joker(JokerB, 2);
        self.triple_cut();
        let i = self.d.last().unwrap().count_index();
        self.count_cut(i);
        let i = self.d[0].count_index();
        let output_card = self.d[i];
        match output_card {
            Clubs(i) => i,
            Diamonds(i) => i + 13,
            Hearts(i) => i,
            Spades(i) => i + 13,
            _ => self.gen_keystream_letter(),
        }
    }

    pub fn move_joker(&mut self, j: Card, count: int) {
        let mut i = self.d.as_slice().position_elem(&j).unwrap();
        for _ in range(0i, count) {
            if i < self.d.len()-1 {
                self.d.as_mut_slice().swap(i, i+1);
            } else {
                // if card is the last card in the deck, move below the first card of the deck
                // every card needs to be moved... maybe this should have been a linked list
                let mut new = Vec::with_capacity(self.d.len());
                new.push(self.d[0]);
                new.push(*self.d.last().unwrap());
                new.push_all(self.d.slice(1, self.d.len()-1));
                self.d = new;
            }
            i = if i != self.d.len()-1 {
                i + 1
            } else {
                1
            };
        }
    }

    pub fn triple_cut(&mut self) {
        let mut new = Vec::with_capacity(self.d.len());
        let ai = self.d.as_slice().position_elem(&JokerA).unwrap();
        let bi = self.d.as_slice().position_elem(&JokerB).unwrap();
        let first = cmp::min(ai, bi);
        let secnd = cmp::max(ai, bi);
        new.push_all(self.d.slice(secnd+1, self.d.len()));
        new.push_all(self.d.slice(first, secnd + 1));
        new.push_all(self.d.slice(0, first));
        self.d = new;
    }

    pub fn count_cut(&mut self, c: uint) {
        // cut after c
        let mut new = Vec::with_capacity(self.d.len());
        for i in range(c, self.d.len()) {
            new.push(self.d[i]);
        }

        for i in range(0, c) {
            new.push(self.d[i]);
        }
        self.d = new;
    }

}

#[test]
fn new_deck() {
    let d = Deck::new();
    assert_eq!(d, Deck { d: vec![Clubs(1), Clubs(2), Clubs(3), Clubs(4), Clubs(5), Clubs(6), Clubs(7), Clubs(8), Clubs(9), Clubs(10), Clubs(11), Clubs(12), Clubs(13), Diamonds(1), Diamonds(2), Diamonds(3), Diamonds(4), Diamonds(5), Diamonds(6), Diamonds(7), Diamonds(8), Diamonds(9), Diamonds(10), Diamonds(11), Diamonds(12), Diamonds(13), Hearts(1), Hearts(2), Hearts(3), Hearts(4), Hearts(5), Hearts(6), Hearts(7), Hearts(8), Hearts(9), Hearts(10), Hearts(11), Hearts(12), Hearts(13), Spades(1), Spades(2), Spades(3), Spades(4), Spades(5), Spades(6), Spades(7), Spades(8), Spades(9), Spades(10), Spades(11), Spades(12), Spades(13), JokerA, JokerB] });
}

#[test]
fn move_joker() {
    let mut d = Deck{ d: vec![Clubs(1), Clubs(2), JokerA] };
    d.move_joker(JokerA, 1);
    assert_eq!(d.d, vec![Clubs(1), JokerA, Clubs(2)]);

    let mut d = Deck{ d: vec![Clubs(1), Clubs(2), Hearts(3), JokerA, JokerB] };
    d.move_joker(JokerA, 1);
    d.move_joker(JokerB, 2);
    assert_eq!(d.d, vec![Clubs(1), JokerB, Clubs(2), Hearts(3), JokerA]);
}

#[test]
fn triple_cut() {
    let tests = vec![
        (vec![Clubs(1), JokerA, Clubs(2), JokerB, Clubs(3)], vec![Clubs(3), JokerA, Clubs(2), JokerB, Clubs(1)]),
        (vec![Clubs(1), Hearts(1), JokerA, Clubs(2), JokerB, Clubs(3), Hearts(3)], vec![Clubs(3), Hearts(3), JokerA, Clubs(2), JokerB, Clubs(1), Hearts(1)]),
        (vec![JokerA, JokerB], vec![JokerA, JokerB]),
        ];

    for test in tests.iter() {
        let (initial, expect) = test.clone();
        let mut got = Deck{ d: initial };
        got.triple_cut();
        assert_eq!(got.d, expect);
    }
}

#[test]
fn gen_keystream_letter() {
    let mut d = Deck::new();

    assert_eq!(d.gen_keystream_letter(), 4);
}
<|endoftext|>


<commit_before>#[cfg(any(target_os = "linux", target_os = "android"))]
mod eventfd {
    use std::fs::File;
    use std::io::{self, Read, Write};
    use std::mem;
    use std::os::unix::io::FromRawFd;

    use crate::sys::Selector;
    use crate::{Interests, Token};

    /// Waker backed by `eventfd`.
    ///
    /// `eventfd` is effectively an 64 bit counter. All writes must be of 8
    /// bytes (64 bits) and are converted (native endian) into an 64 bit
    /// unsigned integer and added to the count. Reads must also be 8 bytes and
    /// reset the count to 0, returning the count.
    #[derive(Debug)]
    pub struct Waker {
        fd: File,
    }

    impl Waker {
        pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
            let fd = syscall!(eventfd(0, libc::EFD_CLOEXEC | libc::EFD_NONBLOCK))?;

            selector.register(fd, token, Interests::READABLE)?;
            Ok(Waker {
                fd: unsafe { File::from_raw_fd(fd) },
            })
        }

        pub fn wake(&self) -> io::Result<()> {
            let buf: [u8; 8] = unsafe { mem::transmute(1u64) };
            match (&self.fd).write(&buf) {
                Ok(_) => Ok(()),
                Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
                    // Writing only blocks if the counter is going to overflow.
                    // So we'll reset the counter to 0 and wake it again.
                    self.reset()?;
                    self.wake()
                }
                Err(err) => Err(err),
            }
        }

        /// Reset the eventfd object, only need to call this if `wake` fails.
        fn reset(&self) -> io::Result<()> {
            let mut buf: [u8; 8] = [0; 8];
            match (&self.fd).read(&mut buf) {
                Ok(_) => Ok(()),
                // If the `Waker` hasn't been awoken yet this will return a
                // `WouldBlock` error which we can safely ignore.
                Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Ok(()),
                Err(err) => Err(err),
            }
        }
    }
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::eventfd::Waker;

#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
mod kqueue {
    use std::io;

    use crate::sys::Selector;
    use crate::Token;

    /// Waker backed by kqueue user space notifications (`EVFILT_USER`).
    ///
    /// The implementation is fairly simple, first the kqueue must be setup to
    /// receive waker events this done by calling `Selector.setup_waker`. Next
    /// we need access to kqueue, thus we need to duplicate the file descriptor.
    /// Now waking is as simple as adding an event to the kqueue.
    #[derive(Debug)]
    pub struct Waker {
        selector: Selector,
        token: Token,
    }

    impl Waker {
        pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
            selector.try_clone_waker().and_then(|selector| {
                selector
                    .setup_waker(token)
                    .map(|()| Waker { selector, token })
            })
        }

        pub fn wake(&self) -> io::Result<()> {
            self.selector.wake(self.token)
        }
    }
}

#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
pub use self::kqueue::Waker;

#[cfg(any(
    target_os = "bitrig",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "solaris"
))]
mod pipe {
    use std::fs::File;
    use std::io::{self, Read, Write};
    use std::os::unix::io::FromRawFd;

    use crate::sys::unix::Selector;
    use crate::{Interests, Token};

    /// Waker backed by a unix pipe.
    ///
    /// Waker controls both the sending and receiving ends and empties the pipe
    /// if writing to it (waking) fails.
    #[derive(Debug)]
    pub struct Waker {
        sender: File,
        receiver: File,
    }

    impl Waker {
        pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
            let mut fds = [-1; 2];
            syscall!(pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK | libc::O_CLOEXEC))?;
            selector.register(fds[0], token, Interests::READABLE)?;

            unsafe {
                Ok(Waker {
                    sender: File::from_raw_fd(fds[1]),
                    receiver: File::from_raw_fd(fds[0]),
                })
            }
        }

        pub fn wake(&self) -> io::Result<()> {
            match (&self.sender).write(&[1]) {
                Ok(_) => Ok(()),
                Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
                    // The reading end is full so we'll empty the buffer and try
                    // again.
                    self.empty();
                    self.wake()
                }
                Err(ref err) if err.kind() == io::ErrorKind::Interrupted => self.wake(),
                Err(err) => Err(err),
            }
        }

        /// Empty the pipe's buffer, only need to call this if `wake` fails.
        /// This ignores any errors.
        fn empty(&self) {
            let mut buf = [0; 4096];
            loop {
                match (&self.receiver).read(&mut buf) {
                    Ok(n) if n > 0 => continue,
                    _ => return,
                }
            }
        }
    }
}

#[cfg(any(
    target_os = "bitrig",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "solaris"
))]
pub use self::pipe::Waker;
<commit_msg>Reduce unsafe scope in pipe::Waker::new<commit_after>#[cfg(any(target_os = "linux", target_os = "android"))]
mod eventfd {
    use std::fs::File;
    use std::io::{self, Read, Write};
    use std::mem;
    use std::os::unix::io::FromRawFd;

    use crate::sys::Selector;
    use crate::{Interests, Token};

    /// Waker backed by `eventfd`.
    ///
    /// `eventfd` is effectively an 64 bit counter. All writes must be of 8
    /// bytes (64 bits) and are converted (native endian) into an 64 bit
    /// unsigned integer and added to the count. Reads must also be 8 bytes and
    /// reset the count to 0, returning the count.
    #[derive(Debug)]
    pub struct Waker {
        fd: File,
    }

    impl Waker {
        pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
            let fd = syscall!(eventfd(0, libc::EFD_CLOEXEC | libc::EFD_NONBLOCK))?;

            selector.register(fd, token, Interests::READABLE)?;
            Ok(Waker {
                fd: unsafe { File::from_raw_fd(fd) },
            })
        }

        pub fn wake(&self) -> io::Result<()> {
            let buf: [u8; 8] = unsafe { mem::transmute(1u64) };
            match (&self.fd).write(&buf) {
                Ok(_) => Ok(()),
                Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
                    // Writing only blocks if the counter is going to overflow.
                    // So we'll reset the counter to 0 and wake it again.
                    self.reset()?;
                    self.wake()
                }
                Err(err) => Err(err),
            }
        }

        /// Reset the eventfd object, only need to call this if `wake` fails.
        fn reset(&self) -> io::Result<()> {
            let mut buf: [u8; 8] = [0; 8];
            match (&self.fd).read(&mut buf) {
                Ok(_) => Ok(()),
                // If the `Waker` hasn't been awoken yet this will return a
                // `WouldBlock` error which we can safely ignore.
                Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Ok(()),
                Err(err) => Err(err),
            }
        }
    }
}

#[cfg(any(target_os = "linux", target_os = "android"))]
pub use self::eventfd::Waker;

#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
mod kqueue {
    use std::io;

    use crate::sys::Selector;
    use crate::Token;

    /// Waker backed by kqueue user space notifications (`EVFILT_USER`).
    ///
    /// The implementation is fairly simple, first the kqueue must be setup to
    /// receive waker events this done by calling `Selector.setup_waker`. Next
    /// we need access to kqueue, thus we need to duplicate the file descriptor.
    /// Now waking is as simple as adding an event to the kqueue.
    #[derive(Debug)]
    pub struct Waker {
        selector: Selector,
        token: Token,
    }

    impl Waker {
        pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
            selector.try_clone_waker().and_then(|selector| {
                selector
                    .setup_waker(token)
                    .map(|()| Waker { selector, token })
            })
        }

        pub fn wake(&self) -> io::Result<()> {
            self.selector.wake(self.token)
        }
    }
}

#[cfg(any(target_os = "freebsd", target_os = "ios", target_os = "macos"))]
pub use self::kqueue::Waker;

#[cfg(any(
    target_os = "bitrig",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "solaris"
))]
mod pipe {
    use std::fs::File;
    use std::io::{self, Read, Write};
    use std::os::unix::io::FromRawFd;

    use crate::sys::unix::Selector;
    use crate::{Interests, Token};

    /// Waker backed by a unix pipe.
    ///
    /// Waker controls both the sending and receiving ends and empties the pipe
    /// if writing to it (waking) fails.
    #[derive(Debug)]
    pub struct Waker {
        sender: File,
        receiver: File,
    }

    impl Waker {
        pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
            let mut fds = [-1; 2];
            syscall!(pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK | libc::O_CLOEXEC))?;
            selector.register(fds[0], token, Interests::READABLE)?;

            Ok(Waker {
                sender: unsafe { File::from_raw_fd(fds[1]) },
                receiver: unsafe { File::from_raw_fd(fds[0]) },
            })
        }

        pub fn wake(&self) -> io::Result<()> {
            match (&self.sender).write(&[1]) {
                Ok(_) => Ok(()),
                Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
                    // The reading end is full so we'll empty the buffer and try
                    // again.
                    self.empty();
                    self.wake()
                }
                Err(ref err) if err.kind() == io::ErrorKind::Interrupted => self.wake(),
                Err(err) => Err(err),
            }
        }

        /// Empty the pipe's buffer, only need to call this if `wake` fails.
        /// This ignores any errors.
        fn empty(&self) {
            let mut buf = [0; 4096];
            loop {
                match (&self.receiver).read(&mut buf) {
                    Ok(n) if n > 0 => continue,
                    _ => return,
                }
            }
        }
    }
}

#[cfg(any(
    target_os = "bitrig",
    target_os = "dragonfly",
    target_os = "netbsd",
    target_os = "openbsd",
    target_os = "solaris"
))]
pub use self::pipe::Waker;
<|endoftext|>


<commit_before>use std::cell::Cell;
use std::env;
use std::error::Error;
use std::fmt;
use std::mem;
use std::sync::Arc;

use conduit::{Request, Response};
use conduit_middleware::Middleware;
use diesel::pg::PgConnection;
use openssl::ssl::{SslConnector, SslConnectorBuilder, SslMethod, SSL_VERIFY_NONE};
use pg::GenericConnection;
use pg::tls::{TlsHandshake, Stream, TlsStream};
use pg;
use r2d2;
use r2d2_postgres::PostgresConnectionManager as PCM;
use r2d2_postgres::TlsMode;
use r2d2_postgres::postgres;
use r2d2_postgres;
use r2d2_diesel::{self, ConnectionManager};

use app::{App, RequestApp};
use util::{CargoResult, LazyCell, internal};

pub type Pool = r2d2::Pool<PCM>;
pub type Config = r2d2::Config<pg::Connection, r2d2_postgres::Error>;
type PooledConnnection = r2d2::PooledConnection<PCM>;
pub type DieselPool = r2d2::Pool<ConnectionManager<PgConnection>>;
type DieselPooledConn = r2d2::PooledConnection<ConnectionManager<PgConnection>>;

/// Creates a TLS handshake mechanism used by our postgres driver to negotiate
/// the TLS connection.
pub fn tls_handshake() -> Box<TlsHandshake + Sync + Send> {
    struct MyHandshake(SslConnector);

    // Note that rust-postgres provides a suite of TLS drivers to select from,
    // including all the native platform versions. It even correctly verifies
    // hostnames and such by default!
    //
    // Unfortunately for us, though, Heroku doesn't actually use valid
    // certificates for the database connections that we're initiating. In a
    // support ticket they've clarified that the certs are self-signed and
    // relatively ephemeral. As a result we have no choice but to disable
    // verification of the certificate.
    //
    // We use the standard `SslConnector` from the `openssl` crate here as it
    // will configure a number of other security parameters, but we use it in
    // two special ways:
    //
    // 1. We pass `SSL_VERIFY_NONE` to disable verification of the certificate
    //    chain
    // 2. We use a super long and weird method name indicating that we're not
    //    validating the certificate with a domain name, but rather just the
    //    certificate itself.
    //
    // This should get us connecting to Heroku's databases for now and even
    // protect us against passive attackers, but hopefully Heroku offers a
    // better solution in the future for certificate verification...

    impl TlsHandshake for MyHandshake {
        fn tls_handshake(&self,
                         _domain: &str,
                         stream: Stream)
                         -> Result<Box<TlsStream>, Box<Error + Send + Sync>> {
            let stream = self.0.danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(stream)?;
            Ok(Box::new(stream))
        }
    }

    impl fmt::Debug for MyHandshake {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            fmt.debug_struct("MyHandshake").finish()
        }
    }

    let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
    builder.builder_mut()
           .set_verify(SSL_VERIFY_NONE);

    Box::new(MyHandshake(builder.build()))
}

// Note that this is intended to be called from scripts, not in the main app, it
// panics!
pub fn connect_now() -> pg::Connection {
    let tls = tls_handshake();
    let mode = if env::var("HEROKU").is_ok() {
        pg::TlsMode::Require(&*tls)
    } else {
        pg::TlsMode::Prefer(&*tls)
    };
    pg::Connection::connect(&::env("DATABASE_URL")[..], mode).unwrap()
}

pub fn pool(url: &str, config: r2d2::Config<postgres::Connection, r2d2_postgres::Error>) -> Pool {
    let mode = if env::var("HEROKU").is_ok() {
        TlsMode::Require(tls_handshake())
    } else {
        TlsMode::Prefer(tls_handshake())
    };
    let mgr = PCM::new(url, mode).unwrap();
    r2d2::Pool::new(config, mgr).unwrap()
}

pub fn diesel_pool(url: &str, config: r2d2::Config<PgConnection, r2d2_diesel::Error>) -> DieselPool {
    let manager = ConnectionManager::new(url);
    r2d2::Pool::new(config, manager).unwrap()
}

pub struct TransactionMiddleware;

pub struct Transaction {
    // fields are destructed top-to-bottom so ensure we destroy them in the
    // right order.
    //
    // Note that `slot` and `PooledConnnection` are intentionally behind a `Box`
    // for safety reasons. The `tx` field will actually be containing a borrow
    // into `PooledConnnection`, but this `Transaction` can be moved around in
    // memory, so we need the borrow to be from a stable address. The `Box` will
    // provide this stable address.
    tx: LazyCell<pg::transaction::Transaction<'static>>,
    slot: LazyCell<Box<PooledConnnection>>,
    commit: Cell<Option<bool>>,

    // Keep a handle to the app which keeps a handle to the database to ensure
    // that this `'static` is indeed at least a little more accurate (in that
    // it's alive for the period of time this `Transaction` is alive.
    app: Arc<App>,
}

impl Transaction {
    pub fn new(app: Arc<App>) -> Transaction {
        Transaction {
            app: app,
            slot: LazyCell::new(),
            tx: LazyCell::new(),
            commit: Cell::new(None),
        }
    }

    pub fn conn(&self) -> CargoResult<&r2d2::PooledConnection<r2d2_postgres::PostgresConnectionManager>> {
        if !self.slot.filled() {
            let conn = self.app.database.get().map_err(|e| {
                internal(format!("failed to get a database connection: {}", e))
            })?;
            self.slot.fill(Box::new(conn));
        }
        Ok(&**self.slot.borrow().unwrap())
    }

    fn tx<'a>(&'a self) -> CargoResult<&'a (GenericConnection + 'a)> {
        // Similar to above, the transaction for this request is actually tied
        // to the connection in the request itself, not 'static. We transmute it
        // to static as its paired with the inner connection to achieve the
        // desired effect.
        unsafe {
            if !self.tx.filled() {
                let conn = self.conn()?;
                let t = conn.transaction()?;
                let t = mem::transmute::<_, pg::transaction::Transaction<'static>>(t);
                self.tx.fill(t);
            }
        }
        let tx = self.tx.borrow();
        let tx: &'a pg::transaction::Transaction<'static> = tx.unwrap();
        Ok(tx)
    }

    pub fn rollback(&self) {
        self.commit.set(Some(false));
    }

    pub fn commit(&self) {
        if self.commit.get().is_none() {
            self.commit.set(Some(true));
        }
    }
}

impl Middleware for TransactionMiddleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        let app = req.app().clone();
        req.mut_extensions().insert(Transaction::new(app));
        Ok(())
    }

    fn after(&self, req: &mut Request, res: Result<Response, Box<Error+Send>>)
             -> Result<Response, Box<Error+Send>> {
        let tx = req.mut_extensions().pop::<Transaction>()
                    .expect("Transaction not present in request");
        if let Some(transaction) = tx.tx.into_inner() {
            if res.is_ok() && tx.commit.get() == Some(true) {
                transaction.set_commit();
            }
            transaction.finish().map_err(|e| {
                Box::new(e) as Box<Error + Send>
            })?;
        }
        return res
    }
}

pub struct DieselMiddleware;

impl Middleware for DieselMiddleware {
    fn before(&self, request: &mut Request) -> Result<(), Box<Error+Send>> {
        request.mut_extensions().insert(LazyCell::<DieselPooledConn>::new());
        Ok(())
    }
}

pub trait RequestTransaction {
    /// Return the lazily initialized postgres connection for this request.
    ///
    /// The connection will live for the lifetime of the request.
    fn db_conn(&self) -> CargoResult<&PgConnection>;

    /// Return the lazily initialized postgres transaction for this request.
    ///
    /// The transaction will live for the duration of the request, and it will
    /// only be set to commit() if a successful response code of 200 is seen.
    fn tx(&self) -> CargoResult<&GenericConnection>;

    /// Flag the transaction to not be committed. Does not affect Diesel connections
    fn rollback(&self);
    /// Flag this transaction to be committed. Does not affect Diesel connections.
    fn commit(&self);
}

impl<T: Request + ?Sized> RequestTransaction for T {
    fn db_conn(&self) -> CargoResult<&PgConnection> {
        let cell = self.extensions().find::<LazyCell<DieselPooledConn>>()
            .expect("PgConnection not present in request");
        if !cell.filled() {
            cell.fill(self.app().diesel_database.get()?);
        }
        Ok(&**cell.borrow().unwrap())
    }

    fn tx(&self) -> CargoResult<&GenericConnection> {
        self.extensions().find::<Transaction>()
            .expect("Transaction not present in request")
            .tx()
    }

    fn rollback(&self) {
        self.extensions().find::<Transaction>()
            .expect("Transaction not present in request")
            .rollback()
    }

    fn commit(&self) {
        self.extensions().find::<Transaction>()
            .expect("Transaction not present in request")
            .commit()
    }
}
<commit_msg>Require SSL on Heroku<commit_after>use std::cell::Cell;
use std::env;
use std::error::Error;
use std::fmt;
use std::mem;
use std::sync::Arc;

use conduit::{Request, Response};
use conduit_middleware::Middleware;
use diesel::pg::PgConnection;
use openssl::ssl::{SslConnector, SslConnectorBuilder, SslMethod, SSL_VERIFY_NONE};
use pg::GenericConnection;
use pg::tls::{TlsHandshake, Stream, TlsStream};
use pg;
use r2d2;
use r2d2_postgres::PostgresConnectionManager as PCM;
use r2d2_postgres::TlsMode;
use r2d2_postgres::postgres;
use r2d2_postgres;
use r2d2_diesel::{self, ConnectionManager};
use url::Url;

use app::{App, RequestApp};
use util::{CargoResult, LazyCell, internal};

pub type Pool = r2d2::Pool<PCM>;
pub type Config = r2d2::Config<pg::Connection, r2d2_postgres::Error>;
type PooledConnnection = r2d2::PooledConnection<PCM>;
pub type DieselPool = r2d2::Pool<ConnectionManager<PgConnection>>;
type DieselPooledConn = r2d2::PooledConnection<ConnectionManager<PgConnection>>;

/// Creates a TLS handshake mechanism used by our postgres driver to negotiate
/// the TLS connection.
pub fn tls_handshake() -> Box<TlsHandshake + Sync + Send> {
    struct MyHandshake(SslConnector);

    // Note that rust-postgres provides a suite of TLS drivers to select from,
    // including all the native platform versions. It even correctly verifies
    // hostnames and such by default!
    //
    // Unfortunately for us, though, Heroku doesn't actually use valid
    // certificates for the database connections that we're initiating. In a
    // support ticket they've clarified that the certs are self-signed and
    // relatively ephemeral. As a result we have no choice but to disable
    // verification of the certificate.
    //
    // We use the standard `SslConnector` from the `openssl` crate here as it
    // will configure a number of other security parameters, but we use it in
    // two special ways:
    //
    // 1. We pass `SSL_VERIFY_NONE` to disable verification of the certificate
    //    chain
    // 2. We use a super long and weird method name indicating that we're not
    //    validating the certificate with a domain name, but rather just the
    //    certificate itself.
    //
    // This should get us connecting to Heroku's databases for now and even
    // protect us against passive attackers, but hopefully Heroku offers a
    // better solution in the future for certificate verification...

    impl TlsHandshake for MyHandshake {
        fn tls_handshake(&self,
                         _domain: &str,
                         stream: Stream)
                         -> Result<Box<TlsStream>, Box<Error + Send + Sync>> {
            let stream = self.0.danger_connect_without_providing_domain_for_certificate_verification_and_server_name_indication(stream)?;
            Ok(Box::new(stream))
        }
    }

    impl fmt::Debug for MyHandshake {
        fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
            fmt.debug_struct("MyHandshake").finish()
        }
    }

    let mut builder = SslConnectorBuilder::new(SslMethod::tls()).unwrap();
    builder.builder_mut()
           .set_verify(SSL_VERIFY_NONE);

    Box::new(MyHandshake(builder.build()))
}

// Note that this is intended to be called from scripts, not in the main app, it
// panics!
pub fn connect_now() -> pg::Connection {
    let tls = tls_handshake();
    let mode = if env::var("HEROKU").is_ok() {
        pg::TlsMode::Require(&*tls)
    } else {
        pg::TlsMode::Prefer(&*tls)
    };
    pg::Connection::connect(&::env("DATABASE_URL")[..], mode).unwrap()
}

pub fn pool(url: &str, config: r2d2::Config<postgres::Connection, r2d2_postgres::Error>) -> Pool {
    let mode = if env::var("HEROKU").is_ok() {
        TlsMode::Require(tls_handshake())
    } else {
        TlsMode::Prefer(tls_handshake())
    };
    let mgr = PCM::new(url, mode).unwrap();
    r2d2::Pool::new(config, mgr).unwrap()
}

pub fn diesel_pool(url: &str, config: r2d2::Config<PgConnection, r2d2_diesel::Error>) -> DieselPool {
    let mut url = Url::parse(url).expect("Invalid database URL");
    if env::var("HEROKU").is_ok() && !url.query_pairs().any(|(k, _)| k == "sslmode") {
        url.query_pairs_mut().append_pair("sslmode", "require");
    }
    let manager = ConnectionManager::new(url.into_string());
    r2d2::Pool::new(config, manager).unwrap()
}

pub struct TransactionMiddleware;

pub struct Transaction {
    // fields are destructed top-to-bottom so ensure we destroy them in the
    // right order.
    //
    // Note that `slot` and `PooledConnnection` are intentionally behind a `Box`
    // for safety reasons. The `tx` field will actually be containing a borrow
    // into `PooledConnnection`, but this `Transaction` can be moved around in
    // memory, so we need the borrow to be from a stable address. The `Box` will
    // provide this stable address.
    tx: LazyCell<pg::transaction::Transaction<'static>>,
    slot: LazyCell<Box<PooledConnnection>>,
    commit: Cell<Option<bool>>,

    // Keep a handle to the app which keeps a handle to the database to ensure
    // that this `'static` is indeed at least a little more accurate (in that
    // it's alive for the period of time this `Transaction` is alive.
    app: Arc<App>,
}

impl Transaction {
    pub fn new(app: Arc<App>) -> Transaction {
        Transaction {
            app: app,
            slot: LazyCell::new(),
            tx: LazyCell::new(),
            commit: Cell::new(None),
        }
    }

    pub fn conn(&self) -> CargoResult<&r2d2::PooledConnection<r2d2_postgres::PostgresConnectionManager>> {
        if !self.slot.filled() {
            let conn = self.app.database.get().map_err(|e| {
                internal(format!("failed to get a database connection: {}", e))
            })?;
            self.slot.fill(Box::new(conn));
        }
        Ok(&**self.slot.borrow().unwrap())
    }

    fn tx<'a>(&'a self) -> CargoResult<&'a (GenericConnection + 'a)> {
        // Similar to above, the transaction for this request is actually tied
        // to the connection in the request itself, not 'static. We transmute it
        // to static as its paired with the inner connection to achieve the
        // desired effect.
        unsafe {
            if !self.tx.filled() {
                let conn = self.conn()?;
                let t = conn.transaction()?;
                let t = mem::transmute::<_, pg::transaction::Transaction<'static>>(t);
                self.tx.fill(t);
            }
        }
        let tx = self.tx.borrow();
        let tx: &'a pg::transaction::Transaction<'static> = tx.unwrap();
        Ok(tx)
    }

    pub fn rollback(&self) {
        self.commit.set(Some(false));
    }

    pub fn commit(&self) {
        if self.commit.get().is_none() {
            self.commit.set(Some(true));
        }
    }
}

impl Middleware for TransactionMiddleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        let app = req.app().clone();
        req.mut_extensions().insert(Transaction::new(app));
        Ok(())
    }

    fn after(&self, req: &mut Request, res: Result<Response, Box<Error+Send>>)
             -> Result<Response, Box<Error+Send>> {
        let tx = req.mut_extensions().pop::<Transaction>()
                    .expect("Transaction not present in request");
        if let Some(transaction) = tx.tx.into_inner() {
            if res.is_ok() && tx.commit.get() == Some(true) {
                transaction.set_commit();
            }
            transaction.finish().map_err(|e| {
                Box::new(e) as Box<Error + Send>
            })?;
        }
        return res
    }
}

pub struct DieselMiddleware;

impl Middleware for DieselMiddleware {
    fn before(&self, request: &mut Request) -> Result<(), Box<Error+Send>> {
        request.mut_extensions().insert(LazyCell::<DieselPooledConn>::new());
        Ok(())
    }
}

pub trait RequestTransaction {
    /// Return the lazily initialized postgres connection for this request.
    ///
    /// The connection will live for the lifetime of the request.
    fn db_conn(&self) -> CargoResult<&PgConnection>;

    /// Return the lazily initialized postgres transaction for this request.
    ///
    /// The transaction will live for the duration of the request, and it will
    /// only be set to commit() if a successful response code of 200 is seen.
    fn tx(&self) -> CargoResult<&GenericConnection>;

    /// Flag the transaction to not be committed. Does not affect Diesel connections
    fn rollback(&self);
    /// Flag this transaction to be committed. Does not affect Diesel connections.
    fn commit(&self);
}

impl<T: Request + ?Sized> RequestTransaction for T {
    fn db_conn(&self) -> CargoResult<&PgConnection> {
        let cell = self.extensions().find::<LazyCell<DieselPooledConn>>()
            .expect("PgConnection not present in request");
        if !cell.filled() {
            cell.fill(self.app().diesel_database.get()?);
        }
        Ok(&**cell.borrow().unwrap())
    }

    fn tx(&self) -> CargoResult<&GenericConnection> {
        self.extensions().find::<Transaction>()
            .expect("Transaction not present in request")
            .tx()
    }

    fn rollback(&self) {
        self.extensions().find::<Transaction>()
            .expect("Transaction not present in request")
            .rollback()
    }

    fn commit(&self) {
        self.extensions().find::<Transaction>()
            .expect("Transaction not present in request")
            .commit()
    }
}
<|endoftext|>


<commit_before>//! YAML Deserialization
//!
//! This module provides YAML deserialization with the type `Deserializer`.

use std::collections::btree_map;
use std::slice;

use yaml_rust::{Yaml, YamlLoader};
use yaml_rust::yaml;

use serde::de::{self, Deserialize};

use super::error::{Error, Result};

/// A structure for deserializing a YAML value into a Rust value.
pub struct Deserializer<'a> {
    /// YAML value being deserialized.
    doc: &'a Yaml,
}

impl<'a> Deserializer<'a> {
    /// Creates the YAML deserializer from an in-memory `Yaml`.
    pub fn new(doc: &'a Yaml) -> Self {
        Deserializer {
            doc: doc,
        }
    }
}

struct SeqVisitor<'a> {
    /// Iterator over the YAML array being visited.
    iter: slice::Iter<'a, Yaml>,
}

impl<'a> SeqVisitor<'a> {
    fn new(seq: &'a yaml::Array) -> Self {
        SeqVisitor {
            iter: seq.iter(),
        }
    }
}

impl<'a> de::SeqVisitor for SeqVisitor<'a> {
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>>
        where T: Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some(ref t) => {
                Deserialize::deserialize(&mut Deserializer::new(t)).map(Some)
            },
        }
    }

    fn end(&mut self) -> Result<()> {
        Ok(())
    }
}

struct MapVisitor<'a> {
    /// Iterator over the YAML hash being visited.
    iter: btree_map::Iter<'a, Yaml, Yaml>,
    /// Value associated with the most recently visited key.
    v: Option<&'a Yaml>,
}

impl<'a> MapVisitor<'a> {
    fn new(hash: &'a yaml::Hash) -> Self {
        MapVisitor {
            iter: hash.iter(),
            v: None,
        }
    }
}

impl<'a> de::MapVisitor for MapVisitor<'a> {
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>>
        where K: Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some((ref k, ref v)) => {
                self.v = Some(v);
                Deserialize::deserialize(&mut Deserializer::new(k)).map(Some)
            },
        }
    }

    fn visit_value<V>(&mut self) -> Result<V>
        where V: Deserialize,
    {
        match self.v {
            Some(v) => Deserialize::deserialize(&mut Deserializer::new(v)),
            None => panic!("must call visit_key before visit_value"),
        }
    }

    fn end(&mut self) -> Result<()> {
        Ok(())
    }
}

struct VariantVisitor<'a> {
    /// Representation of which variant it is.
    variant: &'a Yaml,
    /// Representation of the content of the variant.
    content: &'a Yaml,
}

impl<'a> VariantVisitor<'a> {
    fn new(variant: &'a Yaml, content: &'a Yaml) -> Self {
        VariantVisitor {
            variant: variant,
            content: content,
        }
    }
}

impl <'a> de::VariantVisitor for VariantVisitor<'a> {
    type Error = Error;

    fn visit_variant<V>(&mut self) -> Result<V>
        where V: Deserialize
    {
        Deserialize::deserialize(&mut Deserializer::new(self.variant))
    }

    fn visit_unit(&mut self) -> Result<()> {
        Ok(())
    }

    fn visit_newtype<T>(&mut self) -> Result<T>
        where T: Deserialize,
    {
        Deserialize::deserialize(&mut Deserializer::new(self.content))
    }

    fn visit_tuple<V>(&mut self,
                      _len: usize,
                      visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        de::Deserializer::visit(&mut Deserializer::new(self.content), visitor)
    }

    fn visit_struct<V>(&mut self,
                       _fields: &'static [&'static str],
                       visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        de::Deserializer::visit(&mut Deserializer::new(self.content), visitor)
    }
}

impl<'a> de::Deserializer for Deserializer<'a> {
    type Error = Error;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        match *self.doc {
            Yaml::Real(ref s) => visitor.visit_str(s),
            Yaml::Integer(i) => visitor.visit_i64(i),
            Yaml::String(ref s) => visitor.visit_str(s),
            Yaml::Boolean(b) => visitor.visit_bool(b),
            Yaml::Array(ref seq) => visitor.visit_seq(SeqVisitor::new(seq)),
            Yaml::Hash(ref hash) => visitor.visit_map(MapVisitor::new(hash)),
            Yaml::Alias(_) => Err(Error::AliasUnsupported),
            Yaml::Null => visitor.visit_unit(),
            Yaml::BadValue => {
                // The yaml-rust library produces BadValue when a nonexistent
                // node is accessed by the Index trait, and when a type
                // conversion is invalid. Both of these are unexpected in our
                // usage.
                panic!("bad value")
            },
        }
    }

    /// Parses `null` as None and any other values as `Some(...)`.
    fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        match *self.doc {
            Yaml::Null => visitor.visit_none(),
            _ => visitor.visit_some(self),
        }
    }

    /// Parses a newtype struct as the underlying value.
    fn visit_newtype_struct<V>(&mut self,
                               _name: &str,
                               mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        visitor.visit_newtype_struct(self)
    }

    /// Parses an enum as a single key:value pair where the key identifies the
    /// variant and the value gives the content.
    fn visit_enum<V>(&mut self,
                     name: &str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value>
        where V: de::EnumVisitor,
    {
        if let Yaml::Hash(ref hash) = *self.doc {
            let mut iter = hash.iter();
            if let (Some(entry), None) = (iter.next(), iter.next()) {
                let (variant, content) = entry;
                visitor.visit(VariantVisitor::new(variant, content))
            } else {
                Err(Error::VariantMapWrongSize(String::from(name), hash.len()))
            }
        } else {
            Err(Error::VariantNotAMap(String::from(name)))
        }
    }

    fn format() -> &'static str {
        "yaml"
    }
}

/// Decodes a YAML value from a `&str`.
pub fn from_str<T>(s: &str) -> Result<T>
    where T: Deserialize
{
    let docs = try!(YamlLoader::load_from_str(s));
    match docs.len() {
        0 => Err(Error::EndOfStream),
        1 => {
            let doc = &docs[0];
            Deserialize::deserialize(&mut Deserializer::new(doc))
        },
        n => Err(Error::TooManyDocuments(n)),
    }
}
<commit_msg>Coalesce identical match bodies<commit_after>//! YAML Deserialization
//!
//! This module provides YAML deserialization with the type `Deserializer`.

use std::collections::btree_map;
use std::slice;

use yaml_rust::{Yaml, YamlLoader};
use yaml_rust::yaml;

use serde::de::{self, Deserialize};

use super::error::{Error, Result};

/// A structure for deserializing a YAML value into a Rust value.
pub struct Deserializer<'a> {
    /// YAML value being deserialized.
    doc: &'a Yaml,
}

impl<'a> Deserializer<'a> {
    /// Creates the YAML deserializer from an in-memory `Yaml`.
    pub fn new(doc: &'a Yaml) -> Self {
        Deserializer {
            doc: doc,
        }
    }
}

struct SeqVisitor<'a> {
    /// Iterator over the YAML array being visited.
    iter: slice::Iter<'a, Yaml>,
}

impl<'a> SeqVisitor<'a> {
    fn new(seq: &'a yaml::Array) -> Self {
        SeqVisitor {
            iter: seq.iter(),
        }
    }
}

impl<'a> de::SeqVisitor for SeqVisitor<'a> {
    type Error = Error;

    fn visit<T>(&mut self) -> Result<Option<T>>
        where T: Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some(ref t) => {
                Deserialize::deserialize(&mut Deserializer::new(t)).map(Some)
            },
        }
    }

    fn end(&mut self) -> Result<()> {
        Ok(())
    }
}

struct MapVisitor<'a> {
    /// Iterator over the YAML hash being visited.
    iter: btree_map::Iter<'a, Yaml, Yaml>,
    /// Value associated with the most recently visited key.
    v: Option<&'a Yaml>,
}

impl<'a> MapVisitor<'a> {
    fn new(hash: &'a yaml::Hash) -> Self {
        MapVisitor {
            iter: hash.iter(),
            v: None,
        }
    }
}

impl<'a> de::MapVisitor for MapVisitor<'a> {
    type Error = Error;

    fn visit_key<K>(&mut self) -> Result<Option<K>>
        where K: Deserialize,
    {
        match self.iter.next() {
            None => Ok(None),
            Some((ref k, ref v)) => {
                self.v = Some(v);
                Deserialize::deserialize(&mut Deserializer::new(k)).map(Some)
            },
        }
    }

    fn visit_value<V>(&mut self) -> Result<V>
        where V: Deserialize,
    {
        match self.v {
            Some(v) => Deserialize::deserialize(&mut Deserializer::new(v)),
            None => panic!("must call visit_key before visit_value"),
        }
    }

    fn end(&mut self) -> Result<()> {
        Ok(())
    }
}

struct VariantVisitor<'a> {
    /// Representation of which variant it is.
    variant: &'a Yaml,
    /// Representation of the content of the variant.
    content: &'a Yaml,
}

impl<'a> VariantVisitor<'a> {
    fn new(variant: &'a Yaml, content: &'a Yaml) -> Self {
        VariantVisitor {
            variant: variant,
            content: content,
        }
    }
}

impl <'a> de::VariantVisitor for VariantVisitor<'a> {
    type Error = Error;

    fn visit_variant<V>(&mut self) -> Result<V>
        where V: Deserialize
    {
        Deserialize::deserialize(&mut Deserializer::new(self.variant))
    }

    fn visit_unit(&mut self) -> Result<()> {
        Ok(())
    }

    fn visit_newtype<T>(&mut self) -> Result<T>
        where T: Deserialize,
    {
        Deserialize::deserialize(&mut Deserializer::new(self.content))
    }

    fn visit_tuple<V>(&mut self,
                      _len: usize,
                      visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        de::Deserializer::visit(&mut Deserializer::new(self.content), visitor)
    }

    fn visit_struct<V>(&mut self,
                       _fields: &'static [&'static str],
                       visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        de::Deserializer::visit(&mut Deserializer::new(self.content), visitor)
    }
}

impl<'a> de::Deserializer for Deserializer<'a> {
    type Error = Error;

    fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        match *self.doc {
            Yaml::Integer(i) => visitor.visit_i64(i),
            Yaml::Real(ref s) | Yaml::String(ref s) => visitor.visit_str(s),
            Yaml::Boolean(b) => visitor.visit_bool(b),
            Yaml::Array(ref seq) => visitor.visit_seq(SeqVisitor::new(seq)),
            Yaml::Hash(ref hash) => visitor.visit_map(MapVisitor::new(hash)),
            Yaml::Alias(_) => Err(Error::AliasUnsupported),
            Yaml::Null => visitor.visit_unit(),
            Yaml::BadValue => {
                // The yaml-rust library produces BadValue when a nonexistent
                // node is accessed by the Index trait, and when a type
                // conversion is invalid. Both of these are unexpected in our
                // usage.
                panic!("bad value")
            },
        }
    }

    /// Parses `null` as None and any other values as `Some(...)`.
    fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        match *self.doc {
            Yaml::Null => visitor.visit_none(),
            _ => visitor.visit_some(self),
        }
    }

    /// Parses a newtype struct as the underlying value.
    fn visit_newtype_struct<V>(&mut self,
                               _name: &str,
                               mut visitor: V) -> Result<V::Value>
        where V: de::Visitor,
    {
        visitor.visit_newtype_struct(self)
    }

    /// Parses an enum as a single key:value pair where the key identifies the
    /// variant and the value gives the content.
    fn visit_enum<V>(&mut self,
                     name: &str,
                     _variants: &'static [&'static str],
                     mut visitor: V) -> Result<V::Value>
        where V: de::EnumVisitor,
    {
        if let Yaml::Hash(ref hash) = *self.doc {
            let mut iter = hash.iter();
            if let (Some(entry), None) = (iter.next(), iter.next()) {
                let (variant, content) = entry;
                visitor.visit(VariantVisitor::new(variant, content))
            } else {
                Err(Error::VariantMapWrongSize(String::from(name), hash.len()))
            }
        } else {
            Err(Error::VariantNotAMap(String::from(name)))
        }
    }

    fn format() -> &'static str {
        "yaml"
    }
}

/// Decodes a YAML value from a `&str`.
pub fn from_str<T>(s: &str) -> Result<T>
    where T: Deserialize
{
    let docs = try!(YamlLoader::load_from_str(s));
    match docs.len() {
        0 => Err(Error::EndOfStream),
        1 => {
            let doc = &docs[0];
            Deserialize::deserialize(&mut Deserializer::new(doc))
        },
        n => Err(Error::TooManyDocuments(n)),
    }
}
<|endoftext|>


<commit_before>use rustc_hash::FxHashSet;

use ra_syntax::{
    ast, AstNode, Direction, File,
    SyntaxKind::{self, *},
    SyntaxNodeRef, TextRange,
};

#[derive(Debug, PartialEq, Eq)]
pub enum FoldKind {
    Comment,
    Imports,
}

#[derive(Debug)]
pub struct Fold {
    pub range: TextRange,
    pub kind: FoldKind,
}

pub fn folding_ranges(file: &File) -> Vec<Fold> {
    let mut res = vec![];
    let mut visited_comments = FxHashSet::default();

    for node in file.syntax().descendants() {
        // Fold items that span multiple lines
        if let Some(kind) = fold_kind(node.kind()) {
            if has_newline(node) {
                res.push(Fold {
                    range: node.range(),
                    kind,
                });
            }
        }

        // Also fold groups of comments
        if visited_comments.contains(&node) {
            continue;
        }
        if node.kind() == COMMENT {
            if let Some(range) = contiguous_range_for_comment(node, &mut visited_comments) {
                res.push(Fold {
                    range,
                    kind: FoldKind::Comment,
                })
            }
        }
    }

    res
}

fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
    match kind {
        COMMENT => Some(FoldKind::Comment),
        USE_ITEM => Some(FoldKind::Imports),
        _ => None,
    }
}

fn has_newline(node: SyntaxNodeRef) -> bool {
    for descendant in node.descendants() {
        if let Some(ws) = ast::Whitespace::cast(descendant) {
            if ws.has_newlines() {
                return true;
            }
        } else if let Some(comment) = ast::Comment::cast(descendant) {
            if comment.has_newlines() {
                return true;
            }
        }
    }

    false
}

fn contiguous_range_for_comment<'a>(
    first: SyntaxNodeRef<'a>,
    visited: &mut FxHashSet<SyntaxNodeRef<'a>>,
) -> Option<TextRange> {
    visited.insert(first);

    // Only fold comments of the same flavor
    let group_flavor = ast::Comment::cast(first)?.flavor();

    let mut last = first;
    for node in first.siblings(Direction::Next) {
        if let Some(ws) = ast::Whitespace::cast(node) {
            // There is a blank line, which means the group ends here
            if ws.count_newlines_lazy().take(2).count() == 2 {
                break;
            }

            // Ignore whitespace without blank lines
            continue;
        }

        match ast::Comment::cast(node) {
            Some(next_comment) if next_comment.flavor() == group_flavor => {
                visited.insert(node);
                last = node;
            }
            // The comment group ends because either:
            // * An element of a different kind was reached
            // * A comment of a different flavor was reached
            _ => break,
        }
    }

    if first != last {
        Some(TextRange::from_to(
            first.range().start(),
            last.range().end(),
        ))
    } else {
        // The group consists of only one element, therefore it cannot be folded
        None
    }
}

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

    fn do_check(text: &str, fold_kinds: &[FoldKind]) {
        let (ranges, text) = extract_ranges(text);
        let file = File::parse(&text);
        let folds = folding_ranges(&file);

        assert_eq!(folds.len(), ranges.len());
        for ((fold, range), fold_kind) in folds
            .into_iter()
            .zip(ranges.into_iter())
            .zip(fold_kinds.into_iter())
        {
            assert_eq!(fold.range.start(), range.start());
            assert_eq!(fold.range.end(), range.end());
            assert_eq!(&fold.kind, fold_kind);
        }
    }

    #[test]
    fn test_fold_comments() {
        let text = r#"
<|>// Hello
// this is a multiline
// comment
//<|>

// But this is not

fn main() {
    <|>// We should
    // also
    // fold
    // this one.<|>
    <|>//! But this one is different
    //! because it has another flavor<|>
    <|>/* As does this
    multiline comment */<|>
}"#;

        let fold_kinds = &[
            FoldKind::Comment,
            FoldKind::Comment,
            FoldKind::Comment,
            FoldKind::Comment,
        ];
        do_check(text, fold_kinds);
    }

    #[test]
    fn test_fold_imports() {
        let text = r#"
<|>use std::{
    str,
    vec,
    io as iop
};<|>

fn main() {
}"#;

        let folds = &[FoldKind::Imports];
        do_check(text, folds);
    }

}
<commit_msg>Restore folding import groups<commit_after>use rustc_hash::FxHashSet;

use ra_syntax::{
    ast, AstNode, Direction, File,
    SyntaxKind::{self, *},
    SyntaxNodeRef, TextRange,
};

#[derive(Debug, PartialEq, Eq)]
pub enum FoldKind {
    Comment,
    Imports,
}

#[derive(Debug)]
pub struct Fold {
    pub range: TextRange,
    pub kind: FoldKind,
}

pub fn folding_ranges(file: &File) -> Vec<Fold> {
    let mut res = vec![];
    let mut visited_comments = FxHashSet::default();
    let mut visited_imports = FxHashSet::default();

    for node in file.syntax().descendants() {
        // Fold items that span multiple lines
        if let Some(kind) = fold_kind(node.kind()) {
            if has_newline(node) {
                res.push(Fold {
                    range: node.range(),
                    kind,
                });
            }
        }

        // Fold groups of comments
        if node.kind() == COMMENT && !visited_comments.contains(&node) {
            if let Some(range) = contiguous_range_for_comment(node, &mut visited_comments) {
                res.push(Fold {
                    range,
                    kind: FoldKind::Comment,
                })
            }
        }

        // Fold groups of imports
        if node.kind() == USE_ITEM && !visited_imports.contains(&node) {
            if let Some(range) = contiguous_range_for_group(node, &mut visited_imports) {
                res.push(Fold {
                    range,
                    kind: FoldKind::Imports,
                })
            }
        }
    }

    res
}

fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> {
    match kind {
        COMMENT => Some(FoldKind::Comment),
        USE_ITEM => Some(FoldKind::Imports),
        _ => None,
    }
}

fn has_newline(node: SyntaxNodeRef) -> bool {
    for descendant in node.descendants() {
        if let Some(ws) = ast::Whitespace::cast(descendant) {
            if ws.has_newlines() {
                return true;
            }
        } else if let Some(comment) = ast::Comment::cast(descendant) {
            if comment.has_newlines() {
                return true;
            }
        }
    }

    false
}

fn contiguous_range_for_group<'a>(
    first: SyntaxNodeRef<'a>,
    visited: &mut FxHashSet<SyntaxNodeRef<'a>>,
) -> Option<TextRange> {
    visited.insert(first);

    let mut last = first;
    for node in first.siblings(Direction::Next) {
        if let Some(ws) = ast::Whitespace::cast(node) {
            // There is a blank line, which means that the group ends here
            if ws.count_newlines_lazy().take(2).count() == 2 {
                break;
            }

            // Ignore whitespace without blank lines
            continue;
        }

        // Stop if we find a node that doesn't belong to the group
        if node.kind() != first.kind() {
            break;
        }

        visited.insert(node);
        last = node;
    }

    if first != last {
        Some(TextRange::from_to(
            first.range().start(),
            last.range().end(),
        ))
    } else {
        // The group consists of only one element, therefore it cannot be folded
        None
    }
}

fn contiguous_range_for_comment<'a>(
    first: SyntaxNodeRef<'a>,
    visited: &mut FxHashSet<SyntaxNodeRef<'a>>,
) -> Option<TextRange> {
    visited.insert(first);

    // Only fold comments of the same flavor
    let group_flavor = ast::Comment::cast(first)?.flavor();

    let mut last = first;
    for node in first.siblings(Direction::Next) {
        if let Some(ws) = ast::Whitespace::cast(node) {
            // There is a blank line, which means the group ends here
            if ws.count_newlines_lazy().take(2).count() == 2 {
                break;
            }

            // Ignore whitespace without blank lines
            continue;
        }

        match ast::Comment::cast(node) {
            Some(next_comment) if next_comment.flavor() == group_flavor => {
                visited.insert(node);
                last = node;
            }
            // The comment group ends because either:
            // * An element of a different kind was reached
            // * A comment of a different flavor was reached
            _ => break,
        }
    }

    if first != last {
        Some(TextRange::from_to(
            first.range().start(),
            last.range().end(),
        ))
    } else {
        // The group consists of only one element, therefore it cannot be folded
        None
    }
}

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

    fn do_check(text: &str, fold_kinds: &[FoldKind]) {
        let (ranges, text) = extract_ranges(text);
        let file = File::parse(&text);
        let folds = folding_ranges(&file);

        assert_eq!(folds.len(), ranges.len(), "The amount of folds is different than the expected amount");
        assert_eq!(folds.len(), fold_kinds.len(), "The amount of fold kinds is different than the expected amount");
        for ((fold, range), fold_kind) in folds
            .into_iter()
            .zip(ranges.into_iter())
            .zip(fold_kinds.into_iter())
        {
            assert_eq!(fold.range.start(), range.start());
            assert_eq!(fold.range.end(), range.end());
            assert_eq!(&fold.kind, fold_kind);
        }
    }

    #[test]
    fn test_fold_comments() {
        let text = r#"
<|>// Hello
// this is a multiline
// comment
//<|>

// But this is not

fn main() {
    <|>// We should
    // also
    // fold
    // this one.<|>
    <|>//! But this one is different
    //! because it has another flavor<|>
    <|>/* As does this
    multiline comment */<|>
}"#;

        let fold_kinds = &[
            FoldKind::Comment,
            FoldKind::Comment,
            FoldKind::Comment,
            FoldKind::Comment,
        ];
        do_check(text, fold_kinds);
    }

    #[test]
    fn test_fold_imports() {
        let text = r#"
<|>use std::{
    str,
    vec,
    io as iop
};<|>

fn main() {
}"#;

        let folds = &[FoldKind::Imports];
        do_check(text, folds);
    }

    #[test]
    fn test_fold_import_groups() {
        let text = r#"
<|>use std::str;
use std::vec;
use std::io as iop;<|>

<|>use std::mem;
use std::f64;<|>

use std::collections::HashMap;
// Some random comment
use std::collections::VecDeque;

fn main() {
}"#;

        let folds = &[FoldKind::Imports, FoldKind::Imports];
        do_check(text, folds);
    }

    #[test]
    fn test_fold_import_and_groups() {
        let text = r#"
<|>use std::str;
use std::vec;
use std::io as iop;<|>

<|>use std::mem;
use std::f64;<|>

<|>use std::collections::{
    HashMap,
    VecDeque,
};<|>
// Some random comment

fn main() {
}"#;

        let folds = &[FoldKind::Imports, FoldKind::Imports, FoldKind::Imports];
        do_check(text, folds);
    }

}
<|endoftext|>