<commit_before>// Copyright 2015 Ilkka Rauta
//
// Licensed 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.

#![allow(dead_code,non_upper_case_globals)]

use super::ffi as ffi;

bitflags!(
      flags FrontendCaps: u32 {
            const IsStupid = ffi::FE_IS_STUPID,
            const CanInversionAuto = ffi::FE_CAN_INVERSION_AUTO,
            const CanFec12 = ffi::FE_CAN_FEC_1_2,
            const CanFec23 = ffi::FE_CAN_FEC_2_3,
            const CanFec34 = ffi::FE_CAN_FEC_3_4,
            const CanFec45 = ffi::FE_CAN_FEC_4_5,
            const CanFec56 = ffi::FE_CAN_FEC_5_6,
            const CanFec67 = ffi::FE_CAN_FEC_6_7,
            const CanFec78 = ffi::FE_CAN_FEC_7_8,
            const CanFec89 = ffi::FE_CAN_FEC_8_9,
            const CanFecAuto = ffi::FE_CAN_FEC_AUTO,
            const CanQpsk = ffi::FE_CAN_QPSK,
            const CanQam16 = ffi::FE_CAN_QAM_16,
            const CanQam32 = ffi::FE_CAN_QAM_32,
            const CanQam64 = ffi::FE_CAN_QAM_64,
            const CanQam128 = ffi::FE_CAN_QAM_128,
            const CanQam256 = ffi::FE_CAN_QAM_256,
            const CanQamAuto = ffi::FE_CAN_QAM_AUTO,
            const CanTransmissionModeAuto = ffi::FE_CAN_TRANSMISSION_MODE_AUTO,
            const CanBandwidthAuto = ffi::FE_CAN_BANDWIDTH_AUTO,
            const CanGuardIntervalAuto = ffi::FE_CAN_GUARD_INTERVAL_AUTO,
            const CanHierarchyAuto = ffi::FE_CAN_HIERARCHY_AUTO,
            const Can8vsb = ffi::FE_CAN_8VSB,
            const Can16vsb = ffi::FE_CAN_16VSB,
            const HasExtendedCaps = ffi::FE_HAS_EXTENDED_CAPS,
            const CanMultistream = ffi::FE_CAN_MULTISTREAM,
            const CanTurboFec = ffi::FE_CAN_TURBO_FEC,
            const Can2gModulation = ffi::FE_CAN_2G_MODULATION,
            const NeedsBending = ffi::FE_NEEDS_BENDING,
            const CanRecover = ffi::FE_CAN_RECOVER,
            const CanMuteTs = ffi::FE_CAN_MUTE_TS,
      }
);<commit_msg>Refactor and expand the frontend caps type(s).<commit_after>// Copyright 2015 Ilkka Rauta
//
// Licensed 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.

#![allow(dead_code,non_upper_case_globals)]

use super::ffi as ffi;

macro_rules! frontend_caps (
    ({
        $($variant:ident => $value:path),+
    }) => (
        bitflags!(
            flags FrontendCaps: u32 {
                $(const $variant = $value),+
            }
        );
        #[derive(Debug,Copy,Clone)]
        pub enum FrontendCapsEnum {
            $($variant),+
        }
        impl Into<Vec<FrontendCapsEnum>> for FrontendCaps {
            fn into(self) -> Vec<FrontendCapsEnum> {
                let mut caps = Vec::new();
                if self.is_empty() {
                    return caps;
                }
                $(
                    if !$variant.is_empty() && self.contains($variant) {
                        caps.push(FrontendCapsEnum::$variant);
                    }
                )+
                caps
            }
        }
    )
);

frontend_caps!({
    IsStupid => ffi::FE_IS_STUPID,
    CanInversionAuto => ffi::FE_CAN_INVERSION_AUTO,
    CanFec12 => ffi::FE_CAN_FEC_1_2,
    CanFec23 => ffi::FE_CAN_FEC_2_3,
    CanFec34 => ffi::FE_CAN_FEC_3_4,
    CanFec45 => ffi::FE_CAN_FEC_4_5,
    CanFec56 => ffi::FE_CAN_FEC_5_6,
    CanFec67 => ffi::FE_CAN_FEC_6_7,
    CanFec78 => ffi::FE_CAN_FEC_7_8,
    CanFec89 => ffi::FE_CAN_FEC_8_9,
    CanFecAuto => ffi::FE_CAN_FEC_AUTO,
    CanQpsk => ffi::FE_CAN_QPSK,
    CanQam16 => ffi::FE_CAN_QAM_16,
    CanQam32 => ffi::FE_CAN_QAM_32,
    CanQam64 => ffi::FE_CAN_QAM_64,
    CanQam128 => ffi::FE_CAN_QAM_128,
    CanQam256 => ffi::FE_CAN_QAM_256,
    CanQamAuto => ffi::FE_CAN_QAM_AUTO,
    CanTransmissionModeAuto => ffi::FE_CAN_TRANSMISSION_MODE_AUTO,
    CanBandwidthAuto => ffi::FE_CAN_BANDWIDTH_AUTO,
    CanGuardIntervalAuto => ffi::FE_CAN_GUARD_INTERVAL_AUTO,
    CanHierarchyAuto => ffi::FE_CAN_HIERARCHY_AUTO,
    Can8vsb => ffi::FE_CAN_8VSB,
    Can16vsb => ffi::FE_CAN_16VSB,
    HasExtendedCaps => ffi::FE_HAS_EXTENDED_CAPS,
    CanMultistream => ffi::FE_CAN_MULTISTREAM,
    CanTurboFec => ffi::FE_CAN_TURBO_FEC,
    Can2gModulation => ffi::FE_CAN_2G_MODULATION,
    NeedsBending => ffi::FE_NEEDS_BENDING,
    CanRecover => ffi::FE_CAN_RECOVER,
    CanMuteTs => ffi::FE_CAN_MUTE_TS
});
<|endoftext|>


<commit_before>//! Twitch streams.
//!
//! Streams are video broadcasts that are currently live.
//! They have a broadcaster and are part of a channel.

use std::collections::BTreeMap;

pub use model::TwitchLinks;
pub use model::DateString;
pub use model::UrlString;
pub use model::image::ImageLinks;
pub use model::channel::Channel;

/// Streams that are queried by a number of parameters sorted by number of viewers descending.
///
/// # Example in JSON
///
/// ```json
/// {
///   "_total": 12345,
///   "streams": [
///     {
///       // See `Stream` type
///     }
///   ],
///   "_links": {
///     "summary": "https://api.twitch.tv/kraken/streams/summary",
///     "followed": "https://api.twitch.tv/kraken/streams/followed",
///     "next": "https://api.twitch.tv/kraken/streams?channel=test_channel%2Ctest_channel2&game=StarCraft+II%3A+Heart+of+the+Swarm&limit=100&offset=100",
///     "featured": "https://api.twitch.tv/kraken/streams/featured",
///     "self": "https://api.twitch.tv/kraken/streams?channel=test_channel%2Ctest_channel2&game=StarCraft+II%3A+Heart+of+the+Swarm&limit=100&offset=0"
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Streams {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    #[serde(rename="_total")]
    total: u32,
    streams: Vec<Stream>,
}

/// Featured (promoted) streams.
///
/// # Example in JSON
///
/// ```json
/// {
///   "_links": {
///      "self": "https://api.twitch.tv/kraken/streams/featured?limit=25&offset=0",
///      "next": "https://api.twitch.tv/kraken/streams/featured?limit=25&offset=25"
///   },
///   "featured": [
///     {
///       // See `FeaturedStream` type
///     }
///   ]
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FeaturedStreams {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    featured: Vec<FeaturedStream>,
}

/// Twitch stream information of a specific channel.
///
/// # Example in JSON if offline
///
/// ```json
/// {
///   "stream": null,
///   "_links": {
///     "self": "https://api.twitch.tv/kraken/streams/test_channel",
///     "channel": "https://api.twitch.tv/kraken/channels/test_channel"
///   }
/// }
/// ```
///
/// # Example in JSON if online
///
/// ```json
/// {
///   "_links": {
///     "channel": "https://api.twitch.tv/kraken/channels/test_channel",
///     "self": "https://api.twitch.tv/kraken/streams/test_channel"
///   },
///   "stream": {
///     // See `Stream` type
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ChannelStream {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    stream: Option<Stream>,
}

/// Summary of current streams.
///
/// # Example in JSON
///
/// ```json
/// {
///   "viewers": 194774,
///   "channels": 4144,
///   "_links": {
///     "self": "https://api.twitch.tv/kraken/streams/summary"
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct StreamsSummary {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    viewers: u32,
    channels: u32,
}

/// Featured (promoted) stream.
///
/// # Example in JSON
///
/// ```json
/// {
///   "image": "http://s.jtvnw.net/jtv_user_pictures/hosted_images/TwitchPartnerSpotlight.png",
///   "text": "<p>some html to describe this featured stream</p>",
///   "title": "Twitch Partner Spotlight",
///   "sponsored": false,
///   "scheduled": true,
///   "stream": {
///     // See `Stream` type
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FeaturedStream {
    text: String,
    image: UrlString,
    title: String,
    sponsored: bool,
    priority: u8,
    scheduled: bool,
    stream: Stream,
}

/// Basic Stream type.
///
/// # Example in JSON
///
/// ```json
/// {
///   "game": "StarCraft II: Heart of the Swarm",
///   "viewers": 2123,
///   "average_fps": 29.9880749574,
///   "delay": 0,
///   "video_height": 720,
///   "created_at": "2015-02-12T04:42:31Z",
///   "_id": 4989654544,
///   "channel": {
///     // See `Channel` type
///   },
///   "preview": {
///     "small": "http://static-cdn.jtvnw.net/previews-ttv/live_user_test_channel-80x45.jpg",
///     "medium": "http://static-cdn.jtvnw.net/previews-ttv/live_user_test_channel-320x180.jpg",
///     "large": "http://static-cdn.jtvnw.net/previews-ttv/live_user_test_channel-640x360.jpg",
///     "template": "http://static-cdn.jtvnw.net/previews-ttv/live_user_test_channel-{width}x{height}.jpg"
///   },
///   "_links": {
///     "self": "https://api.twitch.tv/kraken/streams/test_channel"
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Stream {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    #[serde(rename="_id")]
    id: u64,
    game: String,
    viewers: u32,
    average_fps: f64,
    delay: Option<u32>,
    video_height: u16,
    is_playlist: bool,
    created_at: DateString,
    channel: Channel,
    preview: ImageLinks,
}

impl TwitchLinks for Streams {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl Streams {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams?channel=test_channel%2Ctest_channel2&game=StarCraft+II%3A+Heart+of+the+Swarm&limit=100&offset=0"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Link with key "next".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams?channel=test_channel%2Ctest_channel2&game=StarCraft+II%3A+Heart+of+the+Swarm&limit=100&offset=100"
    pub fn link_next(&self) -> &String {
        self.get_expected_link("next")
    }
    /// Link with key "featured".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/featured"
    pub fn link_featured(&self) -> &String {
        self.get_expected_link("featured")
    }
    /// Link with key "summary".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/summary"
    pub fn link_summary(&self) -> &String {
        self.get_expected_link("summary")
    }
    /// Link with key "followed".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/followed"
    pub fn link_followed(&self) -> &String {
        self.get_expected_link("followed")
    }
    /// Example value: 12345
    pub fn total(&self) -> u32 {
        self.total
    }
    /// Example value: See `Stream` type.
    pub fn streams(&self) -> &Vec<Stream> {
        &self.streams
    }
}

impl TwitchLinks for FeaturedStreams {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl FeaturedStreams {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/featured?limit=25&offset=0"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Link with key "next".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/featured?limit=25&offset=25"
    pub fn link_next(&self) -> &String {
        self.get_expected_link("next")
    }
    /// Example value: See `FeaturedStream` type.
    pub fn featured(&self) -> &Vec<FeaturedStream> {
        &self.featured
    }
}

impl TwitchLinks for ChannelStream {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl ChannelStream {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/test_channel"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Link with key "channel".
    ///
    /// Example value: "https://api.twitch.tv/kraken/channels/test_channel"
    pub fn link_channel(&self) -> &String {
        self.get_expected_link("channel")
    }
    /// Example value: See `Stream` type.
    pub fn stream(&self) -> &Option<Stream> {
        &self.stream
    }
}

impl TwitchLinks for StreamsSummary {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl StreamsSummary {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/summary"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Example value: 194774
    pub fn viewers(&self) -> u32 {
        self.viewers
    }
    /// Example value: 4144
    pub fn channels(&self) -> u32 {
        self.channels
    }
}

impl FeaturedStream {
    /// Example value: "
some html to describe this featured stream
"
    pub fn text(&self) -> &String {
        &self.text
    }
    /// Example value: "http://s.jtvnw.net/jtv_user_pictures/hosted_images/TwitchPartnerSpotlight.png"
    pub fn image(&self) -> &UrlString {
        &self.image
    }
    /// Example value: "Twitch Partner Spotlight"
    pub fn title(&self) -> &String {
        &self.title
    }
    /// Example value: false
    pub fn sponsored(&self) -> bool {
        self.sponsored
    }
    /// Example value: 3
    pub fn priority(&self) -> u8 {
        self.priority
    }
    /// Example value: true
    pub fn scheduled(&self) -> bool {
        self.scheduled
    }
    /// Example value: See `Stream` type.
    pub fn stream(&self) -> &Stream {
        &self.stream
    }
}

impl TwitchLinks for Stream {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl Stream {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/test_channel"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Example value: 4989654544
    pub fn id(&self) -> u64 {
        self.id
    }
    /// Example value: "StarCraft II: Heart of the Swarm"
    pub fn game(&self) -> &String {
        &self.game
    }
    /// Example value: 2123
    pub fn viewers(&self) -> u32 {
        self.viewers
    }
    /// Example value: 29.9880749574
    pub fn average_fps(&self) -> f64 {
        self.average_fps
    }
    /// Example value: 0
    pub fn delay(&self) -> Option<u32> {
        self.delay
    }
    /// Example value: 720
    pub fn video_height(&self) -> u16 {
        self.video_height
    }
    /// Example value: false
    pub fn is_playlist(&self) -> bool {
        self.is_playlist
    }
    /// Example value: "2015-02-12T04:42:31Z"
    pub fn created_at(&self) -> &DateString {
        &self.created_at
    }
    /// Example value: See `Channel` type.
    pub fn channel(&self) -> &Channel {
        &self.channel
    }
    /// Example value: See `ImageLinks` type.
    pub fn preview(&self) -> &ImageLinks {
        &self.preview
    }
}
<commit_msg>Fixed stream game possibly being null<commit_after>//! Twitch streams.
//!
//! Streams are video broadcasts that are currently live.
//! They have a broadcaster and are part of a channel.

use std::collections::BTreeMap;

pub use model::TwitchLinks;
pub use model::DateString;
pub use model::UrlString;
pub use model::image::ImageLinks;
pub use model::channel::Channel;

/// Streams that are queried by a number of parameters sorted by number of viewers descending.
///
/// # Example in JSON
///
/// ```json
/// {
///   "_total": 12345,
///   "streams": [
///     {
///       // See `Stream` type
///     }
///   ],
///   "_links": {
///     "summary": "https://api.twitch.tv/kraken/streams/summary",
///     "followed": "https://api.twitch.tv/kraken/streams/followed",
///     "next": "https://api.twitch.tv/kraken/streams?channel=test_channel%2Ctest_channel2&game=StarCraft+II%3A+Heart+of+the+Swarm&limit=100&offset=100",
///     "featured": "https://api.twitch.tv/kraken/streams/featured",
///     "self": "https://api.twitch.tv/kraken/streams?channel=test_channel%2Ctest_channel2&game=StarCraft+II%3A+Heart+of+the+Swarm&limit=100&offset=0"
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Streams {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    #[serde(rename="_total")]
    total: u32,
    streams: Vec<Stream>,
}

/// Featured (promoted) streams.
///
/// # Example in JSON
///
/// ```json
/// {
///   "_links": {
///      "self": "https://api.twitch.tv/kraken/streams/featured?limit=25&offset=0",
///      "next": "https://api.twitch.tv/kraken/streams/featured?limit=25&offset=25"
///   },
///   "featured": [
///     {
///       // See `FeaturedStream` type
///     }
///   ]
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FeaturedStreams {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    featured: Vec<FeaturedStream>,
}

/// Twitch stream information of a specific channel.
///
/// # Example in JSON if offline
///
/// ```json
/// {
///   "stream": null,
///   "_links": {
///     "self": "https://api.twitch.tv/kraken/streams/test_channel",
///     "channel": "https://api.twitch.tv/kraken/channels/test_channel"
///   }
/// }
/// ```
///
/// # Example in JSON if online
///
/// ```json
/// {
///   "_links": {
///     "channel": "https://api.twitch.tv/kraken/channels/test_channel",
///     "self": "https://api.twitch.tv/kraken/streams/test_channel"
///   },
///   "stream": {
///     // See `Stream` type
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ChannelStream {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    stream: Option<Stream>,
}

/// Summary of current streams.
///
/// # Example in JSON
///
/// ```json
/// {
///   "viewers": 194774,
///   "channels": 4144,
///   "_links": {
///     "self": "https://api.twitch.tv/kraken/streams/summary"
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct StreamsSummary {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    viewers: u32,
    channels: u32,
}

/// Featured (promoted) stream.
///
/// # Example in JSON
///
/// ```json
/// {
///   "image": "http://s.jtvnw.net/jtv_user_pictures/hosted_images/TwitchPartnerSpotlight.png",
///   "text": "<p>some html to describe this featured stream</p>",
///   "title": "Twitch Partner Spotlight",
///   "sponsored": false,
///   "scheduled": true,
///   "stream": {
///     // See `Stream` type
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct FeaturedStream {
    text: String,
    image: UrlString,
    title: String,
    sponsored: bool,
    priority: u8,
    scheduled: bool,
    stream: Stream,
}

/// Basic Stream type.
///
/// # Example in JSON
///
/// ```json
/// {
///   "game": "StarCraft II: Heart of the Swarm",
///   "viewers": 2123,
///   "average_fps": 29.9880749574,
///   "delay": 0,
///   "video_height": 720,
///   "created_at": "2015-02-12T04:42:31Z",
///   "_id": 4989654544,
///   "channel": {
///     // See `Channel` type
///   },
///   "preview": {
///     "small": "http://static-cdn.jtvnw.net/previews-ttv/live_user_test_channel-80x45.jpg",
///     "medium": "http://static-cdn.jtvnw.net/previews-ttv/live_user_test_channel-320x180.jpg",
///     "large": "http://static-cdn.jtvnw.net/previews-ttv/live_user_test_channel-640x360.jpg",
///     "template": "http://static-cdn.jtvnw.net/previews-ttv/live_user_test_channel-{width}x{height}.jpg"
///   },
///   "_links": {
///     "self": "https://api.twitch.tv/kraken/streams/test_channel"
///   }
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Stream {
    #[serde(rename="_links")]
    links: BTreeMap<String, String>,
    #[serde(rename="_id")]
    id: u64,
    game: Option<String>,
    viewers: u32,
    average_fps: f64,
    delay: Option<u32>,
    video_height: u16,
    is_playlist: bool,
    created_at: DateString,
    channel: Channel,
    preview: ImageLinks,
}

impl TwitchLinks for Streams {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl Streams {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams?channel=test_channel%2Ctest_channel2&game=StarCraft+II%3A+Heart+of+the+Swarm&limit=100&offset=0"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Link with key "next".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams?channel=test_channel%2Ctest_channel2&game=StarCraft+II%3A+Heart+of+the+Swarm&limit=100&offset=100"
    pub fn link_next(&self) -> &String {
        self.get_expected_link("next")
    }
    /// Link with key "featured".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/featured"
    pub fn link_featured(&self) -> &String {
        self.get_expected_link("featured")
    }
    /// Link with key "summary".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/summary"
    pub fn link_summary(&self) -> &String {
        self.get_expected_link("summary")
    }
    /// Link with key "followed".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/followed"
    pub fn link_followed(&self) -> &String {
        self.get_expected_link("followed")
    }
    /// Example value: 12345
    pub fn total(&self) -> u32 {
        self.total
    }
    /// Example value: See `Stream` type.
    pub fn streams(&self) -> &Vec<Stream> {
        &self.streams
    }
}

impl TwitchLinks for FeaturedStreams {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl FeaturedStreams {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/featured?limit=25&offset=0"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Link with key "next".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/featured?limit=25&offset=25"
    pub fn link_next(&self) -> &String {
        self.get_expected_link("next")
    }
    /// Example value: See `FeaturedStream` type.
    pub fn featured(&self) -> &Vec<FeaturedStream> {
        &self.featured
    }
}

impl TwitchLinks for ChannelStream {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl ChannelStream {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/test_channel"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Link with key "channel".
    ///
    /// Example value: "https://api.twitch.tv/kraken/channels/test_channel"
    pub fn link_channel(&self) -> &String {
        self.get_expected_link("channel")
    }
    /// Example value: See `Stream` type.
    pub fn stream(&self) -> &Option<Stream> {
        &self.stream
    }
}

impl TwitchLinks for StreamsSummary {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl StreamsSummary {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/summary"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Example value: 194774
    pub fn viewers(&self) -> u32 {
        self.viewers
    }
    /// Example value: 4144
    pub fn channels(&self) -> u32 {
        self.channels
    }
}

impl FeaturedStream {
    /// Example value: "
some html to describe this featured stream
"
    pub fn text(&self) -> &String {
        &self.text
    }
    /// Example value: "http://s.jtvnw.net/jtv_user_pictures/hosted_images/TwitchPartnerSpotlight.png"
    pub fn image(&self) -> &UrlString {
        &self.image
    }
    /// Example value: "Twitch Partner Spotlight"
    pub fn title(&self) -> &String {
        &self.title
    }
    /// Example value: false
    pub fn sponsored(&self) -> bool {
        self.sponsored
    }
    /// Example value: 3
    pub fn priority(&self) -> u8 {
        self.priority
    }
    /// Example value: true
    pub fn scheduled(&self) -> bool {
        self.scheduled
    }
    /// Example value: See `Stream` type.
    pub fn stream(&self) -> &Stream {
        &self.stream
    }
}

impl TwitchLinks for Stream {
    fn links(&self) -> &BTreeMap<String, String> {
        &self.links
    }
}

impl Stream {
    /// Link with key "self".
    ///
    /// Example value: "https://api.twitch.tv/kraken/streams/test_channel"
    pub fn link_self(&self) -> &String {
        self.get_expected_link("self")
    }
    /// Example value: 4989654544
    pub fn id(&self) -> u64 {
        self.id
    }
    /// Example value: "StarCraft II: Heart of the Swarm"
    pub fn game(&self) -> &Option<String> {
        &self.game
    }
    /// Example value: 2123
    pub fn viewers(&self) -> u32 {
        self.viewers
    }
    /// Example value: 29.9880749574
    pub fn average_fps(&self) -> f64 {
        self.average_fps
    }
    /// Example value: 0
    pub fn delay(&self) -> Option<u32> {
        self.delay
    }
    /// Example value: 720
    pub fn video_height(&self) -> u16 {
        self.video_height
    }
    /// Example value: false
    pub fn is_playlist(&self) -> bool {
        self.is_playlist
    }
    /// Example value: "2015-02-12T04:42:31Z"
    pub fn created_at(&self) -> &DateString {
        &self.created_at
    }
    /// Example value: See `Channel` type.
    pub fn channel(&self) -> &Channel {
        &self.channel
    }
    /// Example value: See `ImageLinks` type.
    pub fn preview(&self) -> &ImageLinks {
        &self.preview
    }
}
<|endoftext|>


<commit_before>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

//! Parser for Intecture data files.

#[macro_use]
mod macros;
mod condition;

use error::{Error, Result};
use serde_json::{self, Value};
use std::collections::BTreeMap;
use std::fs;
use std::path::{Path, PathBuf};

#[doc(hidden)]
pub fn open<P: AsRef<Path>>(path: P) -> Result<Value> {
    let mut p = PathBuf::from("data");
    p.push(path);
    open_raw(&p)
}

fn open_raw<P: AsRef<Path>>(path: P) -> Result<Value> {
    let mut fh = try!(fs::File::open(path.as_ref()));
    let data: Value = try!(serde_json::from_reader(&mut fh));

    if !data.is_object() {
        Err(Error::Generic("Value is not an object".into()))
    } else {
        Ok(data)
    }
}

pub fn merge(mut me: Value, mut last_value: Value) -> Result<Value> {
    for dep in try!(dependencies(&mut me)) {
        last_value = try!(merge(dep, last_value));
    }

    let lv_clone = last_value.clone();
    Ok(try!(merge_values(me, last_value, &lv_clone)))
}

fn dependencies(me: &mut Value) -> Result<Vec<Value>> {
    let mut deps = Vec::new();
    let mut payloads: Vec<String> = Vec::new();

    if let Some(inc) = me.find("_include") {
        if !inc.is_array() {
            return Err(Error::Generic("Value of `_include` is not an array".into()));
        }

        // Loop in reverse order to get lowest importance first
        for i in inc.as_array().unwrap().iter().rev() {
            if let Some(s) = i.as_str() {
                if s.starts_with("payload:") {
                    let (_, payload) = s.split_at(8);
                    let payload = payload.trim();
                    let parts: Vec<&str> = payload.split("::").collect();

                    let mut buf = PathBuf::from("payloads");
                    buf.push(try!(parts.get(0).ok_or(Error::Generic("Empty payload in `_include`".into()))));
                    buf.push("data");
                    buf.push(parts.get(1).unwrap_or(&"main"));
                    buf.set_extension("json");

                    if let Ok(d) = open_raw(&buf) {
                        deps.push(d);
                    }
                    payloads.insert(0, payload.into());
                } else {
                    deps.push(try!(open(s)));
                }
            } else {
                return Err(Error::Generic("Non-string value in `_include`".into()));
            }
        }
    }

    if me.is_object() && !payloads.is_empty() {
        me.as_object_mut().unwrap().insert("_payloads".into(), serde_json::to_value(payloads));
    }

    Ok(deps)
}

fn merge_values(into: Value, mut from: Value, parent_from: &Value) -> Result<Value> {
    match into {
        Value::Null |
        Value::Bool(_) |
        Value::I64(_) |
        Value::U64(_) |
        Value::F64(_) |
        Value::String(_) => Ok(into),
        Value::Array(mut a) => {
            if from.is_array() {
                a.append(from.as_array_mut().unwrap());
            }
            else if !from.is_null() {
                a.push(from);
            }

            let mut b = Vec::new();

            for v in a {
                b.push(try!(merge_values(v, Value::Null, parent_from)));
            }

            Ok(Value::Array(b))
        },
        Value::Object(o) => {
            let mut new: BTreeMap<String, Value> = BTreeMap::new();

            for (mut key, mut value) in o {
                if key.ends_with("?") || key.ends_with("?!") {
                    if key.pop().unwrap() == '!' {
                        key.pop();
                        key.push('!');
                    }

                    value = try!(query_value(&parent_from, value)).unwrap_or(Value::Null);
                }

                let mut merge_val = Value::Null;

                if key.ends_with("!") {
                    key.pop();
                }
                else if let Some(o1) = from.find(&key) {
                    merge_val = o1.clone();
                }

                value = try!(merge_values(value, merge_val, &parent_from));

                new.insert(key, value);
            }

            // Insert any missing values
            if let Some(o1) = from.as_object() {
                for (key, value) in o1 {
                    if !new.contains_key(key) {
                        new.insert(key.clone(), value.clone());
                    }
                }
            }

            Ok(Value::Object(new))
        }
    }
}

fn query_value(data: &Value, value: Value) -> Result<Option<Value>> {
    match value {
        Value::Array(a) => {
            for opt in a {
                if let Some(v) = try!(query_value(data, opt)) {
                    return Ok(Some(v));
                }
            }
        },
        Value::Object(mut o) => {
            if let Some(v) = o.remove("_") {
                if let Some(q) = o.get("?") {
                    match *q {
                        Value::String(ref s) => {
                            if try!(condition::eval(data, s)) {
                                return Ok(Some(v));
                            }
                        },
                        _ => return Err(Error::Generic("Query must be string".into())),
                    };
                }

                return Ok(Some(v));
            }
        },
        _ => return Ok(Some(value)),
    }

    Ok(None)
}

#[cfg(test)]
mod tests {
    use serde_json::{self, Value};
    use std::fs;
    use std::io::Write;
    use std::path::PathBuf;
    use super::*;
    use tempdir::TempDir;

    #[test]
    fn test_parser() {
        let tempdir = TempDir::new("parser_test").unwrap();
        let mut path = tempdir.path().to_owned();

        path.push("data");
        fs::create_dir(&path).unwrap();
        path.pop();
        path.push("payloads/payload/data");

        fs::create_dir_all(&path).unwrap();
        path.pop();
        path.pop();
        path.pop();

        let expected_value = create_data(&mut path);

        path.push("data/top.json");
        let value = open(&path).unwrap();
        let value = merge(value, Value::Null).unwrap();

        assert_eq!(value, expected_value);
    }

    fn create_data(path: &mut PathBuf) -> Value {
        path.push("data/middle.json");
        let mut fh = fs::File::create(&path).unwrap();
        path.pop();
        path.pop();
        fh.write_all(format!("{{
            \"payload\": {{
                \"b!\": [ 3, 4 ],
                \"d\": [ 987 ]
            }},
            \"variable\": false,
            \"d\": 4,
            \"_include\": [
                \"payload: {}/payloads/payload::default\"
            ]
        }}", path.to_str().unwrap()).as_bytes()).unwrap();

        path.push("data/bottom.json");
        let mut fh = fs::File::create(&path).unwrap();
        path.pop();
        path.pop();
        fh.write_all(b"{
            \"moo\": \"cow\",
            \"payload\": {
                \"b\": [ 5 ],
                \"d\": [ 999 ]
            }
        }").unwrap();

        path.push("payloads/payload/data/default.json");
        let mut fh = fs::File::create(&path).unwrap();
        path.pop();
        path.pop();
        path.pop();
        path.pop();
        fh.write_all(b"{
            \"pvalue\": \"payload\"
        }").unwrap();

        path.push("data/top.json");
        let mut fh = fs::File::create(&path).unwrap();
        path.pop();
        path.pop();
        fh.write_all(format!("{{
            \"a\": 1,
            \"payload\": {{
                \"b\": [ 1, 2 ],
                \"c?\": [
                    {{
                        \"_\": [ 6, 7 ],
                        \"?\": \"/variable = false\"
                    }},
                    {{
                        \"_\": [ 8, 9 ]
                    }}
                ],
                \"d\": [ 123 ]
            }},
            \"variable\": {{
                \"one!\": true,
                \"two\": false
            }},
            \"_include\": [
                \"{}/data/middle.json\",
                \"{0}/data/bottom.json\"
            ]
        }}", path.to_str().unwrap()).as_bytes()).unwrap();

        serde_json::from_str(&format!("{{
            \"_include\": [
                \"{}/data/middle.json\",
                \"{0}/data/bottom.json\",
                \"payload: {0}/payloads/payload::default\"
            ],
            \"_payloads\": [
                \"{0}/payloads/payload::default\"
            ],
            \"a\": 1,
            \"d\": 4,
            \"moo\": \"cow\",
            \"payload\": {{
                \"b\": [ 1, 2, 3, 4 ],
                \"c\": [ 6, 7 ],
                \"d\": [ 123, 987, 999 ]
            }},
            \"pvalue\": \"payload\",
            \"variable\": {{
                \"one\": true,
                \"two\": false
            }}
        }}", path.to_str().unwrap())).unwrap()
    }
}
<commit_msg>Fix bug with data query where failed condition would still return positive result<commit_after>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

//! Parser for Intecture data files.

#[macro_use]
mod macros;
mod condition;

use error::{Error, Result};
use serde_json::{self, Value};
use std::collections::BTreeMap;
use std::fs;
use std::path::{Path, PathBuf};

#[doc(hidden)]
pub fn open<P: AsRef<Path>>(path: P) -> Result<Value> {
    let mut p = PathBuf::from("data");
    p.push(path);
    open_raw(&p)
}

fn open_raw<P: AsRef<Path>>(path: P) -> Result<Value> {
    let mut fh = try!(fs::File::open(path.as_ref()));
    let data: Value = try!(serde_json::from_reader(&mut fh));

    if !data.is_object() {
        Err(Error::Generic("Value is not an object".into()))
    } else {
        Ok(data)
    }
}

pub fn merge(mut me: Value, mut last_value: Value) -> Result<Value> {
    for dep in try!(dependencies(&mut me)) {
        last_value = try!(merge(dep, last_value));
    }

    let lv_clone = last_value.clone();
    Ok(try!(merge_values(me, last_value, &lv_clone)))
}

fn dependencies(me: &mut Value) -> Result<Vec<Value>> {
    let mut deps = Vec::new();
    let mut payloads: Vec<String> = Vec::new();

    if let Some(inc) = me.find("_include") {
        if !inc.is_array() {
            return Err(Error::Generic("Value of `_include` is not an array".into()));
        }

        // Loop in reverse order to get lowest importance first
        for i in inc.as_array().unwrap().iter().rev() {
            if let Some(s) = i.as_str() {
                if s.starts_with("payload:") {
                    let (_, payload) = s.split_at(8);
                    let payload = payload.trim();
                    let parts: Vec<&str> = payload.split("::").collect();

                    let mut buf = PathBuf::from("payloads");
                    buf.push(try!(parts.get(0).ok_or(Error::Generic("Empty payload in `_include`".into()))));
                    buf.push("data");
                    buf.push(parts.get(1).unwrap_or(&"main"));
                    buf.set_extension("json");

                    if let Ok(d) = open_raw(&buf) {
                        deps.push(d);
                    }
                    payloads.insert(0, payload.into());
                } else {
                    deps.push(try!(open(s)));
                }
            } else {
                return Err(Error::Generic("Non-string value in `_include`".into()));
            }
        }
    }

    if me.is_object() && !payloads.is_empty() {
        me.as_object_mut().unwrap().insert("_payloads".into(), serde_json::to_value(payloads));
    }

    Ok(deps)
}

fn merge_values(into: Value, mut from: Value, parent_from: &Value) -> Result<Value> {
    match into {
        Value::Null |
        Value::Bool(_) |
        Value::I64(_) |
        Value::U64(_) |
        Value::F64(_) |
        Value::String(_) => Ok(into),
        Value::Array(mut a) => {
            if from.is_array() {
                a.append(from.as_array_mut().unwrap());
            }
            else if !from.is_null() {
                a.push(from);
            }

            let mut b = Vec::new();

            for v in a {
                b.push(try!(merge_values(v, Value::Null, parent_from)));
            }

            Ok(Value::Array(b))
        },
        Value::Object(o) => {
            let mut new: BTreeMap<String, Value> = BTreeMap::new();

            for (mut key, mut value) in o {
                if key.ends_with("?") || key.ends_with("?!") {
                    if key.pop().unwrap() == '!' {
                        key.pop();
                        key.push('!');
                    }

                    value = try!(query_value(&parent_from, value)).unwrap_or(Value::Null);
                }

                let mut merge_val = Value::Null;

                if key.ends_with("!") {
                    key.pop();
                }
                else if let Some(o1) = from.find(&key) {
                    merge_val = o1.clone();
                }

                value = try!(merge_values(value, merge_val, &parent_from));

                new.insert(key, value);
            }

            // Insert any missing values
            if let Some(o1) = from.as_object() {
                for (key, value) in o1 {
                    if !new.contains_key(key) {
                        new.insert(key.clone(), value.clone());
                    }
                }
            }

            Ok(Value::Object(new))
        }
    }
}

fn query_value(data: &Value, value: Value) -> Result<Option<Value>> {
    match value {
        Value::Array(a) => {
            for opt in a {
                if let Some(v) = try!(query_value(data, opt)) {
                    return Ok(Some(v));
                }
            }
        },
        Value::Object(mut o) => {
            if let Some(v) = o.remove("_") {
                if let Some(q) = o.get("?") {
                    match *q {
                        Value::String(ref s) => {
                            if try!(condition::eval(data, s)) {
                                return Ok(Some(v));
                            }
                        },
                        _ => return Err(Error::Generic("Query must be string".into())),
                    };
                } else {
                    return Ok(Some(v));
                }
            }
        },
        _ => return Ok(Some(value)),
    }

    Ok(None)
}

#[cfg(test)]
mod tests {
    use serde_json::{self, Value};
    use std::fs;
    use std::io::Write;
    use std::path::PathBuf;
    use super::*;
    use tempdir::TempDir;

    #[test]
    fn test_parser() {
        let tempdir = TempDir::new("parser_test").unwrap();
        let mut path = tempdir.path().to_owned();

        path.push("data");
        fs::create_dir(&path).unwrap();
        path.pop();

        path.push("payloads/payload/data");
        fs::create_dir_all(&path).unwrap();
        path.pop();
        path.pop();
        path.pop();

        let expected_value = create_data(&mut path);

        path.push("data/top.json");
        let value = open(&path).unwrap();
        let value = merge(value, Value::Null).unwrap();

        assert_eq!(value, expected_value);
    }

    fn create_data(path: &mut PathBuf) -> Value {
        path.push("data/middle.json");
        let mut fh = fs::File::create(&path).unwrap();
        path.pop();
        path.pop();
        fh.write_all(format!("{{
            \"payload\": {{
                \"b!\": [ 3, 4 ],
                \"d\": [ 987 ]
            }},
            \"variable\": false,
            \"d\": 4,
            \"_include\": [
                \"payload: {}/payloads/payload::default\"
            ]
        }}", path.to_str().unwrap()).as_bytes()).unwrap();

        path.push("data/bottom.json");
        let mut fh = fs::File::create(&path).unwrap();
        path.pop();
        path.pop();
        fh.write_all(b"{
            \"moo\": \"cow\",
            \"payload\": {
                \"b\": [ 5 ],
                \"d\": [ 999 ]
            }
        }").unwrap();

        path.push("payloads/payload/data/default.json");
        let mut fh = fs::File::create(&path).unwrap();
        path.pop();
        path.pop();
        path.pop();
        path.pop();
        fh.write_all(b"{
            \"pvalue\": \"payload\"
        }").unwrap();

        path.push("data/top.json");
        let mut fh = fs::File::create(&path).unwrap();
        path.pop();
        path.pop();
        fh.write_all(format!("{{
            \"a\": 1,
            \"payload\": {{
                \"b\": [ 1, 2 ],
                \"c?\": [
                    {{
                        \"_\": [ 6, 7 ],
                        \"?\": \"/variable = false\"
                    }},
                    {{
                        \"_\": [ 8, 9 ]
                    }}
                ],
                \"d\": [ 123 ]
            }},
            \"variable\": {{
                \"one!\": true,
                \"two\": false
            }},
            \"_include\": [
                \"{}/data/middle.json\",
                \"{0}/data/bottom.json\"
            ]
        }}", path.to_str().unwrap()).as_bytes()).unwrap();

        serde_json::from_str(&format!("{{
            \"_include\": [
                \"{}/data/middle.json\",
                \"{0}/data/bottom.json\",
                \"payload: {0}/payloads/payload::default\"
            ],
            \"_payloads\": [
                \"{0}/payloads/payload::default\"
            ],
            \"a\": 1,
            \"d\": 4,
            \"moo\": \"cow\",
            \"payload\": {{
                \"b\": [ 1, 2, 3, 4 ],
                \"c\": [ 6, 7 ],
                \"d\": [ 123, 987, 999 ]
            }},
            \"pvalue\": \"payload\",
            \"variable\": {{
                \"one\": true,
                \"two\": false
            }}
        }}", path.to_str().unwrap())).unwrap()
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::collections::RingBuf;

/// Decodes an integer encoded with a given prefix size (in bits).
/// Assumes that the buffer `buf` contains the integer to be decoded,
/// with the first byte representing the octet that contains the
/// prefix.
///
/// Returns a tuple representing the decoded integer and the number
/// of bytes from the buffer that were used.
fn decode_integer(buf: &[u8], prefix_size: u8) -> (usize, usize) {
    assert!(prefix_size >= 1 && prefix_size <= 8);
    assert!(buf.len() >= 1);
    let mask = (1u8 << prefix_size) - 1;
    let mut value: usize = (buf[0] & mask) as usize;
    if value < (mask as usize) {
        return (value, 1);
    }

    // Already one byte used (the prefix)
    let mut total = 1;
    let mut m = 0;
    for &b in buf[1..].iter() {
        total += 1;
        value += ((b & 127) as usize) * (1us << m);
        m += 7;
        if b & 128 != 128 {
            break;
        }
    }

    // TODO Error situation -- what happens if we reach here w/o having
    //      `b` byte-sized...
    (value, total)
}

/// Encode an integer to the representation defined by HPACK.
///
/// Returns a newly allocated `Vec` containing the encoded bytes.
/// Only `prefix_size` lowest-order bits of the first byte in the
/// array are guaranteed to be used.
fn encode_integer(mut value: usize, prefix_size: u8) -> Vec<u8> {
    let mask: usize = ((1u8 << prefix_size) - 1) as usize;
    if value < mask {
        // Right now, the caller would need to be the one to combine
        // the other part of the prefix byte (but would know that it's
        // safe to do so using the bit-wise or).
        return vec![value as u8];
    }

    let mut res: Vec<u8> = Vec::new();
    res.push(mask as u8);
    value -= mask;
    while value >= 128 {
        res.push(((value % 128) + 128) as u8);
        value = value / 128;
    }
    res.push(value as u8);

    res
}

/// The table represents the static header table defined by the HPACK spec.
/// (HPACK, Appendix A)
static STATIC_TABLE: &'static [(&'static [u8], &'static [u8])] = &[
  (b":authority", b""),
  (b":method", b"GET"),
  (b":method", b"POST"),
  (b":path", b"/"),
  (b":path", b"/index.html"),
  (b":scheme", b"http"),
  (b":scheme", b"https"),
  (b":status", b"200"),
  (b":status", b"204"),
  (b":status", b"206"),
  (b":status", b"304"),
  (b":status", b"400"),
  (b":status", b"404"),
  (b":status", b"500"),
  (b"accept-", b""),
  (b"accept-encoding", b"gzip, deflate"),
  (b"accept-language", b""),
  (b"accept-ranges", b""),
  (b"accept", b""),
  (b"access-control-allow-origin", b""),
  (b"age", b""),
  (b"allow", b""),
  (b"authorization", b""),
  (b"cache-control", b""),
  (b"content-disposition", b""),
  (b"content-encoding", b""),
  (b"content-language", b""),
  (b"content-length", b""),
  (b"content-location", b""),
  (b"content-range", b""),
  (b"content-type", b""),
  (b"cookie", b""),
  (b"date", b""),
  (b"etag", b""),
  (b"expect", b""),
  (b"expires", b""),
  (b"from", b""),
  (b"host", b""),
  (b"if-match", b""),
  (b"if-modified-since", b""),
  (b"if-none-match", b""),
  (b"if-range", b""),
  (b"if-unmodified-since", b""),
  (b"last-modified", b""),
  (b"link", b""),
  (b"location", b""),
  (b"max-forwards", b""),
  (b"proxy-authenticate", b""),
  (b"proxy-authorization", b""),
  (b"range", b""),
  (b"referer", b""),
  (b"refresh", b""),
  (b"retry-after", b""),
  (b"server", b""),
  (b"set-cookie", b""),
  (b"strict-transport-security", b""),
  (b"transfer-encoding", b""),
  (b"user-agent", b""),
  (b"vary", b""),
  (b"via", b""),
  (b"www-authenticate", b""),
];

/// A struct representing the dynamic table that needs to be maintained by the
/// coder.
struct DynamicTable {
    table: RingBuf<(Vec<u8>, Vec<u8>)>,
    size: usize,
    max_size: usize,
}

impl DynamicTable {
    /// Creates a new empty dynamic table with a default size.
    fn new() -> DynamicTable {
        // The default maximum size corresponds to the default HTTP/2
        // setting
        DynamicTable::with_size(4096)
    }

    /// Creates a new empty dynamic table with the given maximum size.
    fn with_size(max_size: usize) -> DynamicTable {
        DynamicTable {
            table: RingBuf::new(),
            size: 0,
            max_size: max_size,
        }
    }

    /// Returns the current size of the table in octets, as defined by the IETF
    /// HPACK spec.
    fn get_size(&self) -> usize {
        self.size
    }

    /// Add a new header to the dynamic table.
    ///
    /// The table automatically gets resized, if necessary.
    ///
    /// Do note that, under the HPACK rules, it is possible the given header
    /// is not found in the dynamic table after this operation finishes, in
    /// case the total size of the given header exceeds the maximum size of the
    /// dynamic table.
    fn add_header(&mut self, name: Vec<u8>, value: Vec<u8>) {
        // This is how the HPACK spec makes us calculate the size.  The 32 is
        // a magic number determined by them (under reasonable assumptions of
        // how the table is stored).
        self.size += name.len() + value.len() + 32;
        debug!("New dynamic table size {}", self.size);
        // Now add it to the internal buffer
        self.table.push_front((name, value));
    }

    /// Returns the number of headers in the dynamic table.
    ///
    /// This is different than the size of the dynamic table.
    fn len(&self) -> usize {
        self.table.len()
    }

    /// Converts the current state of the table to a `Vec`
    fn get_table_as_list(&self) -> Vec<(Vec<u8>, Vec<u8>)> {
        let mut ret: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
        for elem in self.table.iter() {
            ret.push(elem.clone());
        }

        ret
    }

    /// Returns a reference to the header at the given index, if found in the
    /// dynamic table.
    fn get(&self, index: usize) -> Option<&(Vec<u8>, Vec<u8>)> {
        self.table.get(index)
    }
}

impl fmt::Show for DynamicTable {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", self.table)
    }
}

mod tests {
    use super::{decode_integer};
    use super::{encode_integer};
    use super::DynamicTable;

    #[test]
    fn test_dynamic_table_size_calculation_simple() {
        let mut table = DynamicTable::new();
        // Sanity check
        assert_eq!(0, table.get_size());

        table.add_header(b"a".to_vec(), b"b".to_vec());

        assert_eq!(32 + 2, table.get_size());
    }

    #[test]
    fn test_dynamic_table_size_calculation() {
        let mut table = DynamicTable::new();

        table.add_header(b"a".to_vec(), b"b".to_vec());
        table.add_header(b"123".to_vec(), b"456".to_vec());
        table.add_header(b"a".to_vec(), b"b".to_vec());

        assert_eq!(3 * 32 + 2 + 6 + 2, table.get_size());
    }

    #[test]
    fn test_decode_integer() {
        assert_eq!((10us, 1), decode_integer(&[10], 5));
        assert_eq!((1337us, 3), decode_integer(&[31, 154, 10], 5));
        assert_eq!((1337us, 3), decode_integer(&[31 + 32, 154, 10], 5));
        assert_eq!((1337us, 3), decode_integer(&[31 + 64, 154, 10], 5));
        assert_eq!((1337us, 3), decode_integer(&[31, 154, 10, 342, 22], 5));

        assert_eq!((127us, 2), decode_integer(&[255, 0], 7));
        assert_eq!((127us, 2), decode_integer(&[127, 0], 7));
    }

    #[test]
    fn test_encode_integer() {
        assert_eq!(encode_integer(10, 5), [10]);
        assert_eq!(encode_integer(1337, 5), [31, 154, 10]);
        assert_eq!(encode_integer(127, 7), [127, 0]);
    }
}
<commit_msg>DynamicTable: Evict headers to keep size below given max<commit_after>use std::fmt;
use std::collections::RingBuf;

/// Decodes an integer encoded with a given prefix size (in bits).
/// Assumes that the buffer `buf` contains the integer to be decoded,
/// with the first byte representing the octet that contains the
/// prefix.
///
/// Returns a tuple representing the decoded integer and the number
/// of bytes from the buffer that were used.
fn decode_integer(buf: &[u8], prefix_size: u8) -> (usize, usize) {
    assert!(prefix_size >= 1 && prefix_size <= 8);
    assert!(buf.len() >= 1);
    let mask = (1u8 << prefix_size) - 1;
    let mut value: usize = (buf[0] & mask) as usize;
    if value < (mask as usize) {
        return (value, 1);
    }

    // Already one byte used (the prefix)
    let mut total = 1;
    let mut m = 0;
    for &b in buf[1..].iter() {
        total += 1;
        value += ((b & 127) as usize) * (1us << m);
        m += 7;
        if b & 128 != 128 {
            break;
        }
    }

    // TODO Error situation -- what happens if we reach here w/o having
    //      `b` byte-sized...
    (value, total)
}

/// Encode an integer to the representation defined by HPACK.
///
/// Returns a newly allocated `Vec` containing the encoded bytes.
/// Only `prefix_size` lowest-order bits of the first byte in the
/// array are guaranteed to be used.
fn encode_integer(mut value: usize, prefix_size: u8) -> Vec<u8> {
    let mask: usize = ((1u8 << prefix_size) - 1) as usize;
    if value < mask {
        // Right now, the caller would need to be the one to combine
        // the other part of the prefix byte (but would know that it's
        // safe to do so using the bit-wise or).
        return vec![value as u8];
    }

    let mut res: Vec<u8> = Vec::new();
    res.push(mask as u8);
    value -= mask;
    while value >= 128 {
        res.push(((value % 128) + 128) as u8);
        value = value / 128;
    }
    res.push(value as u8);

    res
}

/// The table represents the static header table defined by the HPACK spec.
/// (HPACK, Appendix A)
static STATIC_TABLE: &'static [(&'static [u8], &'static [u8])] = &[
  (b":authority", b""),
  (b":method", b"GET"),
  (b":method", b"POST"),
  (b":path", b"/"),
  (b":path", b"/index.html"),
  (b":scheme", b"http"),
  (b":scheme", b"https"),
  (b":status", b"200"),
  (b":status", b"204"),
  (b":status", b"206"),
  (b":status", b"304"),
  (b":status", b"400"),
  (b":status", b"404"),
  (b":status", b"500"),
  (b"accept-", b""),
  (b"accept-encoding", b"gzip, deflate"),
  (b"accept-language", b""),
  (b"accept-ranges", b""),
  (b"accept", b""),
  (b"access-control-allow-origin", b""),
  (b"age", b""),
  (b"allow", b""),
  (b"authorization", b""),
  (b"cache-control", b""),
  (b"content-disposition", b""),
  (b"content-encoding", b""),
  (b"content-language", b""),
  (b"content-length", b""),
  (b"content-location", b""),
  (b"content-range", b""),
  (b"content-type", b""),
  (b"cookie", b""),
  (b"date", b""),
  (b"etag", b""),
  (b"expect", b""),
  (b"expires", b""),
  (b"from", b""),
  (b"host", b""),
  (b"if-match", b""),
  (b"if-modified-since", b""),
  (b"if-none-match", b""),
  (b"if-range", b""),
  (b"if-unmodified-since", b""),
  (b"last-modified", b""),
  (b"link", b""),
  (b"location", b""),
  (b"max-forwards", b""),
  (b"proxy-authenticate", b""),
  (b"proxy-authorization", b""),
  (b"range", b""),
  (b"referer", b""),
  (b"refresh", b""),
  (b"retry-after", b""),
  (b"server", b""),
  (b"set-cookie", b""),
  (b"strict-transport-security", b""),
  (b"transfer-encoding", b""),
  (b"user-agent", b""),
  (b"vary", b""),
  (b"via", b""),
  (b"www-authenticate", b""),
];

/// A struct representing the dynamic table that needs to be maintained by the
/// coder.
struct DynamicTable {
    table: RingBuf<(Vec<u8>, Vec<u8>)>,
    size: usize,
    max_size: usize,
}

impl DynamicTable {
    /// Creates a new empty dynamic table with a default size.
    fn new() -> DynamicTable {
        // The default maximum size corresponds to the default HTTP/2
        // setting
        DynamicTable::with_size(4096)
    }

    /// Creates a new empty dynamic table with the given maximum size.
    fn with_size(max_size: usize) -> DynamicTable {
        DynamicTable {
            table: RingBuf::new(),
            size: 0,
            max_size: max_size,
        }
    }

    /// Returns the current size of the table in octets, as defined by the IETF
    /// HPACK spec.
    fn get_size(&self) -> usize {
        self.size
    }

    /// Add a new header to the dynamic table.
    ///
    /// The table automatically gets resized, if necessary.
    ///
    /// Do note that, under the HPACK rules, it is possible the given header
    /// is not found in the dynamic table after this operation finishes, in
    /// case the total size of the given header exceeds the maximum size of the
    /// dynamic table.
    fn add_header(&mut self, name: Vec<u8>, value: Vec<u8>) {
        // This is how the HPACK spec makes us calculate the size.  The 32 is
        // a magic number determined by them (under reasonable assumptions of
        // how the table is stored).
        self.size += name.len() + value.len() + 32;
        debug!("New dynamic table size {}", self.size);
        // Now add it to the internal buffer
        self.table.push_front((name, value));
        // ...and make sure we're not over the maximum size.
        self.consolidate_table();
        debug!("After consolidation dynamic table size {}", self.size);
    }

    fn consolidate_table(&mut self) {
        while self.size > self.max_size {
            {
                let last_header = match self.table.back() {
                    Some(x) => x,
                    None => {
                        // Can never happen as the size of the table must reach 0,
                        // by the time we've exhausted all elements.
                        // Only time it *could* happen is if max_size were 0 too.
                        panic!("Somehow managed to have size != 0, with no headers");
                    }
                };
                self.size -= last_header.0.len() + last_header.1.len() + 32;
            }
            self.table.pop_back();
        }
    }

    /// Returns the number of headers in the dynamic table.
    ///
    /// This is different than the size of the dynamic table.
    fn len(&self) -> usize {
        self.table.len()
    }

    /// Converts the current state of the table to a `Vec`
    fn get_table_as_list(&self) -> Vec<(Vec<u8>, Vec<u8>)> {
        let mut ret: Vec<(Vec<u8>, Vec<u8>)> = Vec::new();
        for elem in self.table.iter() {
            ret.push(elem.clone());
        }

        ret
    }

    /// Returns a reference to the header at the given index, if found in the
    /// dynamic table.
    fn get(&self, index: usize) -> Option<&(Vec<u8>, Vec<u8>)> {
        self.table.get(index)
    }
}

impl fmt::Show for DynamicTable {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", self.table)
    }
}

mod tests {
    use super::{decode_integer};
    use super::{encode_integer};
    use super::DynamicTable;

    #[test]
    fn test_dynamic_table_size_calculation_simple() {
        let mut table = DynamicTable::new();
        // Sanity check
        assert_eq!(0, table.get_size());

        table.add_header(b"a".to_vec(), b"b".to_vec());

        assert_eq!(32 + 2, table.get_size());
    }

    #[test]
    fn test_dynamic_table_size_calculation() {
        let mut table = DynamicTable::new();

        table.add_header(b"a".to_vec(), b"b".to_vec());
        table.add_header(b"123".to_vec(), b"456".to_vec());
        table.add_header(b"a".to_vec(), b"b".to_vec());

        assert_eq!(3 * 32 + 2 + 6 + 2, table.get_size());
    }

    /// Tests that the `DynamicTable` gets correctly resized (by evicting old
    /// headers) if it exceeds the maximum size on an insertion.
    #[test]
    fn test_dynamic_table_auto_resize() {
        let mut table = DynamicTable::with_size(38);
        table.add_header(b"a".to_vec(), b"b".to_vec());
        assert_eq!(32 + 2, table.get_size());

        table.add_header(b"123".to_vec(), b"456".to_vec());

        // Resized?
        assert_eq!(32 + 6, table.get_size());
        // Only has the second header?
        assert_eq!(table.get_table_as_list(), vec![
            (b"123".to_vec(), b"456".to_vec())]);
    }

    /// Tests that when inserting a new header whose size is larger than the
    /// size of the entire table, the table is fully emptied.
    #[test]
    fn test_dynamic_table_auto_resize_into_empty() {
        let mut table = DynamicTable::with_size(38);
        table.add_header(b"a".to_vec(), b"b".to_vec());
        assert_eq!(32 + 2, table.get_size());

        table.add_header(b"123".to_vec(), b"4567".to_vec());

        // Resized and empty?
        assert_eq!(0, table.get_size());
        assert_eq!(0, table.get_table_as_list().len());
    }

    #[test]
    fn test_decode_integer() {
        assert_eq!((10us, 1), decode_integer(&[10], 5));
        assert_eq!((1337us, 3), decode_integer(&[31, 154, 10], 5));
        assert_eq!((1337us, 3), decode_integer(&[31 + 32, 154, 10], 5));
        assert_eq!((1337us, 3), decode_integer(&[31 + 64, 154, 10], 5));
        assert_eq!((1337us, 3), decode_integer(&[31, 154, 10, 342, 22], 5));

        assert_eq!((127us, 2), decode_integer(&[255, 0], 7));
        assert_eq!((127us, 2), decode_integer(&[127, 0], 7));
    }

    #[test]
    fn test_encode_integer() {
        assert_eq!(encode_integer(10, 5), [10]);
        assert_eq!(encode_integer(1337, 5), [31, 154, 10]);
        assert_eq!(encode_integer(127, 7), [127, 0]);
    }
}
<|endoftext|>


<commit_before>#[crate_id = "euler"];
#[crate_type = "bin"];

#[feature(managed_boxes)];

extern mod extra;
extern mod common;

use std::{io, os};
use std::iter::Range;
use extra::{time, term};
use extra::term::Terminal;
use problem::Problem;

mod problem;

static NSEC_PER_SEC: u64 = 1000000000;
fn nanosec_to_str(nsec: u64) -> ~str {
    return format!("{}.{:09}",
         (nsec / NSEC_PER_SEC) as uint,
         (nsec % NSEC_PER_SEC) as uint);
}

fn bench<T>(f: proc() -> T) -> (u64, T) {
    let start_time = time::precise_time_ns();
    let result     = f();
    let end_time   = time::precise_time_ns();
    return (end_time - start_time, result);
}

fn color_print(color: term::color::Color, s: &str) {
    match Terminal::new(io::stdout()) {
        Ok(ref mut term) => {
            term.fg(color);
            term.write(s.as_bytes());
            term.reset();
        }
        Err(_) => { io::stdout().write(s.as_bytes()) }
    }
}

fn print_result(name: &str, time: u64, comp_answer: &str, time_color: bool, correct: bool) {
    let out = &mut io::stdout() as &mut Writer;
    write!(out, "[");
    if correct {
        color_print(term::color::GREEN, "OK");
    } else {
        color_print(term::color::RED, "NG");
    }
    write!(out, "] {:5}", name);
    if (time_color && time > 10 * NSEC_PER_SEC) {
        color_print(term::color::RED, format!(" {:13}", nanosec_to_str(time)));
    } else if time_color && time > NSEC_PER_SEC {
        color_print(term::color::YELLOW, format!(" {:13}", nanosec_to_str(time)));
    } else {
        write!(out, " {:13}", nanosec_to_str(time));
    }
    writeln!(out, " {:20}", comp_answer);
}

struct ArgIterator<'a> {
    args: &'a [~str],
    idx: uint,
    cur_range: Range<uint>,
}

impl<'a> ArgIterator<'a> {
    pub fn new<'a>(args: &'a [~str]) -> ArgIterator<'a> {
        let mut it = ArgIterator { args: args, idx: 0, cur_range: range(0u, 0) };
        it.update_range();
        return it;
    }

    fn update_range(&mut self) {
        self.cur_range = range(0u, 0);
        if self.idx >= self.args.len() { return; }

        if !self.args[self.idx].contains_char('-') {
            let n = from_str::<uint>(self.args[self.idx]);
            for &n in n.iter() {
                self.cur_range = range(n, n + 1);
            }
            return;
        }

        let mut ns = ~[];
        for ss in self.args[self.idx].split('-') {
            match from_str::<uint>(ss) {
                Some(n) => { ns.push(n); }
                None    => { return; }
            }
        }
        if ns.len() > 2 { return; }
        self.cur_range = range(ns[0], ns[1] + 1);
    }
}

impl<'a> Iterator<uint> for ArgIterator<'a> {
    fn next(&mut self) -> Option<uint> {
        loop {
            if self.idx >= self.args.len() { return None; }
            match self.cur_range.next() {
                Some(n) => { return Some(n); }
                None    => {
                    self.idx += 1;
                    self.update_range();
                }
            }
        }
    }
}

fn solve_all<T: Iterator<&'static Problem<'static>>>(mut it: T) {
    let mut total_time  = 0;
    let mut solve_cnt   = 0;
    let mut all_correct = true;

    for p in it {
        let (time, answer) = do bench { (p.solve)() };
        let correct = p.answer == answer;
        print_result(p.id.to_str(), time, answer, true, correct);

        total_time += time;
        solve_cnt  += 1;
        all_correct &= correct;
    }

    if solve_cnt > 1 {
        print_result("AVG", total_time / solve_cnt, "", true, all_correct);
        print_result("TOTAL", total_time, "", false, all_correct);
    }
}

fn main() {
    let args = os::args();
    let args = args.tail();

    if args.is_empty() {
        solve_all(range(0, problem::PROBLEMS.len())
                  .map(|i| problem::PROBLEMS[i]))
    } else {
        solve_all(ArgIterator::new(args)
                  .filter_map(|n| problem::PROBLEMS.bsearch(|&p| p.id.cmp(&n)))
                  .map(|i| problem::PROBLEMS[i]));
    };
}
<commit_msg>不要なキャスト式を削除<commit_after>#[crate_id = "euler"];
#[crate_type = "bin"];

#[feature(managed_boxes)];

extern mod extra;
extern mod common;

use std::{io, os};
use std::iter::Range;
use extra::{time, term};
use extra::term::Terminal;
use problem::Problem;

mod problem;

static NSEC_PER_SEC: u64 = 1000000000;
fn nanosec_to_str(nsec: u64) -> ~str {
    return format!("{}.{:09}",
         (nsec / NSEC_PER_SEC) as uint,
         (nsec % NSEC_PER_SEC) as uint);
}

fn bench<T>(f: proc() -> T) -> (u64, T) {
    let start_time = time::precise_time_ns();
    let result     = f();
    let end_time   = time::precise_time_ns();
    return (end_time - start_time, result);
}

fn color_print(color: term::color::Color, s: &str) {
    match Terminal::new(io::stdout()) {
        Ok(ref mut term) => {
            term.fg(color);
            term.write(s.as_bytes());
            term.reset();
        }
        Err(_) => { io::stdout().write(s.as_bytes()) }
    }
}

fn print_result(name: &str, time: u64, comp_answer: &str, time_color: bool, correct: bool) {
    let out = &mut io::stdout();
    write!(out, "[");
    if correct {
        color_print(term::color::GREEN, "OK");
    } else {
        color_print(term::color::RED, "NG");
    }
    write!(out, "] {:5}", name);
    if (time_color && time > 10 * NSEC_PER_SEC) {
        color_print(term::color::RED, format!(" {:13}", nanosec_to_str(time)));
    } else if time_color && time > NSEC_PER_SEC {
        color_print(term::color::YELLOW, format!(" {:13}", nanosec_to_str(time)));
    } else {
        write!(out, " {:13}", nanosec_to_str(time));
    }
    writeln!(out, " {:20}", comp_answer);
}

struct ArgIterator<'a> {
    args: &'a [~str],
    idx: uint,
    cur_range: Range<uint>,
}

impl<'a> ArgIterator<'a> {
    pub fn new<'a>(args: &'a [~str]) -> ArgIterator<'a> {
        let mut it = ArgIterator { args: args, idx: 0, cur_range: range(0u, 0) };
        it.update_range();
        return it;
    }

    fn update_range(&mut self) {
        self.cur_range = range(0u, 0);
        if self.idx >= self.args.len() { return; }

        if !self.args[self.idx].contains_char('-') {
            let n = from_str::<uint>(self.args[self.idx]);
            for &n in n.iter() {
                self.cur_range = range(n, n + 1);
            }
            return;
        }

        let mut ns = ~[];
        for ss in self.args[self.idx].split('-') {
            match from_str::<uint>(ss) {
                Some(n) => { ns.push(n); }
                None    => { return; }
            }
        }
        if ns.len() > 2 { return; }
        self.cur_range = range(ns[0], ns[1] + 1);
    }
}

impl<'a> Iterator<uint> for ArgIterator<'a> {
    fn next(&mut self) -> Option<uint> {
        loop {
            if self.idx >= self.args.len() { return None; }
            match self.cur_range.next() {
                Some(n) => { return Some(n); }
                None    => {
                    self.idx += 1;
                    self.update_range();
                }
            }
        }
    }
}

fn solve_all<T: Iterator<&'static Problem<'static>>>(mut it: T) {
    let mut total_time  = 0;
    let mut solve_cnt   = 0;
    let mut all_correct = true;

    for p in it {
        let (time, answer) = do bench { (p.solve)() };
        let correct = p.answer == answer;
        print_result(p.id.to_str(), time, answer, true, correct);

        total_time += time;
        solve_cnt  += 1;
        all_correct &= correct;
    }

    if solve_cnt > 1 {
        print_result("AVG", total_time / solve_cnt, "", true, all_correct);
        print_result("TOTAL", total_time, "", false, all_correct);
    }
}

fn main() {
    let args = os::args();
    let args = args.tail();

    if args.is_empty() {
        solve_all(range(0, problem::PROBLEMS.len())
                  .map(|i| problem::PROBLEMS[i]))
    } else {
        solve_all(ArgIterator::new(args)
                  .filter_map(|n| problem::PROBLEMS.bsearch(|&p| p.id.cmp(&n)))
                  .map(|i| problem::PROBLEMS[i]));
    };
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use bit::{BitVec};
use std::{cmp};

use Primes;

/// A segmented sieve that yields only a small run of primes at a
/// time.
///
/// This is heavily inspired by this [segmented
/// sieve](http://primesieve.org/segmented_sieve.html) code.
#[derive(Debug)]
pub struct StreamingSieve {
    small: Primes,
    sieve: BitVec,
    primes: Vec<(usize, usize)>,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = 32 << 10;
// 8 for the bit vector, 2 for storing odd numbers only
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = 2 * SEG_ELEMS;

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    pub fn new(limit: usize) -> StreamingSieve {
        let small = Primes::sieve((limit as f64).sqrt() as usize + 1);
        let current = 3;
        let low = 0;

        let elems = cmp::min(limit, SEG_ELEMS);
        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],

            low: low,
            current: current,
            limit: limit
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    pub fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);
        self.sieve.set_all();

        let mut s = self.current;

        while s * s <= high {
            if self.small.is_prime(s) {
                self.primes.push((s, s * s - low));
            }
            s += 1
        }

        self.current = s;
        let lim = self.limit;
        let top = cmp::min(SEG_LEN, lim) / 2;
        for &mut (k, ref mut next) in self.primes.iter_mut() {
            let mut j = *next / 2;
            while j < top {
                unsafe {
                    self.sieve.set_unchecked(j, false);
                }
                j += k;
            }

            *next = (2 * j + 1) - SEG_LEN;
        }

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, false);
        }

        Some((low, &self.sieve))
    }
}

#[cfg(test)]
mod tests {
    use super::StreamingSieve;
    #[test]
    fn test() {
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::Primes::sieve(LIMIT);
        while let Some((low, next)) = sieve.next() {
            let mut i = low + 1;
            while i < low + next.len() {
                if i > LIMIT { break }
                assert!(primes.is_prime(i) == next[(i - low) / 2],
                        "failed for {} (is prime = {})", i, primes.is_prime(i));
                i += 2;
            }
        }
    }

}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use bit::BitVec;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
}
<commit_msg>Flip how fast_sieve indicates primality/compositity.<commit_after>#![allow(dead_code)]

use bit::{BitVec};
use std::{cmp};

use Primes;

/// A segmented sieve that yields only a small run of primes at a
/// time.
///
/// This is heavily inspired by this [segmented
/// sieve](http://primesieve.org/segmented_sieve.html) code.
#[derive(Debug)]
pub struct StreamingSieve {
    small: Primes,
    // stores which numbers *aren't* prime, i.e. true == composite.
    sieve: BitVec,
    primes: Vec<(usize, usize)>,

    low: usize,
    current: usize,
    limit: usize,
}

const CACHE: usize = 32 << 10;
// 8 for the bit vector, 2 for storing odd numbers only
const SEG_ELEMS: usize = 8 * CACHE;
const SEG_LEN: usize = 2 * SEG_ELEMS;

impl StreamingSieve {
    /// Create a new instance of the streaming sieve that will
    /// correctly progressively filter primes up to `limit`.
    pub fn new(limit: usize) -> StreamingSieve {
        let small = Primes::sieve((limit as f64).sqrt() as usize + 1);
        let current = 3;
        let low = 0;

        let elems = cmp::min(limit, SEG_ELEMS);
        StreamingSieve {
            small: small,
            sieve: BitVec::from_elem(elems, false),
            primes: vec![],

            low: low,
            current: current,
            limit: limit
        }
    }

    /// Extract the next chunk of filtered primes, the return value is
    /// `Some((low, v))` or `None` if the sieve has reached the limit.
    ///
    /// The vector stores bits for each odd number starting at `low`.
    /// Bit `n` of `v` is set if and only if `low + 2 * n + 1` is
    /// prime.
    ///
    /// NB. the prime 2 is not included in any of these sieves and so
    /// needs special handling.
    pub fn next(&mut self) -> Option<(usize, &BitVec)> {
        if self.low >= self.limit {
            return None
        }

        let low = self.low;
        self.low += SEG_LEN;
        let high = cmp::min(low + SEG_LEN - 1, self.limit);
        self.sieve.clear();

        let mut s = self.current;

        while s * s <= high {
            if self.small.is_prime(s) {
                self.primes.push((s, s * s - low));
            }
            s += 1
        }

        self.current = s;
        let lim = self.limit;
        let top = cmp::min(SEG_LEN, lim) / 2;
        for &mut (k, ref mut next) in self.primes.iter_mut() {
            let mut j = *next / 2;
            while j < top {
                unsafe {
                    self.sieve.set_unchecked(j, true);
                }
                j += k;
            }

            *next = (2 * j + 1) - SEG_LEN;
        }

        if low == 0 {
            // 1 is not prime.
            self.sieve.set(0, true);
        }

        Some((low, &self.sieve))
    }
}

#[cfg(test)]
mod tests {
    use super::StreamingSieve;
    #[test]
    fn test() {
        const LIMIT: usize = 2_000_000;
        let mut sieve = StreamingSieve::new(LIMIT);
        let primes = ::Primes::sieve(LIMIT);
        while let Some((low, next)) = sieve.next() {
            let mut i = low + 1;
            while i < low + next.len() {
                if i > LIMIT { break }
                assert!(primes.is_prime(i) == !next[(i - low) / 2],
                        "failed for {} (is prime = {})", i, primes.is_prime(i));
                i += 2;
            }
        }
    }

}

#[cfg(all(test, feature = "unstable"))]
mod benches {
    use test::Bencher;
    use bit::BitVec;
    use super::StreamingSieve;

    fn run(b: &mut Bencher, n: usize) {
        b.iter(|| {
            let mut sieve = StreamingSieve::new(n);
            while sieve.next().is_some() {}
        })
    }

    #[bench]
    fn sieve_small(b: &mut Bencher) {
        run(b, 100)
    }
    #[bench]
    fn sieve_medium(b: &mut Bencher) {
        run(b, 10_000)
    }
    #[bench]
    fn sieve_large(b: &mut Bencher) {
        run(b, 100_000)
    }
    #[bench]
    fn sieve_larger(b: &mut Bencher) {
        run(b, 1_000_000)
    }
    #[bench]
    fn sieve_huge(b: &mut Bencher) {
        run(b, 10_000_000)
    }
}
<|endoftext|>


<commit_before>// Generators

use data::*;

pub struct BoolGenerator;
pub struct VecGenerator<G>(G);

pub trait Generator {
    type Item;
    fn generate(&self, source: &mut InfoTap) -> Maybe<Self::Item>;
}

pub fn booleans() -> BoolGenerator {
    BoolGenerator
}
pub fn vecs<G>(inner: G) -> VecGenerator<G> {
    VecGenerator(inner)
}

impl<G: Generator> Generator for VecGenerator<G> {
    type Item = Vec<G::Item>;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        let mut result = Vec::new();
        let bs = booleans();
        while bs.generate(src)? {
            let item = self.0.generate(src)?;
            result.push(item)
        }

        Ok(result)
    }
}
impl Generator for BoolGenerator {
    type Item = bool;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        src.next_byte().map(|next| next >= 0x80)
    }
}

impl BoolGenerator {}

#[cfg(test)]
mod tests {
    use rand::random;
    use std::iter;
    use super::*;
    use data::InfoPool;
    const SHORT_VEC_SIZE : usize = 64;

    fn gen_random_vec() -> Vec<u8> {
        (0..SHORT_VEC_SIZE).map(|_| random()).collect::<Vec<u8>>()
    }

    // If only I had some kind of property testing library.
    #[test]
    fn bools_should_generate_false_booleans_from_zeros() {
        let v1 = vec![0];
        let bools = booleans();
        assert_eq!(bools.generate(&mut InfoPool::of_vec(v1).tap()), Ok(false));
    }

    #[test]
    fn bools_should_generate_true_booleans_from_saturated_values() {
        let v1 = vec![0xff];
        let bools = booleans();
        assert_eq!(bools.generate(&mut InfoPool::of_vec(v1).tap()), Ok(true));
    }

    #[test]
    fn bools_should_generate_same_output_given_same_input() {
        let gen = booleans();
        for (p0, p1, v0, v1) in iter::repeat(())
            .map(|_| gen_random_vec())
            .map(|v0| (InfoPool::of_vec(v0.clone()), InfoPool::of_vec(v0)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (p0, p1, v0, v1))
                })
            })
            .take(100)
        {
            assert!(v0 == v1, "({:?} == {:?}) -> ({:?} == {:?})", p0, p1, v0, v1);
        }

    }

    // These really need to be proper statistical tests.
    #[test]
    fn bools_usually_generates_different_output_for_different_inputs() {
        let gen = booleans();
        let nitems = 100;
        let differing = iter::repeat(())
            .map(|_| (gen_random_vec(), gen_random_vec()))
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .map(|(v0, v1)| (InfoPool::of_vec(v0), InfoPool::of_vec(v1)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (v0, v1))
                })
            })
            .take(nitems)
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .count();
        assert!(differing > 0, "Differing items:{} > 0", differing);
    }

    #[test]
    fn vecs_should_generate_same_output_given_same_input() {
        let gen = vecs(booleans());
        for (p0, p1, v0, v1) in iter::repeat(())
            .map(|_| gen_random_vec())
            .map(|v0| (InfoPool::of_vec(v0.clone()), InfoPool::of_vec(v0)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (p0, p1, v0, v1))
                })
            })
            .take(100)
        {
            assert!(v0 == v1, "({:?} == {:?}) -> ({:?} == {:?})", p0, p1, v0, v1);
        }
    }

    #[test]
    fn vecs_usually_generates_different_output_for_different_inputs() {
        let gen = vecs(booleans());
        let nitems = 100;
        let differing = iter::repeat(())
            .map(|_| (gen_random_vec(), gen_random_vec()))
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .map(|(v0, v1)| (InfoPool::of_vec(v0), InfoPool::of_vec(v1)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (v0, v1))
                })
            })
            .take(nitems)
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .count();
        assert!(differing > 0, "Differing items:{} > 0", differing);
    }
}
<commit_msg>Investigate searching for minimal examples.<commit_after>// Generators

use data::*;

pub struct BoolGenerator;
pub struct VecGenerator<G>(G);

pub trait Generator {
    type Item;
    fn generate(&self, source: &mut InfoTap) -> Maybe<Self::Item>;
}

pub fn booleans() -> BoolGenerator {
    BoolGenerator
}
pub fn vecs<G>(inner: G) -> VecGenerator<G> {
    VecGenerator(inner)
}

impl<G: Generator> Generator for VecGenerator<G> {
    type Item = Vec<G::Item>;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        let mut result = Vec::new();
        let bs = booleans();
        while bs.generate(src)? {
            let item = self.0.generate(src)?;
            result.push(item)
        }

        Ok(result)
    }
}
impl Generator for BoolGenerator {
    type Item = bool;
    fn generate(&self, src: &mut InfoTap) -> Maybe<Self::Item> {
        src.next_byte().map(|next| next >= 0x80)
    }
}

impl BoolGenerator {}

#[cfg(test)]
mod tests {
    use rand::random;
    use std::iter;
    use super::*;
    use data::InfoPool;
    const SHORT_VEC_SIZE: usize = 64;

    fn gen_random_vec() -> Vec<u8> {
        (0..SHORT_VEC_SIZE).map(|_| random()).collect::<Vec<u8>>()
    }

    // If only I had some kind of property testing library.
    #[test]
    fn bools_should_generate_false_booleans_from_zeros() {
        let v1 = vec![0];
        let bools = booleans();
        assert_eq!(bools.generate(&mut InfoPool::of_vec(v1).tap()), Ok(false));
    }

    #[test]
    fn bools_should_generate_true_booleans_from_saturated_values() {
        let v1 = vec![0xff];
        let bools = booleans();
        assert_eq!(bools.generate(&mut InfoPool::of_vec(v1).tap()), Ok(true));
    }

    #[test]
    fn bools_should_generate_same_output_given_same_input() {
        let gen = booleans();
        for (p0, p1, v0, v1) in iter::repeat(())
            .map(|_| gen_random_vec())
            .map(|v0| (InfoPool::of_vec(v0.clone()), InfoPool::of_vec(v0)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (p0, p1, v0, v1))
                })
            })
            .take(100)
        {
            assert!(v0 == v1, "({:?} == {:?}) -> ({:?} == {:?})", p0, p1, v0, v1);
        }

    }

    // These really need to be proper statistical tests.
    #[test]
    fn bools_usually_generates_different_output_for_different_inputs() {
        let gen = booleans();
        let nitems = 100;
        let differing = iter::repeat(())
            .map(|_| (gen_random_vec(), gen_random_vec()))
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .map(|(v0, v1)| (InfoPool::of_vec(v0), InfoPool::of_vec(v1)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (v0, v1))
                })
            })
            .take(nitems)
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .count();
        assert!(differing > 0, "Differing items:{} > 0", differing);
    }

    #[test]
    fn bools_minimize_to_false() {
        let gen = booleans();
        let p = InfoPool::random_of_size(4);
        println!("Before: {:?}", p);
        let p = minimize(&p, &|mut t| gen.generate(&mut t).is_ok()).unwrap_or(p);
        println!("After: {:?}", p);

        let val = gen.generate(&mut p.tap()).expect("generated value");
        assert_eq!(val, false);
    }

    #[test]
    fn vecs_should_generate_same_output_given_same_input() {
        let gen = vecs(booleans());
        for (p0, p1, v0, v1) in iter::repeat(())
            .map(|_| gen_random_vec())
            .map(|v0| (InfoPool::of_vec(v0.clone()), InfoPool::of_vec(v0)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (p0, p1, v0, v1))
                })
            })
            .take(100)
        {
            assert!(v0 == v1, "({:?} == {:?}) -> ({:?} == {:?})", p0, p1, v0, v1);
        }
    }

    #[test]
    fn vecs_usually_generates_different_output_for_different_inputs() {
        let gen = vecs(booleans());
        let nitems = 100;
        let differing = iter::repeat(())
            .map(|_| (gen_random_vec(), gen_random_vec()))
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .map(|(v0, v1)| (InfoPool::of_vec(v0), InfoPool::of_vec(v1)))
            .flat_map(|(p0, p1)| {
                gen.generate(&mut p0.tap()).and_then(|v0| {
                    gen.generate(&mut p1.tap()).map(|v1| (v0, v1))
                })
            })
            .take(nitems)
            .filter(|&(ref v0, ref v1)| v0 != v1)
            .count();
        assert!(differing > 0, "Differing items:{} > 0", differing);
    }

    #[test]
    fn vec_bools_minimize_to_empty() {
        let gen = vecs(booleans());
        let p = InfoPool::random_of_size(4);
        println!("Before: {:?}", p);
        let p = minimize(&p, &|mut t| gen.generate(&mut t).is_ok()).unwrap_or(p);
        println!("After: {:?}", p);

        let val = gen.generate(&mut p.tap()).expect("generated value");
        assert_eq!(val, vec![]);
    }

    #[test]
    fn vec_bools_can_minimise_with_predicate() {
        let gen = vecs(booleans());
        let mut p = InfoPool::random_of_size(SHORT_VEC_SIZE);
        while !gen.generate(&mut p.tap()).map(|v| v.len() > 2).unwrap_or(
            false,
        )
        {
            p = InfoPool::random_of_size(SHORT_VEC_SIZE);
        }
        println!("Before: {:?}", p);
        let p = minimize(&p, &|mut t| {
            gen.generate(&mut t).map(|v| v.len() > 2).unwrap_or(false)
        }).unwrap_or(p);
        println!("After: {:?}", p);

        let val = gen.generate(&mut p.tap()).expect("generated value");
        assert_eq!(val, vec![false, false, false]);
    }
}
<|endoftext|>


<commit_before>#![allow(unused_variables, dead_code)] // macros

/// Dbus macro for Layout code

use super::{DBusTree, DBusResult};
use super::utils;

use dbus::tree::MethodErr;

use uuid::Uuid;

use super::super::layout::try_lock_tree;
use super::super::layout::Direction;
use super::super::layout::commands as layout_cmd;

dbus_interface! {
    path: "/org/way_cooler/Layout";
    name: "org.way_cooler.Layout";

    fn ToggleFloat(container_id: String) -> success: DBusResult<bool> {
        if container_id == "" {
            layout_cmd::toggle_float();
            Ok(true)
        } else {
            let uuid = try!(Uuid::parse_str(&container_id).map_err(
                |uuid_err| MethodErr::invalid_arg(&"uuid is not valid")));
            if let Ok(mut tree) = try_lock_tree() {
                match tree.toggle_float() {
                    Ok(_) => Ok(true),
                    Err(err) => return Err(MethodErr::failed(&"could not toggle float"))
                }
            } else {
                return Err(MethodErr::failed(&"could not lock tree"))
            }
        }
    }

    fn MoveContainer(container_id: String, direction: String) -> success: DBusResult<bool> {
        let target_uuid = match &*container_id {
            "" => None,
            uuid => Some(try!(Uuid::parse_str(uuid).map_err(
                |uuid_err| MethodErr::invalid_arg(&"uuid is not valid"))))
        };
        let direction = try!(match &*direction.to_lowercase() {
            "up" => Ok(Direction::Up),
            "down" => Ok(Direction::Down),
            "left" => Ok(Direction::Left),
            "right" => Ok(Direction::Right),
            other => Err(MethodErr::invalid_arg(&"direction is not a valid direction"))
        });
        if let Ok(mut tree) = try_lock_tree() {
            match tree.move_active(target_uuid, direction) {
                Ok(_) => Ok(true),
                Err(err) => Err(MethodErr::failed(&"could not move that container"))
            }
        } else {
            Err(MethodErr::failed(&"could not lock tree"))
        }
    }

    fn ActiveContainerId() -> container_id: DBusResult<String> {
        if let Ok(mut tree) = try_lock_tree() {
            match tree.active_id() {
                Some(id) => Ok(id.to_string()),
                None => Ok("".to_string())
            }
        } else {
            Err(MethodErr::failed(&"could not read from the tree"))
        }
    }

    fn SplitContainer(container_id: String, split_direction: String) -> success: DBusResult<bool> {
        let uuid = try!(utils::parse_uuid("container_id", &container_id));
        let direction = try!(utils::parse_direction("split_direction", &split_direction));

        if let Ok(mut tree) = try_lock_tree() {
            match tree.move_active(uuid, direction) {
                Ok(_) => Ok(true),
                Err(_) => Ok(false)
            }
        } else {
            Err(MethodErr::failed(&"Could not lock tree"))
        }
    }
}
<commit_msg>Improved layout command wrappers<commit_after>#![allow(unused_variables, dead_code)] // macros

/// Dbus macro for Layout code

use super::utils::{parse_uuid, parse_direction};

use dbus::tree::MethodErr;

use super::super::layout::try_lock_tree;
use super::super::layout::Direction;
use super::super::layout::commands as layout_cmd;

dbus_interface! {
    path: "/org/way_cooler/Layout";
    name: "org.way_cooler.Layout";

    fn ToggleFloat(container_id: String) -> success: DBusResult<bool> {
        let maybe_uuid = try!(parse_uuid("container_id", &container_id));
        match maybe_uuid {
            Some(uuid) => {
                match try_lock_tree() {
                    Ok(mut tree) => {
                        tree.toggle_float()
                            .and(Ok(true))
                            .map_err(|err| {
                                MethodErr::failed(&format!("{:?}", err))
                            })
                    },
                    Err(err) => Err(MethodErr::failed(&format!("{:?}", err)))
                }
            },
            None => {
                layout_cmd::toggle_float();
                Ok(true)
            }
        }
    }

    fn MoveContainer(container_id: String, direction: String) -> success: DBusResult<bool> {
        let target_uuid = try!(parse_uuid("container_id", &container_id));
        let direction = match direction.to_lowercase().as_str() {
            "up" => Direction::Up,
            "down" => Direction::Down,
            "left" => Direction::Left,
            "right" => Direction::Right,
            other => return Err(MethodErr::invalid_arg(&"Not a valid direction"))
        };
        match try_lock_tree() {
            Ok(mut tree) => {
                match tree.move_active(target_uuid, direction) {
                    Ok(_) => Ok(true),
                    Err(err) => Err(MethodErr::failed(&format!("{:?}", err)))
                }
            },
            Err(err) => Err(MethodErr::failed(&format!("{:?}", err)))
        }
    }

    fn ActiveContainerId() -> container_id: DBusResult<String> {
        match try_lock_tree() {
            Ok(tree) => {
                match tree.active_id() {
                    Some(id) => Ok(id.to_string()),
                    None => Ok("".to_string())
                }
            },
            Err(err) => Err(MethodErr::failed(&format!("{:?}", err)))
        }
    }

    fn SplitContainer(container_id: String, split_direction: String) -> success: DBusResult<bool> {
        let uuid = try!(parse_uuid("container_id", &container_id));
        let direction = try!(parse_direction("split_direction", &split_direction));

        if let Ok(mut tree) = try_lock_tree() {
            match tree.move_active(uuid, direction) {
                Ok(_) => Ok(true),
                Err(_) => Ok(false)
            }
        } else {
            Err(MethodErr::failed(&"Could not lock tree"))
        }
    }
}
<|endoftext|>