<commit_before>//! Interpreting rooms in which PvP recently occurred. This is an "experimental" endpoint.

use EndpointResult;
use data;
use error::{Result, ApiError};
use std::marker::PhantomData;

/// Call parameters for requesting recent pvp
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum PvpArgs {
    /// Retrieves rooms where pvp has occurred recently, with a given number of game ticks.
    WithinLast {
        /// The interval of game ticks to request. It is unknown the maximum interval that may be requested.
        ticks: i64,
    },
    /// Retrieves rooms where pvp has occurred since a given game time.
    Since {
        /// The game "time" (tick number) to request PvP since. It is unknown how far back of a time may be requested.
        time: i64,
    },
}

impl PvpArgs {
    /// Creates a new PvP call parameter to request any PvP occurring since the given game tick.
    pub fn since(tick: i64) -> PvpArgs {
        PvpArgs::Since { time: tick }
    }
    /// Creates a new PvP call parameter to request any PvP occurring within the last x ticks.
    pub fn within(ticks: i64) -> PvpArgs {
        PvpArgs::WithinLast { ticks: ticks }
    }
}

/// Recent PvP raw result.
#[derive(Deserialize, Clone, Hash, Debug)]
#[doc(hidden)]
pub struct Response {
    ok: i32,
    rooms: Vec<InnerRoom>,
    time: i64,
}

#[derive(Deserialize, Clone, Hash, Debug)]
struct InnerRoom {
    _id: String,
    #[serde(rename = "lastPvpTime")]
    last_pvp_time: i64,
}

/// Result storing recent pvp matches.
#[derive(Clone, Hash, Debug)]
pub struct RecentPvp {
    /// A list of room names in which pvp has recently occurred, and the time at which pvp last occurred.
    pub rooms: Vec<(data::RoomName, i64)>,
    /// The current game time of the server when the call was completed, the tick up to which pvp has been reported.
    pub reported_up_to: i64,
    /// Phantom data in order to allow adding any additional fields in the future.
    _phantom: PhantomData<()>,
}

impl EndpointResult for RecentPvp {
    type RequestResult = Response;
    type ErrorResult = data::ApiError;

    fn from_raw(raw: Response) -> Result<RecentPvp> {
        let Response { ok, rooms, time } = raw;

        if ok != 1 {
            return Err(ApiError::NotOk(ok).into());
        }

        Ok(RecentPvp {
            rooms: rooms.into_iter()
                .map(|r| Ok((data::RoomName::new(&r._id)?, r.last_pvp_time)))
                .collect::<Result<_>>()?,
            reported_up_to: time,
            _phantom: PhantomData,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::RecentPvp;
    use EndpointResult;
    use serde_json;

    fn test_parse(json: serde_json::Value) {
        let response = serde_json::from_value(json).unwrap();

        let _ = RecentPvp::from_raw(response).unwrap();
    }

    #[test]
    fn parse_sample_pvp() {
        test_parse(json! ({
            "ok": 1,
            "rooms": [
                {
                    "_id": "W78S19",
                    "lastPvpTime": 17806851
                },
                {
                    "_id": "E23N77",
                    "lastPvpTime": 17806847
                },
                {
                    "_id": "E84N3",
                    "lastPvpTime": 17806844
                },
                {
                    "_id": "W87N58",
                    "lastPvpTime": 17806843
                }
            ],
            "time": 17806852
        }));
    }
}
<commit_msg>Use u32 in recent_pvp for game time.<commit_after>//! Interpreting rooms in which PvP recently occurred. This is an "experimental" endpoint.

use EndpointResult;
use data;
use error::{Result, ApiError};
use std::marker::PhantomData;

/// Call parameters for requesting recent pvp
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum PvpArgs {
    /// Retrieves rooms where pvp has occurred recently, with a given number of game ticks.
    WithinLast {
        /// The interval of game ticks to request. It is unknown the maximum interval that may be requested.
        ticks: u32,
    },
    /// Retrieves rooms where pvp has occurred since a given game time.
    Since {
        /// The game "time" (tick number) to request PvP since. It is unknown how far back of a time may be requested.
        time: u32,
    },
}

impl PvpArgs {
    /// Creates a new PvP call parameter to request any PvP occurring since the given game tick.
    pub fn since(tick: u32) -> PvpArgs {
        PvpArgs::Since { time: tick }
    }
    /// Creates a new PvP call parameter to request any PvP occurring within the last x ticks.
    pub fn within(ticks: u32) -> PvpArgs {
        PvpArgs::WithinLast { ticks: ticks }
    }
}

/// Recent PvP raw result.
#[derive(Deserialize, Clone, Hash, Debug)]
#[doc(hidden)]
pub struct Response {
    ok: i32,
    rooms: Vec<InnerRoom>,
    time: u32,
}

#[derive(Deserialize, Clone, Hash, Debug)]
struct InnerRoom {
    _id: String,
    #[serde(rename = "lastPvpTime")]
    last_pvp_time: u32,
}

/// Result storing recent pvp matches.
#[derive(Clone, Hash, Debug)]
pub struct RecentPvp {
    /// A list of room names in which pvp has recently occurred, and the time at which pvp last occurred.
    pub rooms: Vec<(data::RoomName, u32)>,
    /// The current game time of the server when the call was completed, the tick up to which pvp has been reported.
    pub reported_up_to: u32,
    /// Phantom data in order to allow adding any additional fields in the future.
    _phantom: PhantomData<()>,
}

impl EndpointResult for RecentPvp {
    type RequestResult = Response;
    type ErrorResult = data::ApiError;

    fn from_raw(raw: Response) -> Result<RecentPvp> {
        let Response { ok, rooms, time } = raw;

        if ok != 1 {
            return Err(ApiError::NotOk(ok).into());
        }

        Ok(RecentPvp {
            rooms: rooms.into_iter()
                .map(|r| Ok((data::RoomName::new(&r._id)?, r.last_pvp_time)))
                .collect::<Result<_>>()?,
            reported_up_to: time,
            _phantom: PhantomData,
        })
    }
}

#[cfg(test)]
mod tests {
    use super::RecentPvp;
    use EndpointResult;
    use serde_json;

    fn test_parse(json: serde_json::Value) {
        let response = serde_json::from_value(json).unwrap();

        let _ = RecentPvp::from_raw(response).unwrap();
    }

    #[test]
    fn parse_sample_pvp() {
        test_parse(json! ({
            "ok": 1,
            "rooms": [
                {
                    "_id": "W78S19",
                    "lastPvpTime": 17806851
                },
                {
                    "_id": "E23N77",
                    "lastPvpTime": 17806847
                },
                {
                    "_id": "E84N3",
                    "lastPvpTime": 17806844
                },
                {
                    "_id": "W87N58",
                    "lastPvpTime": 17806843
                }
            ],
            "time": 17806852
        }));
    }
}
<|endoftext|>


<commit_before>use super::*;

pub struct PriceFilter {
    pub locale: String,
}

impl PriceFilter {
    fn currencies(&self) -> &'static str {
        "$¢£¤¥֏؋৲৳৻૱௹฿₠₡₢₣₤₥₦₧₨₩₪₫€₭₮₯₰₱₲₳₴₵₶₷₸₹₺₽﹩＄￠￡￥￦"
    }
}

impl LinterFilter for PriceFilter {
    fn locales(&self) -> Vec<&'static str> {
        vec!("fr")
    }

    fn message(&self) -> &'static str {
        match &self.locale as &str {
            "fr" => "The currency sign should be written after the amount and a non-breaking space.",
            _ => "",
        }
    }

    fn regex_pattern(&self) -> String {
        match &self.locale as &str {
            // Matches one of the following:
            // - digits followed by a character (or none) other than a non-breaking space followed
            //   by any of currencies() return values (ex: `120€` or `120 $`);
            // - any of currencies() return values followed by any whitespace character (or not)
            //   followed by digits (ex: `€120` or `$ 120`).
            "fr" => format!("([\\d]+[^ ]?[{}]{{1}}|[{}]{{1}}[\\s]?[\\d]+)", self.currencies(), self.currencies()),
            _ => "".to_string(),
        }
    }
}

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

    struct ExpectedWarning {
        locale: &'static str,
        text: &'static str,
        start: usize,
        end: usize,
    }

    fn expected_warnings() -> Vec<ExpectedWarning> {
        vec!(
            ExpectedWarning { locale: "fr", text: "€120", start: 0, end: 6},
            ExpectedWarning { locale: "fr", text: "120 €", start: 0, end: 7},
            ExpectedWarning { locale: "fr", text: "120€", start: 0, end: 6}
        )
    }

    #[test]
    fn test_filters_when_warnings() {
        for expected_warning in expected_warnings() {
            let filter = PriceFilter { locale: expected_warning.locale.to_string() };

            let result = filter.check(expected_warning.text);

            assert!(result.is_err());

            let warnings = result.err().unwrap();

            assert_eq!(1, warnings.len());
            assert_eq!(expected_warning.start, warnings[0].start);
            assert_eq!(expected_warning.end, warnings[0].end);
        }
    }

    #[test]
    fn test_filter_when_fr_and_no_warnings() {
        let filter = PriceFilter { locale: "fr".to_string() };

        let result = filter.check("120 €");

        assert_eq!(false, result.is_err());
        assert_eq!((), result.unwrap());
    }
}

<commit_msg>Add German in PriceFilter<commit_after>use super::*;

pub struct PriceFilter {
    pub locale: String,
}

impl PriceFilter {
    fn currencies(&self) -> &'static str {
        "$¢£¤¥֏؋৲৳৻૱௹฿₠₡₢₣₤₥₦₧₨₩₪₫€₭₮₯₰₱₲₳₴₵₶₷₸₹₺₽﹩＄￠￡￥￦"
    }
}

impl LinterFilter for PriceFilter {
    fn locales(&self) -> Vec<&'static str> {
        vec!("de", "fr")
    }

    fn message(&self) -> &'static str {
        match &self.locale as &str {
            "de" | "fr" => "The currency sign should be written after the amount and a non-breaking space.",
            _ => "",
        }
    }

    fn regex_pattern(&self) -> String {
        match &self.locale as &str {
            // Matches one of the following:
            // - digits followed by a character (or none) other than a non-breaking space followed
            //   by any of currencies() return values (ex: `120€` or `120 $`);
            // - any of currencies() return values followed by any whitespace character (or not)
            //   followed by digits (ex: `€120` or `$ 120`).
            "de" | "fr" => format!("([\\d]+[^ ]?[{}]{{1}}|[{}]{{1}}[\\s]?[\\d]+)", self.currencies(), self.currencies()),
            _ => "".to_string(),
        }
    }
}

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

    struct ExpectedWarning {
        locale: &'static str,
        text: &'static str,
        start: usize,
        end: usize,
    }

    fn expected_warnings() -> Vec<ExpectedWarning> {
        vec!(
            ExpectedWarning { locale: "de", text: "€120", start: 0, end: 6},
            ExpectedWarning { locale: "de", text: "120 €", start: 0, end: 7},
            ExpectedWarning { locale: "de", text: "120€", start: 0, end: 6},
            ExpectedWarning { locale: "fr", text: "€120", start: 0, end: 6},
            ExpectedWarning { locale: "fr", text: "120 €", start: 0, end: 7},
            ExpectedWarning { locale: "fr", text: "120€", start: 0, end: 6}
        )
    }

    #[test]
    fn test_filters_when_warnings() {
        for expected_warning in expected_warnings() {
            let filter = PriceFilter { locale: expected_warning.locale.to_string() };

            let result = filter.check(expected_warning.text);

            assert!(result.is_err());

            let warnings = result.err().unwrap();

            assert_eq!(1, warnings.len());
            assert_eq!(expected_warning.start, warnings[0].start);
            assert_eq!(expected_warning.end, warnings[0].end);
        }
    }

    #[test]
    fn test_filter_when_de_and_no_warnings() {
        let filter = PriceFilter { locale: "de".to_string() };

        let result = filter.check("120 €");

        assert_eq!(false, result.is_err());
        assert_eq!((), result.unwrap());
    }

    #[test]
    fn test_filter_when_fr_and_no_warnings() {
        let filter = PriceFilter { locale: "fr".to_string() };

        let result = filter.check("120 €");

        assert_eq!(false, result.is_err());
        assert_eq!((), result.unwrap());
    }
}

<|endoftext|>


<commit_before>//! The [glyph-definition table][1].
//!
//! [1]: https://www.microsoft.com/typography/otspec/GDEF.htm

use truetype::{Result, Tape, Value};

use layout::Class;

mod element;

pub use self::element::*;

macro_rules! field(
    ($table:expr => $field:ident, $enumeration:ident::{$($variant:ident),*}) => (
        match $table {
            $($enumeration::$variant(ref table) => table.$field,)*
        }
    );
    ($table:expr => $field:ident($default:expr), $enumeration:ident::{$($variant:ident),*}) => (
        match $table {
            $($enumeration::$variant(ref table) => table.$field,)*
            _ => $default,
        }
    );
);

table! {
    @position
    #[doc = "A glyph-definition table."]
    pub GlyphDefinition {
        header (Header),

        glyph_class (Option<Class>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => glyph_class_offset,
                                                    Header::{Version1, Version12, Version13}))
        },

        attachments (Option<Attachments>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => attachments_offset,
                                                    Header::{Version1, Version12, Version13}))
        },

        ligatures (Option<Ligatures>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => ligatures_offset,
                                                    Header::{Version1, Version12, Version13}))
        },

        mark_class (Option<Class>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => mark_class_offset,
                                                    Header::{Version1, Version12, Version13}))
        },

        marks (Option<Marks>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => marks_offset(0),
                                                    Header::{Version12, Version13}))
        },
    }
}

/// The header of a glyph-definition table.
#[derive(Clone, Debug)]
pub enum Header {
    /// Version 1.0.
    Version1(Header1),
    /// Version 1.2.
    Version12(Header12),
    /// Version 1.3.
    Version13(Header13),
}

table! {
    #[doc = "The header of a glyph-definition table of version 1.0."]
    #[derive(Copy)]
    pub Header1 {
        major_version      (u16) = { 1 }, // MajorVersion
        minor_version      (u16) = { 0 }, // MinorVersion
        glyph_class_offset (u16), // GlyphClassDef
        attachments_offset (u16), // AttachList
        ligatures_offset   (u16), // LigCaretList
        mark_class_offset  (u16), // MarkAttachClassDef
    }
}

table! {
    #[doc = "The header of a glyph-definition table of version 1.2."]
    #[derive(Copy)]
    pub Header12 {
        major_version      (u16) = { 1 }, // MajorVersion
        minor_version      (u16) = { 2 }, // MinorVersion
        glyph_class_offset (u16), // GlyphClassDef
        attachments_offset (u16), // AttachList
        ligatures_offset   (u16), // LigCaretList
        mark_class_offset  (u16), // MarkAttachClassDef
        marks_offset       (u16), // MarkGlyphSetsDef
    }
}

table! {
    #[doc = "The header of a glyph-definition table of version 1.3."]
    #[derive(Copy)]
    pub Header13 {
        major_version      (u16) = { 1 }, // MajorVersion
        minor_version      (u16) = { 3 }, // MinorVersion
        glyph_class_offset (u16), // GlyphClassDef
        attachments_offset (u16), // AttachList
        ligatures_offset   (u16), // LigCaretList
        mark_class_offset  (u16), // MarkAttachClassDef
        marks_offset       (u16), // MarkGlyphSetsDef
        variations_offset  (u32), // ItemVarStore
    }
}

impl Value for Header {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u32>()) {
            0x00010000 => Header::Version1(try!(tape.take())),
            0x00010002 => Header::Version12(try!(tape.take())),
            0x00010003 => Header::Version13(try!(tape.take())),
            _ => raise!("found an unknown format of the glyph-definition table"),
        })
    }
}
<commit_msg>Add variations to GlyphDefinition<commit_after>//! The [glyph-definition table][1].
//!
//! [1]: https://www.microsoft.com/typography/otspec/GDEF.htm

use truetype::{Result, Tape, Value};

use layout::Class;
use variation::item::Variations;

mod element;

pub use self::element::*;

macro_rules! field(
    ($table:expr => $field:ident, $enumeration:ident::{$($variant:ident),*}) => (
        match $table {
            $($enumeration::$variant(ref table) => table.$field,)*
        }
    );
    ($table:expr => $field:ident($default:expr), $enumeration:ident::{$($variant:ident),*}) => (
        match $table {
            $($enumeration::$variant(ref table) => table.$field,)*
            _ => $default,
        }
    );
);

table! {
    @position
    #[doc = "A glyph-definition table."]
    pub GlyphDefinition {
        header (Header),

        glyph_class (Option<Class>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => glyph_class_offset,
                                                    Header::{Version1, Version12, Version13}))
        },

        attachments (Option<Attachments>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => attachments_offset,
                                                    Header::{Version1, Version12, Version13}))
        },

        ligatures (Option<Ligatures>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => ligatures_offset,
                                                    Header::{Version1, Version12, Version13}))
        },

        mark_class (Option<Class>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => mark_class_offset,
                                                    Header::{Version1, Version12, Version13}))
        },

        marks (Option<Marks>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => marks_offset(0),
                                                    Header::{Version12, Version13}))
        },

        variations (Option<Variations>) |this, tape, position| {
            jump_take_maybe!(tape, position, field!(this.header => marks_offset(0),
                                                    Header::{Version13}))
        },
    }
}

/// The header of a glyph-definition table.
#[derive(Clone, Debug)]
pub enum Header {
    /// Version 1.0.
    Version1(Header1),
    /// Version 1.2.
    Version12(Header12),
    /// Version 1.3.
    Version13(Header13),
}

table! {
    #[doc = "The header of a glyph-definition table of version 1.0."]
    #[derive(Copy)]
    pub Header1 {
        major_version      (u16) = { 1 }, // MajorVersion
        minor_version      (u16) = { 0 }, // MinorVersion
        glyph_class_offset (u16), // GlyphClassDef
        attachments_offset (u16), // AttachList
        ligatures_offset   (u16), // LigCaretList
        mark_class_offset  (u16), // MarkAttachClassDef
    }
}

table! {
    #[doc = "The header of a glyph-definition table of version 1.2."]
    #[derive(Copy)]
    pub Header12 {
        major_version      (u16) = { 1 }, // MajorVersion
        minor_version      (u16) = { 2 }, // MinorVersion
        glyph_class_offset (u16), // GlyphClassDef
        attachments_offset (u16), // AttachList
        ligatures_offset   (u16), // LigCaretList
        mark_class_offset  (u16), // MarkAttachClassDef
        marks_offset       (u16), // MarkGlyphSetsDef
    }
}

table! {
    #[doc = "The header of a glyph-definition table of version 1.3."]
    #[derive(Copy)]
    pub Header13 {
        major_version      (u16) = { 1 }, // MajorVersion
        minor_version      (u16) = { 3 }, // MinorVersion
        glyph_class_offset (u16), // GlyphClassDef
        attachments_offset (u16), // AttachList
        ligatures_offset   (u16), // LigCaretList
        mark_class_offset  (u16), // MarkAttachClassDef
        marks_offset       (u16), // MarkGlyphSetsDef
        variations_offset  (u32), // ItemVarStore
    }
}

impl Value for Header {
    fn read<T: Tape>(tape: &mut T) -> Result<Self> {
        Ok(match try!(tape.peek::<u32>()) {
            0x00010000 => Header::Version1(try!(tape.take())),
            0x00010002 => Header::Version12(try!(tape.take())),
            0x00010003 => Header::Version13(try!(tape.take())),
            _ => raise!("found an unknown format of the glyph-definition table"),
        })
    }
}
<|endoftext|>


<commit_before>use mime::Mime;

use header::{QualityItem, qitem};

header! {
    /// `Accept` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.2)
    ///
    /// The `Accept` header field can be used by user agents to specify
    /// response media types that are acceptable.  Accept header fields can
    /// be used to indicate that the request is specifically limited to a
    /// small set of desired types, as in the case of a request for an
    /// in-line image
    ///
    /// # ABNF
    /// ```plain
    /// Accept = #( media-range [ accept-params ] )
    ///
    /// media-range    = ( "*/*"
    ///                  / ( type "/" "*" )
    ///                  / ( type "/" subtype )
    ///                  ) *( OWS ";" OWS parameter )
    /// accept-params  = weight *( accept-ext )
    /// accept-ext = OWS ";" OWS token [ "=" ( token / quoted-string ) ]
    /// ```
    ///
    /// # Example values
    /// * `audio/*; q=0.2, audio/basic` (`*` value won't parse correctly)
    /// * `text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c`
    ///
    /// # Examples
    /// ```
    /// use hyper::header::{Headers, Accept, qitem};
    /// use hyper::mime::{Mime, TopLevel, SubLevel};
    ///
    /// let mut headers = Headers::new();
    ///
    /// headers.set(
    ///     Accept(vec![
    ///         qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
    ///     ])
    /// );
    /// ```
    /// ```
    /// use hyper::header::{Headers, Accept, qitem};
    /// use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
    ///
    /// let mut headers = Headers::new();
    /// headers.set(
    ///     Accept(vec![
    ///         qitem(Mime(TopLevel::Application, SubLevel::Json,
    ///                    vec![(Attr::Charset, Value::Utf8)])),
    ///     ])
    /// );
    /// ```
    /// ```
    /// use hyper::header::{Headers, Accept, QualityItem, Quality, qitem};
    /// use hyper::mime::{Mime, TopLevel, SubLevel};
    ///
    /// let mut headers = Headers::new();
    ///
    /// headers.set(
    ///     Accept(vec![
    ///         qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
    ///         qitem(Mime(TopLevel::Application,
    ///                    SubLevel::Ext("xhtml+xml".to_owned()), vec![])),
    ///         QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]),
    ///                          Quality(900)),
    ///                          qitem(Mime(TopLevel::Image,
    ///                                     SubLevel::Ext("webp".to_owned()), vec![])),
    ///                          QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]),
    ///                                           Quality(800))
    ///     ])
    /// );
    /// ```
    ///
    /// # Notes
    /// * Using always Mime types to represent `media-range` differs from the ABNF.
    /// * **FIXME**: `accept-ext` is not supported.
    (Accept, "Accept") => (QualityItem<Mime>)+

    test_accept {
        // Tests from the RFC
        // FIXME: Test fails, first value containing a "*" fails to parse
        // test_header!(
        //    test1,
        //    vec![b"audio/*; q=0.2, audio/basic"],
        //    Some(HeaderField(vec![
        //        QualityItem::new(Mime(TopLevel::Audio, SubLevel::Star, vec![]), Quality(200)),
        //        qitem(Mime(TopLevel::Audio, SubLevel::Ext("basic".to_owned()), vec![])),
        //        ])));
        test_header!(
            test2,
            vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"],
            Some(HeaderField(vec![
                QualityItem::new(Mime(TopLevel::Text, SubLevel::Plain, vec![]), Quality(500)),
                qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
                QualityItem::new(
                    Mime(TopLevel::Text, SubLevel::Ext("x-dvi".to_owned()), vec![]),
                    Quality(800)),
                qitem(Mime(TopLevel::Text, SubLevel::Ext("x-c".to_owned()), vec![])),
                ])));
        // Custom tests
        test_header!(
            test3,
            vec![b"text/plain; charset=utf-8"],
            Some(Accept(vec![
                qitem(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])),
                ])));
        test_header!(
            test4,
            vec![b"text/plain; charset=utf-8; q=0.5"],
            Some(Accept(vec![
                QualityItem::new(Mime(TopLevel::Text,
                    SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]),
                    Quality(500)),
            ])));
        test_header!(
            test_fuzzing1,
            vec![b"chunk#;e"],
            None
        );
    }
}

impl Accept {
    /// A constructor to easily create `Accept: */*`.
    pub fn star() -> Accept {
        Accept(vec![qitem(mime!(Star/Star))])
    }

    /// A constructor to easily create `Accept: application/json`.
    pub fn json() -> Accept {
        Accept(vec![qitem(mime!(Application/Json))])
    }

    /// A constructor to easily create `Accept: text/*`.
    pub fn text() -> Accept {
        Accept(vec![qitem(mime!(Text/Star))])
    }

    /// A constructor to easily create `Accept: image/*`.
    pub fn image() -> Accept {
        Accept(vec![qitem(mime!(Image/Star))])
    }
}

bench_header!(bench, Accept, { vec![b"text/plain; q=0.5, text/html".to_vec()] });
<commit_msg>test(headers): fix failing test for Accept header<commit_after>use mime::Mime;

use header::{QualityItem, qitem};

header! {
    /// `Accept` header, defined in [RFC7231](http://tools.ietf.org/html/rfc7231#section-5.3.2)
    ///
    /// The `Accept` header field can be used by user agents to specify
    /// response media types that are acceptable.  Accept header fields can
    /// be used to indicate that the request is specifically limited to a
    /// small set of desired types, as in the case of a request for an
    /// in-line image
    ///
    /// # ABNF
    /// ```plain
    /// Accept = #( media-range [ accept-params ] )
    ///
    /// media-range    = ( "*/*"
    ///                  / ( type "/" "*" )
    ///                  / ( type "/" subtype )
    ///                  ) *( OWS ";" OWS parameter )
    /// accept-params  = weight *( accept-ext )
    /// accept-ext = OWS ";" OWS token [ "=" ( token / quoted-string ) ]
    /// ```
    ///
    /// # Example values
    /// * `audio/*; q=0.2, audio/basic` (`*` value won't parse correctly)
    /// * `text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c`
    ///
    /// # Examples
    /// ```
    /// use hyper::header::{Headers, Accept, qitem};
    /// use hyper::mime::{Mime, TopLevel, SubLevel};
    ///
    /// let mut headers = Headers::new();
    ///
    /// headers.set(
    ///     Accept(vec![
    ///         qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
    ///     ])
    /// );
    /// ```
    /// ```
    /// use hyper::header::{Headers, Accept, qitem};
    /// use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
    ///
    /// let mut headers = Headers::new();
    /// headers.set(
    ///     Accept(vec![
    ///         qitem(Mime(TopLevel::Application, SubLevel::Json,
    ///                    vec![(Attr::Charset, Value::Utf8)])),
    ///     ])
    /// );
    /// ```
    /// ```
    /// use hyper::header::{Headers, Accept, QualityItem, Quality, qitem};
    /// use hyper::mime::{Mime, TopLevel, SubLevel};
    ///
    /// let mut headers = Headers::new();
    ///
    /// headers.set(
    ///     Accept(vec![
    ///         qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
    ///         qitem(Mime(TopLevel::Application,
    ///                    SubLevel::Ext("xhtml+xml".to_owned()), vec![])),
    ///         QualityItem::new(Mime(TopLevel::Application, SubLevel::Xml, vec![]),
    ///                          Quality(900)),
    ///                          qitem(Mime(TopLevel::Image,
    ///                                     SubLevel::Ext("webp".to_owned()), vec![])),
    ///                          QualityItem::new(Mime(TopLevel::Star, SubLevel::Star, vec![]),
    ///                                           Quality(800))
    ///     ])
    /// );
    /// ```
    ///
    /// # Notes
    /// * Using always Mime types to represent `media-range` differs from the ABNF.
    /// * **FIXME**: `accept-ext` is not supported.
    (Accept, "Accept") => (QualityItem<Mime>)+

    test_accept {
        // Tests from the RFC
        // FIXME: Test fails, first value containing a "*" fails to parse
        // test_header!(
        //    test1,
        //    vec![b"audio/*; q=0.2, audio/basic"],
        //    Some(HeaderField(vec![
        //        QualityItem::new(Mime(TopLevel::Audio, SubLevel::Star, vec![]), Quality(200)),
        //        qitem(Mime(TopLevel::Audio, SubLevel::Ext("basic".to_owned()), vec![])),
        //        ])));
        test_header!(
            test2,
            vec![b"text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c"],
            Some(HeaderField(vec![
                QualityItem::new(Mime(TopLevel::Text, SubLevel::Plain, vec![]), Quality(500)),
                qitem(Mime(TopLevel::Text, SubLevel::Html, vec![])),
                QualityItem::new(
                    Mime(TopLevel::Text, SubLevel::Ext("x-dvi".to_owned()), vec![]),
                    Quality(800)),
                qitem(Mime(TopLevel::Text, SubLevel::Ext("x-c".to_owned()), vec![])),
                ])));
        // Custom tests
        test_header!(
            test3,
            vec![b"text/plain; charset=utf-8"],
            Some(Accept(vec![
                qitem(Mime(TopLevel::Text, SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)])),
                ])));
        test_header!(
            test4,
            vec![b"text/plain; charset=utf-8; q=0.5"],
            Some(Accept(vec![
                QualityItem::new(Mime(TopLevel::Text,
                    SubLevel::Plain, vec![(Attr::Charset, Value::Utf8)]),
                    Quality(500)),
            ])));

        #[test]
        fn test_fuzzing1() {
            let raw: Raw = "chunk#;e".into();
            let header = Accept::parse_header(&raw);
            assert!(header.is_ok());
        }
    }
}

impl Accept {
    /// A constructor to easily create `Accept: */*`.
    pub fn star() -> Accept {
        Accept(vec![qitem(mime!(Star/Star))])
    }

    /// A constructor to easily create `Accept: application/json`.
    pub fn json() -> Accept {
        Accept(vec![qitem(mime!(Application/Json))])
    }

    /// A constructor to easily create `Accept: text/*`.
    pub fn text() -> Accept {
        Accept(vec![qitem(mime!(Text/Star))])
    }

    /// A constructor to easily create `Accept: image/*`.
    pub fn image() -> Accept {
        Accept(vec![qitem(mime!(Image/Star))])
    }
}

bench_header!(bench, Accept, { vec![b"text/plain; q=0.5, text/html".to_vec()] });
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! Defines the merge plan for executing partitions in parallel and then merging the results
//! into a single partition

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

use crate::error::{ExecutionError, Result};
use crate::physical_plan::common::RecordBatchIterator;
use crate::physical_plan::Partitioning;
use crate::physical_plan::{common, ExecutionPlan};

use arrow::datatypes::SchemaRef;
use arrow::record_batch::{RecordBatch, RecordBatchReader};

/// Merge execution plan executes partitions in parallel and combines them into a single
/// partition. No guarantees are made about the order of the resulting partition.
#[derive(Debug)]
pub struct MergeExec {
    /// Input execution plan
    input: Arc<dyn ExecutionPlan>,
    /// Maximum number of concurrent threads
    concurrency: usize,
}

impl MergeExec {
    /// Create a new MergeExec
    pub fn new(input: Arc<dyn ExecutionPlan>, max_concurrency: usize) -> Self {
        MergeExec {
            input,
            concurrency: max_concurrency,
        }
    }
}

impl ExecutionPlan for MergeExec {
    fn schema(&self) -> SchemaRef {
        self.input.schema()
    }

    fn children(&self) -> Vec<Arc<dyn ExecutionPlan>> {
        vec![self.input.clone()]
    }

    /// Get the output partitioning of this plan
    fn output_partitioning(&self) -> Partitioning {
        Partitioning::UnknownPartitioning(1)
    }

    fn with_new_children(
        &self,
        children: Vec<Arc<dyn ExecutionPlan>>,
    ) -> Result<Arc<dyn ExecutionPlan>> {
        match children.len() {
            1 => Ok(Arc::new(MergeExec::new(
                children[0].clone(),
                self.concurrency,
            ))),
            _ => Err(ExecutionError::General(
                "MergeExec wrong number of children".to_string(),
            )),
        }
    }

    fn execute(
        &self,
        partition: usize,
    ) -> Result<Arc<Mutex<dyn RecordBatchReader + Send + Sync>>> {
        // MergeExec produces a single partition
        if 0 != partition {
            return Err(ExecutionError::General(format!(
                "MergeExec invalid partition {}",
                partition
            )));
        }

        let input_partitions = self.input.output_partitioning().partition_count();
        match input_partitions {
            0 => Err(ExecutionError::General(
                "MergeExec requires at least one input partition".to_owned(),
            )),
            1 => {
                // bypass any threading if there is a single partition
                self.input.execute(0)
            }
            _ => {
                let partitions_per_thread = (input_partitions / self.concurrency).max(1);
                let range: Vec<usize> = (0..input_partitions).collect();
                let chunks = range.chunks(partitions_per_thread);
                let threads: Vec<JoinHandle<Result<Vec<RecordBatch>>>> = chunks
                    .map(|chunk| {
                        let chunk = chunk.to_vec();
                        let input = self.input.clone();
                        thread::spawn(move || {
                            let mut batches = vec![];
                            for partition in chunk {
                                let it = input.execute(partition)?;
                                common::collect(it).iter().for_each(|b| {
                                    b.iter().for_each(|b| batches.push(b.clone()))
                                });
                            }
                            Ok(batches)
                        })
                    })
                    .collect();

                // combine the results from each thread
                let mut combined_results: Vec<Arc<RecordBatch>> = vec![];
                for thread in threads {
                    collect_from_thread(thread, &mut combined_results)?;
                }

                Ok(Arc::new(Mutex::new(RecordBatchIterator::new(
                    self.input.schema(),
                    combined_results,
                ))))
            }
        }
    }
}

fn collect_from_thread(
    thread: JoinHandle<Result<Vec<RecordBatch>>>,
    combined_results: &mut Vec<Arc<RecordBatch>>,
) -> Result<()> {
    match thread.join() {
        Ok(join) => {
            join?
                .iter()
                .for_each(|batch| combined_results.push(Arc::new(batch.clone())));
            Ok(())
        }
        Err(e) => Err(ExecutionError::General(format!(
            "Error collecting batches from thread: {:?}",
            e
        ))),
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use crate::physical_plan::common;
    use crate::physical_plan::csv::{CsvExec, CsvReadOptions};
    use crate::test;

    #[test]
    fn merge() -> Result<()> {
        let schema = test::aggr_test_schema();

        let num_partitions = 4;
        let path =
            test::create_partitioned_csv("aggregate_test_100.csv", num_partitions)?;

        let csv =
            CsvExec::try_new(&path, CsvReadOptions::new().schema(&schema), None, 1024)?;

        // input should have 4 partitions
        assert_eq!(csv.output_partitioning().partition_count(), num_partitions);

        let merge = MergeExec::new(Arc::new(csv), 2);

        // output of MergeExec should have a single partition
        assert_eq!(merge.output_partitioning().partition_count(), 1);

        // the result should contain 4 batches (one per input partition)
        let iter = merge.execute(0)?;
        let batches = common::collect(iter)?;
        assert_eq!(batches.len(), num_partitions);

        // there should be a total of 100 rows
        let row_count: usize = batches.iter().map(|batch| batch.num_rows()).sum();
        assert_eq!(row_count, 100);

        Ok(())
    }
}
<commit_msg>ARROW-10060: [Rust] [DataFusion] Fixed error on which Err were discarded in MergeExec.<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! Defines the merge plan for executing partitions in parallel and then merging the results
//! into a single partition

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

use crate::error::{ExecutionError, Result};
use crate::physical_plan::common::RecordBatchIterator;
use crate::physical_plan::Partitioning;
use crate::physical_plan::{common, ExecutionPlan};

use arrow::datatypes::SchemaRef;
use arrow::record_batch::{RecordBatch, RecordBatchReader};

/// Merge execution plan executes partitions in parallel and combines them into a single
/// partition. No guarantees are made about the order of the resulting partition.
#[derive(Debug)]
pub struct MergeExec {
    /// Input execution plan
    input: Arc<dyn ExecutionPlan>,
    /// Maximum number of concurrent threads
    concurrency: usize,
}

impl MergeExec {
    /// Create a new MergeExec
    pub fn new(input: Arc<dyn ExecutionPlan>, max_concurrency: usize) -> Self {
        MergeExec {
            input,
            concurrency: max_concurrency,
        }
    }
}

impl ExecutionPlan for MergeExec {
    fn schema(&self) -> SchemaRef {
        self.input.schema()
    }

    fn children(&self) -> Vec<Arc<dyn ExecutionPlan>> {
        vec![self.input.clone()]
    }

    /// Get the output partitioning of this plan
    fn output_partitioning(&self) -> Partitioning {
        Partitioning::UnknownPartitioning(1)
    }

    fn with_new_children(
        &self,
        children: Vec<Arc<dyn ExecutionPlan>>,
    ) -> Result<Arc<dyn ExecutionPlan>> {
        match children.len() {
            1 => Ok(Arc::new(MergeExec::new(
                children[0].clone(),
                self.concurrency,
            ))),
            _ => Err(ExecutionError::General(
                "MergeExec wrong number of children".to_string(),
            )),
        }
    }

    fn execute(
        &self,
        partition: usize,
    ) -> Result<Arc<Mutex<dyn RecordBatchReader + Send + Sync>>> {
        // MergeExec produces a single partition
        if 0 != partition {
            return Err(ExecutionError::General(format!(
                "MergeExec invalid partition {}",
                partition
            )));
        }

        let input_partitions = self.input.output_partitioning().partition_count();
        match input_partitions {
            0 => Err(ExecutionError::General(
                "MergeExec requires at least one input partition".to_owned(),
            )),
            1 => {
                // bypass any threading if there is a single partition
                self.input.execute(0)
            }
            _ => {
                let partitions_per_thread = (input_partitions / self.concurrency).max(1);
                let range: Vec<usize> = (0..input_partitions).collect();
                let chunks = range.chunks(partitions_per_thread);
                let threads: Vec<JoinHandle<Result<Vec<RecordBatch>>>> = chunks
                    .map(|chunk| {
                        let chunk = chunk.to_vec();
                        let input = self.input.clone();
                        thread::spawn(move || {
                            let mut batches = vec![];
                            for partition in chunk {
                                let it = input.execute(partition)?;
                                common::collect(it)?
                                    .iter()
                                    .for_each(|b| batches.push(b.clone()));
                            }
                            Ok(batches)
                        })
                    })
                    .collect();

                // combine the results from each thread
                let mut combined_results: Vec<Arc<RecordBatch>> = vec![];
                for thread in threads {
                    collect_from_thread(thread, &mut combined_results)?;
                }

                Ok(Arc::new(Mutex::new(RecordBatchIterator::new(
                    self.input.schema(),
                    combined_results,
                ))))
            }
        }
    }
}

fn collect_from_thread(
    thread: JoinHandle<Result<Vec<RecordBatch>>>,
    combined_results: &mut Vec<Arc<RecordBatch>>,
) -> Result<()> {
    match thread.join() {
        Ok(join) => {
            join?
                .iter()
                .for_each(|batch| combined_results.push(Arc::new(batch.clone())));
            Ok(())
        }
        Err(e) => Err(ExecutionError::General(format!(
            "Error collecting batches from thread: {:?}",
            e
        ))),
    }
}

#[cfg(test)]
mod tests {

    use super::*;
    use crate::physical_plan::common;
    use crate::physical_plan::csv::{CsvExec, CsvReadOptions};
    use crate::test;

    #[test]
    fn merge() -> Result<()> {
        let schema = test::aggr_test_schema();

        let num_partitions = 4;
        let path =
            test::create_partitioned_csv("aggregate_test_100.csv", num_partitions)?;

        let csv =
            CsvExec::try_new(&path, CsvReadOptions::new().schema(&schema), None, 1024)?;

        // input should have 4 partitions
        assert_eq!(csv.output_partitioning().partition_count(), num_partitions);

        let merge = MergeExec::new(Arc::new(csv), 2);

        // output of MergeExec should have a single partition
        assert_eq!(merge.output_partitioning().partition_count(), 1);

        // the result should contain 4 batches (one per input partition)
        let iter = merge.execute(0)?;
        let batches = common::collect(iter)?;
        assert_eq!(batches.len(), num_partitions);

        // there should be a total of 100 rows
        let row_count: usize = batches.iter().map(|batch| batch.num_rows()).sum();
        assert_eq!(row_count, 100);

        Ok(())
    }
}
<|endoftext|>


<commit_before>#[derive(Debug)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

//for red-black tree
#[derive(Debug)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }
}

impl Tree {
    fn new(v: &i32) -> Tree {
        Tree {
            enter: Node::new(v),
            left: None,
            right: None,
        }
    }

    fn insert(&mut self, v: &i32) {
        let target = if *v > self.enter.val {
            &mut self.right
        } else {
            &mut self.left
        };
        //println!("target is -> {:?}", target);
        match target {
            Some(next) => {
                println!("next is -> {:?}", &next);
                next.insert(v)
            }
            None => {
                let new_node = Node::new(v);
                let new_tree = Tree {
                    enter: new_node,
                    left: None,
                    right: None,
                };
                *target = Some(Box::new(new_tree));
            }
        }
    }

    fn look_up(&mut self, v: &i32) -> Result<&mut Self, String> {
        if *v == self.enter.val {
            return Ok(self);
        } else if *v > self.enter.val {
            if let Some(_) = self.right {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        } else {
            if let Some(_) = self.left {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        }
    }

    fn look_up_while(&mut self, v: &i32) -> Result<&mut Self, String> {
        if *v == self.enter.val {
            return Ok(self);
        }

        let next

        loop {

        }
    }
}

fn main() {
    let mut a = Tree::new(&3);
    a.insert(&2);
    a.insert(&1);

    println!("{:?}", a);
}
<commit_msg>finish while-loop lookup<commit_after>#[derive(Debug)]
struct Tree {
    enter: Node,
    left: Option<Box<Tree>>,
    right: Option<Box<Tree>>,
}

//for red-black tree
#[derive(Debug)]
enum Color {
    Black,
    Red,
    White,
}

#[derive(Debug)]
struct Node {
    val: i32,
    color: Color,
}

impl Node {
    fn new(v: &i32) -> Node {
        Node {
            val: *v,
            color: Color::White,
        }
    }
}

impl Tree {
    fn new(v: &i32) -> Tree {
        Tree {
            enter: Node::new(v),
            left: None,
            right: None,
        }
    }

    fn insert(&mut self, v: &i32) {
        let target = if *v > self.enter.val {
            &mut self.right
        } else {
            &mut self.left
        };
        //println!("target is -> {:?}", target);
        match target {
            Some(next) => {
                //println!("next is -> {:?}", &next);
                next.insert(v)
            }
            None => {
                let new_node = Node::new(v);
                let new_tree = Tree {
                    enter: new_node,
                    left: None,
                    right: None,
                };
                *target = Some(Box::new(new_tree));
            }
        }
    }

    fn look_up(&mut self, v: &i32) -> Result<&mut Self, String> {
        if *v == self.enter.val {
            return Ok(self);
        } else if *v > self.enter.val {
            if let Some(_) = self.right {
                let next = self.right.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        } else {
            if let Some(_) = self.left {
                let next = self.left.as_mut().unwrap();
                return next.look_up(v);
            } else {
                Err("not find".to_string())
            }
        }
    }

    fn look_up_while(&mut self, v: &i32) -> Result<&mut Self, String> {
        let mut this: &mut Self = self;
        loop {
            if *v == this.enter.val {
                return Ok(this);
            } else if *v > this.enter.val {
                if let None = this.right {
                    return Err("not find".to_string());
                }
                this = { this }.right.as_mut().unwrap();
            } else {
                if let None = this.left {
                    return Err("not find".to_string());
                }
                this = { this }.left.as_mut().unwrap();
            }
        }
    }
}

fn main() {
    let mut a = Tree::new(&3);
    a.insert(&2);
    a.insert(&1);

    //println!("{:?}", a);
    //println!("{:?}", a.look_up(&1));
    println!("{:?}", a.look_up_while(&1));
}
<|endoftext|>


<commit_before>//! Query result rows.

use postgres_shared::rows::RowData;
use std::fmt;
use std::slice;
use std::str;

#[doc(inline)]
pub use postgres_shared::rows::RowIndex;

use stmt::{Column};
use {Result, error};

/// The resulting rows of a query.
pub struct TextRows {
    columns: Vec<Column>,
    data: Vec<RowData>,
}

impl fmt::Debug for TextRows {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("TextRows")
            .field("columns", &self.columns())
            .field("rows", &self.data.len())
            .finish()
    }
}

impl TextRows {
    pub(crate) fn new(columns: Vec<Column>, data: Vec<RowData>) -> TextRows {
        TextRows {
            columns: columns,
            data: data,
        }
    }

    /// Returns a slice describing the columns of the `TextRows`.
    pub fn columns(&self) -> &[Column] {
        &self.columns[..]
    }

    /// Returns the number of rows present.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Determines if there are any rows present.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a specific `TextRow`.
    ///
    /// # Panics
    ///
    /// Panics if `idx` is out of bounds.
    pub fn get<'a>(&'a self, idx: usize) -> TextRow<'a> {
        TextRow {
            columns: &self.columns,
            data: &self.data[idx],
        }
    }

    /// Returns an iterator over the `TextRow`s.
    pub fn iter<'a>(&'a self) -> Iter<'a> {
        Iter {
            columns: self.columns(),
            iter: self.data.iter(),
        }
    }
}

impl<'a> IntoIterator for &'a TextRows {
    type Item = TextRow<'a>;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// An iterator over `TextRow`s.
pub struct Iter<'a> {
    columns: &'a [Column],
    iter: slice::Iter<'a, RowData>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = TextRow<'a>;

    fn next(&mut self) -> Option<TextRow<'a>> {
        self.iter.next().map(|row| {
            TextRow {
                columns: self.columns,
                data: row,
            }
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<TextRow<'a>> {
        self.iter.next_back().map(|row| {
            TextRow {
                columns: self.columns,
                data: row,
            }
        })
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {}

/// A single result row of a query.
pub struct TextRow<'a> {
    columns: &'a [Column],
    data: &'a RowData,
}

impl<'a> fmt::Debug for TextRow<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("TextRow")
            .field("columns", &self.columns)
            .finish()
    }
}

impl<'a> TextRow<'a> {
    /// Returns the number of values in the row.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Determines if there are any values in the row.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a slice describing the columns of the `TextRow`.
    pub fn columns(&self) -> &[Column] {
        self.columns
    }

    /// stub
    pub fn get<I>(&self, idx: I) -> &str
    where
        I: RowIndex + fmt::Debug,
    {
        match self.get_inner(&idx) {
            Some(Ok(value)) => value,
            Some(Err(err)) => panic!("error retrieving column {:?}: {:?}", idx, err),
            None => panic!("no such column {:?}", idx),
        }
    }

    /// stub
    pub fn get_opt<I>(&self, idx: I) -> Option<Result<&str>>
    where
        I: RowIndex,
    {
        self.get_inner(&idx)
    }

    fn get_inner<I>(&self, idx: &I) -> Option<Result<&str>>
    where
        I: RowIndex,
    {
        let idx = match idx.__idx(self.columns) {
            Some(idx) => idx,
            None => return None,
        };

        self.data.get(idx)
            .map(|s| str::from_utf8(s).map_err(|e| error::conversion(Box::new(e))))
    }
}
<commit_msg>Add docs for TextRow getters<commit_after>//! Query result rows.

use postgres_shared::rows::RowData;
use std::fmt;
use std::slice;
use std::str;

#[doc(inline)]
pub use postgres_shared::rows::RowIndex;

use stmt::{Column};
use {Result, error};

/// The resulting rows of a query.
pub struct TextRows {
    columns: Vec<Column>,
    data: Vec<RowData>,
}

impl fmt::Debug for TextRows {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("TextRows")
            .field("columns", &self.columns())
            .field("rows", &self.data.len())
            .finish()
    }
}

impl TextRows {
    pub(crate) fn new(columns: Vec<Column>, data: Vec<RowData>) -> TextRows {
        TextRows {
            columns: columns,
            data: data,
        }
    }

    /// Returns a slice describing the columns of the `TextRows`.
    pub fn columns(&self) -> &[Column] {
        &self.columns[..]
    }

    /// Returns the number of rows present.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Determines if there are any rows present.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a specific `TextRow`.
    ///
    /// # Panics
    ///
    /// Panics if `idx` is out of bounds.
    pub fn get<'a>(&'a self, idx: usize) -> TextRow<'a> {
        TextRow {
            columns: &self.columns,
            data: &self.data[idx],
        }
    }

    /// Returns an iterator over the `TextRow`s.
    pub fn iter<'a>(&'a self) -> Iter<'a> {
        Iter {
            columns: self.columns(),
            iter: self.data.iter(),
        }
    }
}

impl<'a> IntoIterator for &'a TextRows {
    type Item = TextRow<'a>;
    type IntoIter = Iter<'a>;

    fn into_iter(self) -> Iter<'a> {
        self.iter()
    }
}

/// An iterator over `TextRow`s.
pub struct Iter<'a> {
    columns: &'a [Column],
    iter: slice::Iter<'a, RowData>,
}

impl<'a> Iterator for Iter<'a> {
    type Item = TextRow<'a>;

    fn next(&mut self) -> Option<TextRow<'a>> {
        self.iter.next().map(|row| {
            TextRow {
                columns: self.columns,
                data: row,
            }
        })
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.iter.size_hint()
    }
}

impl<'a> DoubleEndedIterator for Iter<'a> {
    fn next_back(&mut self) -> Option<TextRow<'a>> {
        self.iter.next_back().map(|row| {
            TextRow {
                columns: self.columns,
                data: row,
            }
        })
    }
}

impl<'a> ExactSizeIterator for Iter<'a> {}

/// A single result row of a query.
pub struct TextRow<'a> {
    columns: &'a [Column],
    data: &'a RowData,
}

impl<'a> fmt::Debug for TextRow<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("TextRow")
            .field("columns", &self.columns)
            .finish()
    }
}

impl<'a> TextRow<'a> {
    /// Returns the number of values in the row.
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Determines if there are any values in the row.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns a slice describing the columns of the `TextRow`.
    pub fn columns(&self) -> &[Column] {
        self.columns
    }

    /// Retrieve the contents of a field of a row
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// # Panics
    ///
    /// Panics if the index does not reference a column
    pub fn get<I>(&self, idx: I) -> &str
    where
        I: RowIndex + fmt::Debug,
    {
        match self.get_inner(&idx) {
            Some(Ok(value)) => value,
            Some(Err(err)) => panic!("error retrieving column {:?}: {:?}", idx, err),
            None => panic!("no such column {:?}", idx),
        }
    }

    /// Retrieves the contents of a field of the row.
    ///
    /// A field can be accessed by the name or index of its column, though
    /// access by index is more efficient. Rows are 0-indexed.
    ///
    /// Returns None if the index does not reference a column, Some(Err(..)) if
    /// there was an error parsing the result as UTF-8, and Some(Ok(..)) on
    /// success.
    pub fn get_opt<I>(&self, idx: I) -> Option<Result<&str>>
    where
        I: RowIndex,
    {
        self.get_inner(&idx)
    }

    fn get_inner<I>(&self, idx: &I) -> Option<Result<&str>>
    where
        I: RowIndex,
    {
        let idx = match idx.__idx(self.columns) {
            Some(idx) => idx,
            None => return None,
        };

        self.data.get(idx)
            .map(|s| str::from_utf8(s).map_err(|e| error::conversion(Box::new(e))))
    }
}
<|endoftext|>


<commit_before>//! Rustdoc's JSON backend
//!
//! This module contains the logic for rendering a crate as JSON rather than the normal static HTML
//! output. See [the RFC](https://github.com/rust-lang/rfcs/pull/2963) and the [`types`] module
//! docs for usage and details.

mod conversions;

use std::cell::RefCell;
use std::fs::File;
use std::path::PathBuf;
use std::rc::Rc;

use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;

use rustdoc_json_types as types;

use crate::clean;
use crate::config::RenderOptions;
use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::FormatRenderer;
use crate::html::render::cache::ExternalLocation;
use crate::json::conversions::{from_def_id, IntoWithTcx};

#[derive(Clone)]
crate struct JsonRenderer<'tcx> {
    tcx: TyCtxt<'tcx>,
    /// A mapping of IDs that contains all local items for this crate which gets output as a top
    /// level field of the JSON blob.
    index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
    /// The directory where the blob will be written to.
    out_path: PathBuf,
    cache: Rc<Cache>,
}

impl JsonRenderer<'tcx> {
    fn sess(&self) -> &'tcx Session {
        self.tcx.sess
    }

    fn get_trait_implementors(&mut self, id: rustc_span::def_id::DefId) -> Vec<types::Id> {
        Rc::clone(&self.cache)
            .implementors
            .get(&id)
            .map(|implementors| {
                implementors
                    .iter()
                    .map(|i| {
                        let item = &i.impl_item;
                        self.item(item.clone()).unwrap();
                        from_def_id(item.def_id)
                    })
                    .collect()
            })
            .unwrap_or_default()
    }

    fn get_impls(&mut self, id: rustc_span::def_id::DefId) -> Vec<types::Id> {
        Rc::clone(&self.cache)
            .impls
            .get(&id)
            .map(|impls| {
                impls
                    .iter()
                    .filter_map(|i| {
                        let item = &i.impl_item;
                        if item.def_id.is_local() {
                            self.item(item.clone()).unwrap();
                            Some(from_def_id(item.def_id))
                        } else {
                            None
                        }
                    })
                    .collect()
            })
            .unwrap_or_default()
    }

    fn get_trait_items(&mut self) -> Vec<(types::Id, types::Item)> {
        Rc::clone(&self.cache)
            .traits
            .iter()
            .filter_map(|(&id, trait_item)| {
                // only need to synthesize items for external traits
                if !id.is_local() {
                    let trait_item = &trait_item.trait_;
                    trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap());
                    Some((
                        from_def_id(id),
                        types::Item {
                            id: from_def_id(id),
                            crate_id: id.krate.as_u32(),
                            name: self
                                .cache
                                .paths
                                .get(&id)
                                .unwrap_or_else(|| {
                                    self.cache
                                        .external_paths
                                        .get(&id)
                                        .expect("Trait should either be in local or external paths")
                                })
                                .0
                                .last()
                                .map(Clone::clone),
                            visibility: types::Visibility::Public,
                            inner: types::ItemEnum::Trait(trait_item.clone().into_tcx(self.tcx)),
                            span: None,
                            docs: Default::default(),
                            links: Default::default(),
                            attrs: Default::default(),
                            deprecation: Default::default(),
                        },
                    ))
                } else {
                    None
                }
            })
            .collect()
    }
}

impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
    fn descr() -> &'static str {
        "json"
    }

    const RUN_ON_MODULE: bool = false;

    fn init(
        krate: clean::Crate,
        options: RenderOptions,
        cache: Cache,
        tcx: TyCtxt<'tcx>,
    ) -> Result<(Self, clean::Crate), Error> {
        debug!("Initializing json renderer");
        Ok((
            JsonRenderer {
                tcx,
                index: Rc::new(RefCell::new(FxHashMap::default())),
                out_path: options.output,
                cache: Rc::new(cache),
            },
            krate,
        ))
    }

    fn make_child_renderer(&self) -> Self {
        self.clone()
    }

    /// Inserts an item into the index. This should be used rather than directly calling insert on
    /// the hashmap because certain items (traits and types) need to have their mappings for trait
    /// implementations filled out before they're inserted.
    fn item(&mut self, item: clean::Item) -> Result<(), Error> {
        // Flatten items that recursively store other items
        item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());

        let id = item.def_id;
        if let Some(mut new_item) = self.convert_item(item) {
            if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
                t.implementors = self.get_trait_implementors(id)
            } else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
                s.impls = self.get_impls(id)
            } else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
                e.impls = self.get_impls(id)
            }
            let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());

            // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
            // to make sure the items are unique. The main place this happens is when an item, is
            // reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod`
            if let Some(old_item) = removed {
                assert_eq!(old_item, new_item);
            }
        }

        Ok(())
    }

    fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
        use clean::types::ItemKind::*;
        if let ModuleItem(m) = &*item.kind {
            for item in &m.items {
                match &*item.kind {
                    // These don't have names so they don't get added to the output by default
                    ImportItem(_) => self.item(item.clone()).unwrap(),
                    ExternCrateItem { .. } => self.item(item.clone()).unwrap(),
                    ImplItem(i) => i.items.iter().for_each(|i| self.item(i.clone()).unwrap()),
                    _ => {}
                }
            }
        }
        self.item(item.clone()).unwrap();
        Ok(())
    }

    fn after_krate(&mut self) -> Result<(), Error> {
        debug!("Done with crate");
        let mut index = (*self.index).clone().into_inner();
        index.extend(self.get_trait_items());
        // This needs to be the default HashMap for compatibility with the public interface for
        // rustdoc-json
        #[allow(rustc::default_hash_types)]
        let output = types::Crate {
            root: types::Id(String::from("0:0")),
            crate_version: self.cache.crate_version.clone(),
            includes_private: self.cache.document_private,
            index: index.into_iter().collect(),
            paths: self
                .cache
                .paths
                .clone()
                .into_iter()
                .chain(self.cache.external_paths.clone().into_iter())
                .map(|(k, (path, kind))| {
                    (
                        from_def_id(k),
                        types::ItemSummary {
                            crate_id: k.krate.as_u32(),
                            path,
                            kind: kind.into_tcx(self.tcx),
                        },
                    )
                })
                .collect(),
            external_crates: self
                .cache
                .extern_locations
                .iter()
                .map(|(k, v)| {
                    (
                        k.as_u32(),
                        types::ExternalCrate {
                            name: v.0.to_string(),
                            html_root_url: match &v.2 {
                                ExternalLocation::Remote(s) => Some(s.clone()),
                                _ => None,
                            },
                        },
                    )
                })
                .collect(),
            format_version: 5,
        };
        let mut p = self.out_path.clone();
        p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
        p.set_extension("json");
        let file = File::create(&p).map_err(|error| Error { error: error.to_string(), file: p })?;
        serde_json::ser::to_writer(&file, &output).unwrap();
        Ok(())
    }

    fn cache(&self) -> &Cache {
        &self.cache
    }
}
<commit_msg>Rollup merge of #84459 - jyn514:json-mod, r=aDotInTheVoid<commit_after>//! Rustdoc's JSON backend
//!
//! This module contains the logic for rendering a crate as JSON rather than the normal static HTML
//! output. See [the RFC](https://github.com/rust-lang/rfcs/pull/2963) and the [`types`] module
//! docs for usage and details.

mod conversions;

use std::cell::RefCell;
use std::fs::File;
use std::path::PathBuf;
use std::rc::Rc;

use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;

use rustdoc_json_types as types;

use crate::clean;
use crate::config::RenderOptions;
use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::FormatRenderer;
use crate::html::render::cache::ExternalLocation;
use crate::json::conversions::{from_def_id, IntoWithTcx};

#[derive(Clone)]
crate struct JsonRenderer<'tcx> {
    tcx: TyCtxt<'tcx>,
    /// A mapping of IDs that contains all local items for this crate which gets output as a top
    /// level field of the JSON blob.
    index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
    /// The directory where the blob will be written to.
    out_path: PathBuf,
    cache: Rc<Cache>,
}

impl JsonRenderer<'tcx> {
    fn sess(&self) -> &'tcx Session {
        self.tcx.sess
    }

    fn get_trait_implementors(&mut self, id: rustc_span::def_id::DefId) -> Vec<types::Id> {
        Rc::clone(&self.cache)
            .implementors
            .get(&id)
            .map(|implementors| {
                implementors
                    .iter()
                    .map(|i| {
                        let item = &i.impl_item;
                        self.item(item.clone()).unwrap();
                        from_def_id(item.def_id)
                    })
                    .collect()
            })
            .unwrap_or_default()
    }

    fn get_impls(&mut self, id: rustc_span::def_id::DefId) -> Vec<types::Id> {
        Rc::clone(&self.cache)
            .impls
            .get(&id)
            .map(|impls| {
                impls
                    .iter()
                    .filter_map(|i| {
                        let item = &i.impl_item;
                        if item.def_id.is_local() {
                            self.item(item.clone()).unwrap();
                            Some(from_def_id(item.def_id))
                        } else {
                            None
                        }
                    })
                    .collect()
            })
            .unwrap_or_default()
    }

    fn get_trait_items(&mut self) -> Vec<(types::Id, types::Item)> {
        Rc::clone(&self.cache)
            .traits
            .iter()
            .filter_map(|(&id, trait_item)| {
                // only need to synthesize items for external traits
                if !id.is_local() {
                    let trait_item = &trait_item.trait_;
                    trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap());
                    Some((
                        from_def_id(id),
                        types::Item {
                            id: from_def_id(id),
                            crate_id: id.krate.as_u32(),
                            name: self
                                .cache
                                .paths
                                .get(&id)
                                .unwrap_or_else(|| {
                                    self.cache
                                        .external_paths
                                        .get(&id)
                                        .expect("Trait should either be in local or external paths")
                                })
                                .0
                                .last()
                                .map(Clone::clone),
                            visibility: types::Visibility::Public,
                            inner: types::ItemEnum::Trait(trait_item.clone().into_tcx(self.tcx)),
                            span: None,
                            docs: Default::default(),
                            links: Default::default(),
                            attrs: Default::default(),
                            deprecation: Default::default(),
                        },
                    ))
                } else {
                    None
                }
            })
            .collect()
    }
}

impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
    fn descr() -> &'static str {
        "json"
    }

    const RUN_ON_MODULE: bool = false;

    fn init(
        krate: clean::Crate,
        options: RenderOptions,
        cache: Cache,
        tcx: TyCtxt<'tcx>,
    ) -> Result<(Self, clean::Crate), Error> {
        debug!("Initializing json renderer");
        Ok((
            JsonRenderer {
                tcx,
                index: Rc::new(RefCell::new(FxHashMap::default())),
                out_path: options.output,
                cache: Rc::new(cache),
            },
            krate,
        ))
    }

    fn make_child_renderer(&self) -> Self {
        self.clone()
    }

    /// Inserts an item into the index. This should be used rather than directly calling insert on
    /// the hashmap because certain items (traits and types) need to have their mappings for trait
    /// implementations filled out before they're inserted.
    fn item(&mut self, item: clean::Item) -> Result<(), Error> {
        // Flatten items that recursively store other items
        item.kind.inner_items().for_each(|i| self.item(i.clone()).unwrap());

        let id = item.def_id;
        if let Some(mut new_item) = self.convert_item(item) {
            if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
                t.implementors = self.get_trait_implementors(id)
            } else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
                s.impls = self.get_impls(id)
            } else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
                e.impls = self.get_impls(id)
            }
            let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());

            // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
            // to make sure the items are unique. The main place this happens is when an item, is
            // reexported in more than one place. See `rustdoc-json/reexport/in_root_and_mod`
            if let Some(old_item) = removed {
                assert_eq!(old_item, new_item);
            }
        }

        Ok(())
    }

    fn mod_item_in(&mut self, _item: &clean::Item) -> Result<(), Error> {
        unreachable!("RUN_ON_MODULE = false should never call mod_item_in")
    }

    fn after_krate(&mut self) -> Result<(), Error> {
        debug!("Done with crate");
        let mut index = (*self.index).clone().into_inner();
        index.extend(self.get_trait_items());
        // This needs to be the default HashMap for compatibility with the public interface for
        // rustdoc-json
        #[allow(rustc::default_hash_types)]
        let output = types::Crate {
            root: types::Id(String::from("0:0")),
            crate_version: self.cache.crate_version.clone(),
            includes_private: self.cache.document_private,
            index: index.into_iter().collect(),
            paths: self
                .cache
                .paths
                .clone()
                .into_iter()
                .chain(self.cache.external_paths.clone().into_iter())
                .map(|(k, (path, kind))| {
                    (
                        from_def_id(k),
                        types::ItemSummary {
                            crate_id: k.krate.as_u32(),
                            path,
                            kind: kind.into_tcx(self.tcx),
                        },
                    )
                })
                .collect(),
            external_crates: self
                .cache
                .extern_locations
                .iter()
                .map(|(k, v)| {
                    (
                        k.as_u32(),
                        types::ExternalCrate {
                            name: v.0.to_string(),
                            html_root_url: match &v.2 {
                                ExternalLocation::Remote(s) => Some(s.clone()),
                                _ => None,
                            },
                        },
                    )
                })
                .collect(),
            format_version: 5,
        };
        let mut p = self.out_path.clone();
        p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
        p.set_extension("json");
        let file = File::create(&p).map_err(|error| Error { error: error.to_string(), file: p })?;
        serde_json::ser::to_writer(&file, &output).unwrap();
        Ok(())
    }

    fn cache(&self) -> &Cache {
        &self.cache
    }
}
<|endoftext|>


<commit_before>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! A multiplexed cita protocol

use byteorder::{BigEndian, ByteOrder};
use bytes::BytesMut;
use std::io;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};
use tokio_proto::pipeline::ServerProto;

pub type CitaRequest = Vec<u8>;
pub type CitaResponse = Vec<u8>;

/// Our multiplexed line-based codec
pub struct CitaCodec;

/// Protocol definition
pub struct CitaProto;

/// Implementation of the multiplexed line-based protocol.
///
/// Frames begin with a 4 byte header, consisting of the numeric request ID
/// encoded in network order, followed by the frame payload encoded as a UTF-8
/// string and terminated with a '\n' character:
///
/// # An example frame:
///
/// +-- request id --+------- frame payload --------+
/// |                |                              |
/// | \xDEADBEEF+len | This is the frame payload    |
/// |                |                              |
/// +----------------+------------------------------+
///
impl Decoder for CitaCodec {
    type Item = CitaRequest;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        let buf_len = buf.len();
        if buf_len < 8 {
            return Ok(None);
        }

        // check flag and msglen
        let request_id = BigEndian::read_u64(buf.as_ref());
        if request_id & 0xffffffff00000000 != 0xDEADBEEF00000000 {
            return Ok(None);
        }
        let msg_len = request_id & 0x00000000ffffffff;
        if (msg_len + 8) > buf_len as u64 {
            return Ok(None);
        }
        // ok skip the flag
        buf.split_to(8);
        // get msg
        let msg = buf.split_to(msg_len as usize);
        let mut payload = Vec::new();
        payload.extend(msg.as_ref());

        trace!("decode msg {:?} {:?}", request_id, payload);

        Ok(Some(payload))
    }
}

impl Encoder for CitaCodec {
    type Item = CitaResponse;
    type Error = io::Error;

    fn encode(&mut self, msg: Self::Item, buf: &mut BytesMut) -> io::Result<()> {
        let request_id = 0xDEADBEEF00000000 + msg.len();
        trace!("encode msg {:?} {:?}", request_id, msg);

        let mut encoded_request_id = [0; 8];
        BigEndian::write_u64(&mut encoded_request_id, request_id as u64);

        buf.extend(&encoded_request_id);
        buf.extend(&msg);

        Ok(())
    }
}

impl<T: AsyncRead + AsyncWrite + 'static> ServerProto<T> for CitaProto {
    type Request = CitaRequest;
    type Response = CitaResponse;

    /// `Framed<T, CitaCodec>` is the return value of `io.framed(CitaCodec)`
    type Transport = Framed<T, CitaCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(CitaCodec))
    }
}
<commit_msg>opt bytes operation<commit_after>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! A multiplexed cita protocol

use byteorder::{BigEndian, ByteOrder};
use bytes::BytesMut;
use bytes::BufMut;
use std::io;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::codec::{Framed, Encoder, Decoder};
use tokio_proto::pipeline::ServerProto;

pub type CitaRequest = Vec<u8>;
pub type CitaResponse = Vec<u8>;

/// Our multiplexed line-based codec
pub struct CitaCodec;

/// Protocol definition
pub struct CitaProto;

/// Implementation of the multiplexed line-based protocol.
///
/// Frames begin with a 4 byte header, consisting of the numeric request ID
/// encoded in network order, followed by the frame payload encoded as a UTF-8
/// string and terminated with a '\n' character:
///
/// # An example frame:
///
/// +-- request id --+------- frame payload --------+
/// |                |                              |
/// | \xDEADBEEF+len | This is the frame payload    |
/// |                |                              |
/// +----------------+------------------------------+
///

fn opt_bytes_extend(buf: &mut BytesMut, data: &[u8]) {
    buf.reserve(data.len());
    unsafe {
        buf.bytes_mut()[..data.len()].copy_from_slice(data);
        buf.advance_mut(data.len());
    }
}

impl Decoder for CitaCodec {
    type Item = CitaRequest;
    type Error = io::Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, io::Error> {
        let buf_len = buf.len();
        if buf_len < 8 {
            return Ok(None);
        }

        // check flag and msglen
        let request_id = BigEndian::read_u64(buf.as_ref());
        if request_id & 0xffffffff00000000 != 0xDEADBEEF00000000 {
            return Ok(None);
        }
        let msg_len = request_id & 0x00000000ffffffff;
        if (msg_len + 8) > buf_len as u64 {
            return Ok(None);
        }
        // ok skip the flag
        buf.split_to(8);
        // get msg
        let payload = buf.split_to(msg_len as usize).to_vec();

        trace!("decode msg {:?} {:?}", request_id, payload);

        Ok(Some(payload))
    }
}

impl Encoder for CitaCodec {
    type Item = CitaResponse;
    type Error = io::Error;

    fn encode(&mut self, msg: Self::Item, buf: &mut BytesMut) -> io::Result<()> {
        let request_id = 0xDEADBEEF00000000 + msg.len();
        trace!("encode msg {:?} {:?}", request_id, msg);

        let mut encoded_request_id = [0; 8];
        BigEndian::write_u64(&mut encoded_request_id, request_id as u64);

        opt_bytes_extend(buf, &encoded_request_id);
        opt_bytes_extend(buf, &msg);

        Ok(())
    }
}

impl<T: AsyncRead + AsyncWrite + 'static> ServerProto<T> for CitaProto {
    type Request = CitaRequest;
    type Response = CitaResponse;

    /// `Framed<T, CitaCodec>` is the return value of `io.framed(CitaCodec)`
    type Transport = Framed<T, CitaCodec>;
    type BindTransport = Result<Self::Transport, io::Error>;

    fn bind_transport(&self, io: T) -> Self::BindTransport {
        Ok(io.framed(CitaCodec))
    }
}
<|endoftext|>


<commit_before>use super::*;

#[test]
// #[ignore]
fn symbol() {
    print_str("abc", "abc");
}

#[test]
// #[ignore]
fn number() {
    print_str("123", "123");
}

#[test]
// #[ignore]
fn unit() {
    print_str(";", ";");
}

#[test]
#[ignore]
fn tpiq() {
    // print_str("|: abc 123", ":< abc 123 >");
    print_str("|# abc 123", "#< abc 123 >");
}

#[test]
// #[ignore]
fn nested_tpiq() {
    print_str("|: |: cde |: abc 123 456", ":(:(cde :(abc 123)) 456)");
}

#[test]
// #[ignore]
fn list() {
    print_str("[abc 123]", ":(abc :(123 ;))");
}

#[test]
// #[ignore]
fn empty_env() {
    print_str("|% ; -1", "%(; -1)");
}

#[test]
// #[ignore]
fn resolve_piq() {
    print_str("|@ abc ;", "@(abc ;)");
}

#[test]
// #[ignore]
fn block() {
    print_str(
        r"|> ; |! |\ |% ; ; ^> -1 [|# abc 123 |@ ; abc] ;",
        r">(; !(\(%(; ;) >(-1 :(#(abc 123) :(@(; abc) ;)))) ;))"
    );
}

#[test]
// #[ignore]
fn evaled_symbol_ast() {
    print_evaled_str("abc", "abc");
}

#[test]
// #[ignore]
fn evaled_number_ast() {
    print_evaled_str("123", "123");
}

#[test]
// #[ignore]
fn evaled_define_ast() {
    // define symbol is number
    print_evaled_str("|> ; |# abc 123", ";");
}

/*
#[test]
#[ignore]
fn evaled_apply() {
    print_evaled_str(r"|> ; |! |\ |% ; ; 0 ;", r"0");
}
*/

#[test]
// #[ignore]
fn evaled_list() {
    print_evaled_str(r"|> ; ^> -1 [1 2 3]", r"3");
}

#[test]
// #[ignore]
fn evaled_defining_list() {
    // print_evaled_str(r"|> ; |# abc 123", r";");
    // print_evaled_str(r"|> ; |@ ; abc", r";");
    print_evaled_str(r"|> ; ^> -1 [|# abc 1234 |@ ; abc]", r"1234");
}

#[test]
// #[ignore]
fn access() {
    // print_str("|. a p", ".(a p)");
    // print_evaled_str("|> ; |. |: 1 3 p", "p")
    print_evaled_str("|> ; |. |: 1 3 q", "3")
}

#[test]
// #[ignore]
fn condition() {
    // print_str("|? abc 123", "?(abc 123)");
    // print_str("^T", "^T");
    // print_str("^F", "^F");
    print_evaled_str("|> ; |? ^T |: 1 0", "1");
    print_evaled_str("|> ; |? ^F |: 1 0", "0");
}

#[test]
// #[ignore]
fn exec_func() {
    // print_str(r"|% ; ;", ";a")
    // print_str(r"|> ; |! |\ |% ; ; 1 ;", ";a")
    print_evaled_str(r"|> ; |! |\ |% ; [a b c] |> ; ^> -1 [|@ ; c |@ ; b] [6667 6668 6669]", "6668")
}

#[test]
#[ignore]
fn primitive_function() {
    // print_evaled_str("|> ; |@ ; decr", "Prim(decr)");
    // print_evaled_str("|> ; |@ ; ltoreq", "Prim(ltoreq)");
    print_evaled_str("|> ; |! |> ; |@ ; decr [5]", "4");
    print_evaled_str("|> ; |! |> ; |@ ; ltoreq [5 4]", "^F"); // 5 <= 4
    // print_evaled_str("|> ; ^> -1 [|! |> ; |@ ; ltoreq [5 4] |! |> ; |@ ; decr [5]]", ";");
    // print_evaled_str(r"|> ; ^> -1 [|! |> ; |@ ; ltoreq [5 4] |! |> ; |\ |% ; [x] |> ; ^> -1 [|@ ; x][5642]]", ";");
}

#[test]
#[ignore]
fn tarai() {
    /*
    print_evaled_str(
        r"|> ; ^> -1 [
          |# abc |\ |% ; [x] ^> -1 [|@ ; x]
          |! |> ; |@ ; abc [8888]
        ]",
        "8888",
    );
    */

    /*
    print_evaled_str(
        r"|> ; ^> -1 [
          |# abc |\ |% ; [x]
                    ^> -1 [
                       |? |> ; |! |> ; |@ ; ltoreq [|> ; |@ ; x 10]
                          |: 1234
                             4321
                       ]
          |! |> ; |@ ; abc [8888]
        ]",
        "8888",
    );
    */

    // (defun tak (x y z)
    //   (if (<= x y)
    //       y
    //       (tak (tak (1- x) y z)
    //            (tak (1- y) z x)
    //            (tak (1- z) x y))))
    // (tak 12 6 0)

    /*
    print_evaled_str(
        r"|> ; ^> -1
        [
            |# recursive |\ |% ; [x]
                      ^> -1 [
                         |? |> ; |! |> ; |@ ; ltoreq [|> ; |@ ; x 0]
                            |: ^T
                               |> ; |! |> ; |@ ; recursive [0]
                      ]

            |! |> ; |@ ; recursive [1]
        ]",
        r";",
    );
    */

    print_evaled_str(
        r"|> ; ^> -1
        [
            |# tak |\ |% ; [x y z]
                      ^> -1 [
                         |? |> ; |! |> ; |@ ; ltoreq [|> ; |@ ; x |> ; |@ ; y]
                            |: |> ; |@ ; y
                               |> ; |! |> ; |@ ; tak [
                                  |> ; |! |> ; |@ ; tak [|> ; |! |> ; |@ ; decr [|> ; |@ ; x] |> ; |@ ; y |> ; |@ ; z]
                                  |> ; |! |> ; |@ ; tak [|> ; |! |> ; |@ ; decr [|> ; |@ ; y] |> ; |@ ; z |> ; |@ ; x]
                                  |> ; |! |> ; |@ ; tak [|> ; |! |> ; |@ ; decr [|> ; |@ ; z] |> ; |@ ; x |> ; |@ ; y]
                               ]
                      ]

            |! |> ; |@ ; tak [2 1 0]
        ]",
        r"2"
    );
}

#[test]
#[ignore]
fn fib() {
    print_evaled_str(
        r"|> ; ^> -1
        [
            |# fib |\ |% ; [n]
                      ^> -1 [
                         |? |> ; |! |> ; |@ ; eq [|> ; |@ ; n 0]
                            |: 0
                               |> ; |? |> ; |! |> ; |@ ; eq [|> ; |@ ; n 1]
                                       |: 1
                                       |> ; |! |> ; |@ ; plus [
                                          |> ; |! |> ; |@ ; fib [|> ; |! |> ; |@ ; minus [|> ; |@ ; n 2]]
                                          |> ; |! |> ; |@ ; fib [|> ; |! |> ; |@ ; minus [|> ; |@ ; n 1]]
                                       ]
                      ]
            |! |> ; |@ ; fib [30]
        ]",
        r"832040"
    );
}

#[test]
#[ignore]
fn prim() {
    print_evaled_str(
        r"|> ; ^> -1
        [
            |# x 1
            |# y 2
            |! |> ; |@ ; ltoreq [|> ; |@ ; x |> ; |@ ; y]
        ]",
        r"^T"
    );
}

#[test]
// #[ignore]
fn text() {
    print_str("\"o58nkry drtse\"", "\"o58nkry drtse\"");
}

#[test]
// #[ignore]
fn evaled_text() {
    print_evaled_str("\"o58nkry drtse\"", "\"o58nkry drtse\"");
}

#[test]
// #[ignore]
fn evaled_text_in_list() {
    print_str("[\"bbb\" 0 \"aaa\"]", ":(\"bbb\" :(0 :(\"aaa\" ;)))");
}

#[test]
fn access_in_list() {
    print_evaled_str("'> |. |: 0 1 p", "0");
}

#[test]
fn single_quote() {
    print_str("'> [a]", ">(; :(a ;))");
}

#[test]
fn resolve_syntax_sugar() {
    print_str("@abc", ">(; @(; abc))");
}

#[test]
fn apply_syntax_sugar() {
    print_syntax_sugar("abc! [1 2]", "'> |! abc [1 2]");
}

#[test]
fn resolve_and_apply_syntax_sugar() {
    print_syntax_sugar("@abc! [1 3]", "'> |! '> '@ abc [1 3]");
}

#[test]
fn lpiq() {
    print_syntax_sugar(r#"abc:"a""#, r#"|: abc "a""#);
}

#[test]
fn nested_lpiq() {
    print_syntax_sugar(r#"abc:"a":1"#, r#"|: abc |: "a" 1"#);
}

#[test]
fn accessor() {
    print_syntax_sugar("a.b", "'> |. a b");
}

#[test]
fn nested_accessor() {
    print_syntax_sugar("a.b.c.d", "'> |. a '> |. b '> |. c d");
}
<commit_msg>use raw stirng<commit_after>use super::*;

#[test]
// #[ignore]
fn symbol() {
    print_str("abc", "abc");
}

#[test]
// #[ignore]
fn number() {
    print_str("123", "123");
}

#[test]
// #[ignore]
fn unit() {
    print_str(";", ";");
}

#[test]
#[ignore]
fn tpiq() {
    // print_str("|: abc 123", ":< abc 123 >");
    print_str("|# abc 123", "#< abc 123 >");
}

#[test]
// #[ignore]
fn nested_tpiq() {
    print_str("|: |: cde |: abc 123 456", ":(:(cde :(abc 123)) 456)");
}

#[test]
// #[ignore]
fn list() {
    print_str("[abc 123]", ":(abc :(123 ;))");
}

#[test]
// #[ignore]
fn empty_env() {
    print_str("|% ; -1", "%(; -1)");
}

#[test]
// #[ignore]
fn resolve_piq() {
    print_str("|@ abc ;", "@(abc ;)");
}

#[test]
// #[ignore]
fn block() {
    print_str(
        r"|> ; |! |\ |% ; ; ^> -1 [|# abc 123 |@ ; abc] ;",
        r">(; !(\(%(; ;) >(-1 :(#(abc 123) :(@(; abc) ;)))) ;))"
    );
}

#[test]
// #[ignore]
fn evaled_symbol_ast() {
    print_evaled_str("abc", "abc");
}

#[test]
// #[ignore]
fn evaled_number_ast() {
    print_evaled_str("123", "123");
}

#[test]
// #[ignore]
fn evaled_define_ast() {
    // define symbol is number
    print_evaled_str("|> ; |# abc 123", ";");
}

/*
#[test]
#[ignore]
fn evaled_apply() {
    print_evaled_str(r"|> ; |! |\ |% ; ; 0 ;", r"0");
}
*/

#[test]
// #[ignore]
fn evaled_list() {
    print_evaled_str(r"|> ; ^> -1 [1 2 3]", r"3");
}

#[test]
// #[ignore]
fn evaled_defining_list() {
    // print_evaled_str(r"|> ; |# abc 123", r";");
    // print_evaled_str(r"|> ; |@ ; abc", r";");
    print_evaled_str(r"|> ; ^> -1 [|# abc 1234 |@ ; abc]", r"1234");
}

#[test]
// #[ignore]
fn access() {
    // print_str("|. a p", ".(a p)");
    // print_evaled_str("|> ; |. |: 1 3 p", "p")
    print_evaled_str("|> ; |. |: 1 3 q", "3")
}

#[test]
// #[ignore]
fn condition() {
    // print_str("|? abc 123", "?(abc 123)");
    // print_str("^T", "^T");
    // print_str("^F", "^F");
    print_evaled_str("|> ; |? ^T |: 1 0", "1");
    print_evaled_str("|> ; |? ^F |: 1 0", "0");
}

#[test]
// #[ignore]
fn exec_func() {
    // print_str(r"|% ; ;", ";a")
    // print_str(r"|> ; |! |\ |% ; ; 1 ;", ";a")
    print_evaled_str(r"|> ; |! |\ |% ; [a b c] |> ; ^> -1 [|@ ; c |@ ; b] [6667 6668 6669]", "6668")
}

#[test]
#[ignore]
fn primitive_function() {
    // print_evaled_str("|> ; |@ ; decr", "Prim(decr)");
    // print_evaled_str("|> ; |@ ; ltoreq", "Prim(ltoreq)");
    print_evaled_str("|> ; |! |> ; |@ ; decr [5]", "4");
    print_evaled_str("|> ; |! |> ; |@ ; ltoreq [5 4]", "^F"); // 5 <= 4
    // print_evaled_str("|> ; ^> -1 [|! |> ; |@ ; ltoreq [5 4] |! |> ; |@ ; decr [5]]", ";");
    // print_evaled_str(r"|> ; ^> -1 [|! |> ; |@ ; ltoreq [5 4] |! |> ; |\ |% ; [x] |> ; ^> -1 [|@ ; x][5642]]", ";");
}

#[test]
#[ignore]
fn tarai() {
    /*
    print_evaled_str(
        r"|> ; ^> -1 [
          |# abc |\ |% ; [x] ^> -1 [|@ ; x]
          |! |> ; |@ ; abc [8888]
        ]",
        "8888",
    );
    */

    /*
    print_evaled_str(
        r"|> ; ^> -1 [
          |# abc |\ |% ; [x]
                    ^> -1 [
                       |? |> ; |! |> ; |@ ; ltoreq [|> ; |@ ; x 10]
                          |: 1234
                             4321
                       ]
          |! |> ; |@ ; abc [8888]
        ]",
        "8888",
    );
    */

    // (defun tak (x y z)
    //   (if (<= x y)
    //       y
    //       (tak (tak (1- x) y z)
    //            (tak (1- y) z x)
    //            (tak (1- z) x y))))
    // (tak 12 6 0)

    /*
    print_evaled_str(
        r"|> ; ^> -1
        [
            |# recursive |\ |% ; [x]
                      ^> -1 [
                         |? |> ; |! |> ; |@ ; ltoreq [|> ; |@ ; x 0]
                            |: ^T
                               |> ; |! |> ; |@ ; recursive [0]
                      ]

            |! |> ; |@ ; recursive [1]
        ]",
        r";",
    );
    */

    print_evaled_str(
        r"|> ; ^> -1
        [
            |# tak |\ |% ; [x y z]
                      ^> -1 [
                         |? |> ; |! |> ; |@ ; ltoreq [|> ; |@ ; x |> ; |@ ; y]
                            |: |> ; |@ ; y
                               |> ; |! |> ; |@ ; tak [
                                  |> ; |! |> ; |@ ; tak [|> ; |! |> ; |@ ; decr [|> ; |@ ; x] |> ; |@ ; y |> ; |@ ; z]
                                  |> ; |! |> ; |@ ; tak [|> ; |! |> ; |@ ; decr [|> ; |@ ; y] |> ; |@ ; z |> ; |@ ; x]
                                  |> ; |! |> ; |@ ; tak [|> ; |! |> ; |@ ; decr [|> ; |@ ; z] |> ; |@ ; x |> ; |@ ; y]
                               ]
                      ]

            |! |> ; |@ ; tak [2 1 0]
        ]",
        r"2"
    );
}

#[test]
#[ignore]
fn fib() {
    print_evaled_str(
        r"|> ; ^> -1
        [
            |# fib |\ |% ; [n]
                      ^> -1 [
                         |? |> ; |! |> ; |@ ; eq [|> ; |@ ; n 0]
                            |: 0
                               |> ; |? |> ; |! |> ; |@ ; eq [|> ; |@ ; n 1]
                                       |: 1
                                       |> ; |! |> ; |@ ; plus [
                                          |> ; |! |> ; |@ ; fib [|> ; |! |> ; |@ ; minus [|> ; |@ ; n 2]]
                                          |> ; |! |> ; |@ ; fib [|> ; |! |> ; |@ ; minus [|> ; |@ ; n 1]]
                                       ]
                      ]
            |! |> ; |@ ; fib [30]
        ]",
        r"832040"
    );
}

#[test]
#[ignore]
fn prim() {
    print_evaled_str(
        r"|> ; ^> -1
        [
            |# x 1
            |# y 2
            |! |> ; |@ ; ltoreq [|> ; |@ ; x |> ; |@ ; y]
        ]",
        r"^T"
    );
}

#[test]
// #[ignore]
fn text() {
    print_str(r#""o58nkry drtse""#, r#""o58nkry drtse""#);
}

#[test]
// #[ignore]
fn evaled_text() {
    print_evaled_str(r#""o58nkry drtse"", r#""o58nkry drtse""#);
}

#[test]
// #[ignore]
fn evaled_text_in_list() {
    print_str(r#"["bbb" 0 "aaa"]"#, r#":("bbb" :(0 :("aaa" ;)))"#);
}

#[test]
fn access_in_list() {
    print_evaled_str("'> |. |: 0 1 p", "0");
}

#[test]
fn single_quote() {
    print_str("'> [a]", ">(; :(a ;))");
}

#[test]
fn resolve_syntax_sugar() {
    print_str("@abc", ">(; @(; abc))");
}

#[test]
fn apply_syntax_sugar() {
    print_syntax_sugar("abc! [1 2]", "'> |! abc [1 2]");
}

#[test]
fn resolve_and_apply_syntax_sugar() {
    print_syntax_sugar("@abc! [1 3]", "'> |! '> '@ abc [1 3]");
}

#[test]
fn lpiq() {
    print_syntax_sugar(r#"abc:"a""#, r#"|: abc "a""#);
}

#[test]
fn nested_lpiq() {
    print_syntax_sugar(r#"abc:"a":1"#, r#"|: abc |: "a" 1"#);
}

#[test]
fn accessor() {
    print_syntax_sugar("a.b", "'> |. a b");
}

#[test]
fn nested_accessor() {
    print_syntax_sugar("a.b.c.d", "'> |. a '> |. b '> |. c d");
}
<|endoftext|>