<commit_before>use byteorder::{ByteOrder, LittleEndian};
use rand_core::le::read_u64_into;
use rand_core::impls::fill_bytes_via_next;
use rand_core::{RngCore, SeedableRng, Error};

/// A splitmix64 random number generator.
///
/// The splitmix algorithm is not suitable for cryptographic purposes, but is
/// very fast and has a 64 bit state.
///
/// The algorithm used here is translated from [the `splitmix64.c`
/// reference source code](http://xoshiro.di.unimi.it/splitmix64.c) by
/// Sebastiano Vigna. For `next_u32`, a more efficient mixing function taken
/// from [`dsiutils`](http://dsiutils.di.unimi.it/) is used.
#[allow(missing_copy_implementations)]
#[derive(Debug, Clone)]
pub struct SplitMix64 {
    x: u64,
}

const PHI: u64 = 0x9e3779b97f4a7c15;

impl RngCore for SplitMix64 {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        self.x = self.x.wrapping_add(PHI);
        let mut z = self.x;
        // David Stafford's
        // (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
        // "Mix4" variant of the 64-bit finalizer in Austin Appleby's
        // MurmurHash3 algorithm.
        z = (z ^ (z >> 33)).wrapping_mul(0x62A9D9ED799705F5);
        z = (z ^ (z >> 28)).wrapping_mul(0xCB24D0A5C88C35B3);
        (z >> 32) as u32
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        self.x = self.x.wrapping_add(PHI);
        let mut z = self.x;
        z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
        z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
        z ^ (z >> 31)
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        fill_bytes_via_next(self, dest);
    }

    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}

impl SeedableRng for SplitMix64 {
    type Seed = [u8; 8];

    /// Create a new `SplitMix64`.
    fn from_seed(seed: [u8; 8]) -> SplitMix64 {
        let mut state = [0; 1];
        read_u64_into(&seed, &mut state);
        SplitMix64 {
            x: state[0],
        }
    }

    /// Seed a `SplitMix64` from a `u64`.
    fn seed_from_u64(seed: u64) -> SplitMix64 {
        let mut x = [0; 8];
        LittleEndian::write_u64(&mut x, seed);
        SplitMix64::from_seed(x)
    }
}

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

    #[test]
    fn reference() {
        let mut rng = SplitMix64::seed_from_u64(1477776061723855037);
        // These values were produced with the reference implementation:
        // http://xoshiro.di.unimi.it/splitmix64.c
        let expected : [u64 ; 20]= [
            1985237415132408290, 2979275885539914483, 13511426838097143398,
            8488337342461049707, 15141737807933549159, 17093170987380407015,
            16389528042912955399, 13177319091862933652, 10841969400225389492,
            17094824097954834098, 3336622647361835228, 9678412372263018368,
            11111587619974030187, 7882215801036322410, 5709234165213761869,
            7799681907651786826, 4616320717312661886, 4251077652075509767,
            7836757050122171900, 5054003328188417616, 12919285918354108358,
            16477564761813870717, 5124667218451240549, 18099554314556827626,
            7603784838804469118, 6358551455431362471, 3037176434532249502,
            3217550417701719149, 9958699920490216947, 5965803675992506258,
            12000828378049868312, 12720568162811471118, 245696019213873792,
            8351371993958923852, 14378754021282935786, 5655432093647472106,
            5508031680350692005, 8515198786865082103, 6287793597487164412,
            14963046237722101617, 3630795823534910476, 8422285279403485710,
            10554287778700714153, 10871906555720704584, 8659066966120258468,
            9420238805069527062, 10338115333623340156, 13514802760105037173,
            14635952304031724449, 15419692541594102413,
        ];
        for &e in &expected {
            assert_eq!(rng.next_u64(), e);
        }
    }

    #[test]
    fn next_u32() {
        let mut rng = SplitMix64::seed_from_u64(10);
        // These values were produced with the reference implementation:
        // http://dsiutils.di.unimi.it/dsiutils-2.5.1-src.tar.gz
        let expected : [u32 ; 100]= [
            3930361779, 4016923089, 4113052479, 925926767, 1755287528,
            802865554, 954171070, 3724185978, 173676273, 1414488795, 12664133,
            1784889697, 1303817078, 261610523, 941280008, 2571813643,
            2954453492, 378291111, 2546873158, 3923319175, 645257028,
            3881821278, 2681538690, 3037029984, 1999958137, 1853970361,
            2989951788, 2126166628, 839962987, 3989679659, 3656977858,
            684284364, 1673258011, 170979192, 3037622326, 1600748179,
            1780764218, 1141430714, 4139736875, 3336905707, 2262051600,
            3830850262, 2430765325, 1073032139, 1668888979, 2716938970,
            4102420032, 40305196, 386350562, 2754480591, 622869439, 2129598760,
            2306038241, 4218338739, 412298926, 3453855056, 3061469690,
            4284292697, 994843708, 1591016681, 414726151, 1238182607, 18073498,
            1237631493, 351884714, 2347486264, 2488990876, 802846256, 645670443,
            957607012, 3126589776, 1966356370, 3036485766, 868696717,
            2808613630, 2070968151, 1025536863, 1743949425, 466212687,
            2994327271, 209776458, 1246125124, 3344380309, 2203947859,
            968313105, 2805485302, 197484837, 3472483632, 3931823935,
            3288490351, 4165666529, 3671080416, 689542830, 1272555356,
            1039141475, 3984640460, 4142959054, 2252788890, 2459379590,
            991872507,
        ];
        for &e in &expected {
            assert_eq!(rng.next_u32(), e);
        }
    }
}
<commit_msg>Fixed xoshiro tests.<commit_after>use byteorder::{ByteOrder, LittleEndian};
use rand_core::le::read_u64_into;
use rand_core::impls::fill_bytes_via_next;
use rand_core::{RngCore, SeedableRng, Error};

/// A splitmix64 random number generator.
///
/// The splitmix algorithm is not suitable for cryptographic purposes, but is
/// very fast and has a 64 bit state.
///
/// The algorithm used here is translated from [the `splitmix64.c`
/// reference source code](http://xoshiro.di.unimi.it/splitmix64.c) by
/// Sebastiano Vigna. For `next_u32`, a more efficient mixing function taken
/// from [`dsiutils`](http://dsiutils.di.unimi.it/) is used.
#[allow(missing_copy_implementations)]
#[derive(Debug, Clone)]
pub struct SplitMix64 {
    x: u64,
}

const PHI: u64 = 0x9e3779b97f4a7c15;

impl RngCore for SplitMix64 {
    #[inline]
    fn next_u32(&mut self) -> u32 {
        self.x = self.x.wrapping_add(PHI);
        let mut z = self.x;
        // David Stafford's
        // (http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html)
        // "Mix4" variant of the 64-bit finalizer in Austin Appleby's
        // MurmurHash3 algorithm.
        z = (z ^ (z >> 33)).wrapping_mul(0x62A9D9ED799705F5);
        z = (z ^ (z >> 28)).wrapping_mul(0xCB24D0A5C88C35B3);
        (z >> 32) as u32
    }

    #[inline]
    fn next_u64(&mut self) -> u64 {
        self.x = self.x.wrapping_add(PHI);
        let mut z = self.x;
        z = (z ^ (z >> 30)).wrapping_mul(0xbf58476d1ce4e5b9);
        z = (z ^ (z >> 27)).wrapping_mul(0x94d049bb133111eb);
        z ^ (z >> 31)
    }

    #[inline]
    fn fill_bytes(&mut self, dest: &mut [u8]) {
        fill_bytes_via_next(self, dest);
    }

    #[inline]
    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.fill_bytes(dest);
        Ok(())
    }
}

impl SeedableRng for SplitMix64 {
    type Seed = [u8; 8];

    /// Create a new `SplitMix64`.
    fn from_seed(seed: [u8; 8]) -> SplitMix64 {
        let mut state = [0; 1];
        read_u64_into(&seed, &mut state);
        SplitMix64 {
            x: state[0],
        }
    }

    /// Seed a `SplitMix64` from a `u64`.
    fn seed_from_u64(seed: u64) -> SplitMix64 {
        let mut x = [0; 8];
        LittleEndian::write_u64(&mut x, seed);
        SplitMix64::from_seed(x)
    }
}

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

    #[test]
    fn reference() {
        let mut rng = SplitMix64::seed_from_u64(1477776061723855037);
        // These values were produced with the reference implementation:
        // http://xoshiro.di.unimi.it/splitmix64.c
        let expected : [u64 ; 50]= [
            1985237415132408290, 2979275885539914483, 13511426838097143398,
            8488337342461049707, 15141737807933549159, 17093170987380407015,
            16389528042912955399, 13177319091862933652, 10841969400225389492,
            17094824097954834098, 3336622647361835228, 9678412372263018368,
            11111587619974030187, 7882215801036322410, 5709234165213761869,
            7799681907651786826, 4616320717312661886, 4251077652075509767,
            7836757050122171900, 5054003328188417616, 12919285918354108358,
            16477564761813870717, 5124667218451240549, 18099554314556827626,
            7603784838804469118, 6358551455431362471, 3037176434532249502,
            3217550417701719149, 9958699920490216947, 5965803675992506258,
            12000828378049868312, 12720568162811471118, 245696019213873792,
            8351371993958923852, 14378754021282935786, 5655432093647472106,
            5508031680350692005, 8515198786865082103, 6287793597487164412,
            14963046237722101617, 3630795823534910476, 8422285279403485710,
            10554287778700714153, 10871906555720704584, 8659066966120258468,
            9420238805069527062, 10338115333623340156, 13514802760105037173,
            14635952304031724449, 15419692541594102413,
        ];
        for &e in expected.iter() {
            assert_eq!(rng.next_u64(), e);
        }
    }

    #[test]
    fn next_u32() {
        let mut rng = SplitMix64::seed_from_u64(10);
        // These values were produced with the reference implementation:
        // http://dsiutils.di.unimi.it/dsiutils-2.5.1-src.tar.gz
        let expected : [u32 ; 100]= [
            3930361779, 4016923089, 4113052479, 925926767, 1755287528,
            802865554, 954171070, 3724185978, 173676273, 1414488795, 12664133,
            1784889697, 1303817078, 261610523, 941280008, 2571813643,
            2954453492, 378291111, 2546873158, 3923319175, 645257028,
            3881821278, 2681538690, 3037029984, 1999958137, 1853970361,
            2989951788, 2126166628, 839962987, 3989679659, 3656977858,
            684284364, 1673258011, 170979192, 3037622326, 1600748179,
            1780764218, 1141430714, 4139736875, 3336905707, 2262051600,
            3830850262, 2430765325, 1073032139, 1668888979, 2716938970,
            4102420032, 40305196, 386350562, 2754480591, 622869439, 2129598760,
            2306038241, 4218338739, 412298926, 3453855056, 3061469690,
            4284292697, 994843708, 1591016681, 414726151, 1238182607, 18073498,
            1237631493, 351884714, 2347486264, 2488990876, 802846256, 645670443,
            957607012, 3126589776, 1966356370, 3036485766, 868696717,
            2808613630, 2070968151, 1025536863, 1743949425, 466212687,
            2994327271, 209776458, 1246125124, 3344380309, 2203947859,
            968313105, 2805485302, 197484837, 3472483632, 3931823935,
            3288490351, 4165666529, 3671080416, 689542830, 1272555356,
            1039141475, 3984640460, 4142959054, 2252788890, 2459379590,
            991872507,
        ];
        for &e in expected.iter() {
            assert_eq!(rng.next_u32(), e);
        }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;

use crate::requests::*;
use crate::types::*;

/// Use this method to send an audio
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[must_use = "requests do nothing unless sent"]
pub struct SendAudio<'c, 'p, 't> {
    chat_id: ChatRef,
    audio: InputFile,
    caption: Option<Cow<'c, str>>,
    parse_mode: Option<ParseMode>,
    duration: Option<i64>,
    performer: Option<Cow<'p, str>>,
    title: Option<Cow<'t, str>>,
    reply_to_message_id: Option<MessageId>,
    disable_notification: bool,
    reply_markup: Option<ReplyMarkup>,
}

impl<'c, 'p, 't> ToMultipart for SendAudio<'c, 'p, 't> {
    fn to_multipart(&self) -> Result<Multipart, Error> {
        multipart_map! {
            self,
            (chat_id (text));
            (audio (raw));
            (caption (text), optional);
            (parse_mode (text), optional);
            (duration (text), optional);
            (performer (text), optional);
            (title (text), optional);
            (reply_to_message_id (text), optional);
            (disable_notification (text), when_true);
            (reply_markup (json), optional);
        }
    }
}

impl<'c, 'p, 't> Request for SendAudio<'c, 'p, 't> {
    type Type = MultipartRequestType<Self>;
    type Response = JsonIdResponse<Message>;

    fn serialize(&self) -> Result<HttpRequest, Error> {
        Self::Type::serialize(RequestUrl::method("sendAudio"), self)
    }
}

impl<'c, 'p, 't> SendAudio<'c, 'p, 't> {
    pub fn new<C, V>(chat: C, audio: V) -> Self
    where
        C: ToChatRef,
        V: Into<InputFile>,
    {
        Self {
            chat_id: chat.to_chat_ref(),
            audio: audio.into(),
            caption: None,
            parse_mode: None,
            duration: None,
            performer: None,
            title: None,
            reply_to_message_id: None,
            reply_markup: None,
            disable_notification: false,
        }
    }

    pub fn caption<T>(&mut self, caption: T) -> &mut Self
    where
        T: Into<Cow<'c, str>>,
    {
        self.caption = Some(caption.into());
        self
    }

    pub fn parse_mode(&mut self, parse_mode: ParseMode) -> &mut Self {
        self.parse_mode = Some(parse_mode);
        self
    }

    pub fn duration(&mut self, duration: i64) -> &mut Self {
        self.duration = Some(duration);
        self
    }

    pub fn performer<T>(&mut self, performer: T) -> &mut Self
    where
        T: Into<Cow<'p, str>>,
    {
        self.performer = Some(performer.into());
        self
    }

    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<Cow<'t, str>>,
    {
        self.title = Some(title.into());
        self
    }

    pub fn reply_to<R>(&mut self, to: R) -> &mut Self
    where
        R: ToMessageId,
    {
        self.reply_to_message_id = Some(to.to_message_id());
        self
    }

    pub fn reply_markup<R>(&mut self, reply_markup: R) -> &mut Self
    where
        R: Into<ReplyMarkup>,
    {
        self.reply_markup = Some(reply_markup.into());
        self
    }
}

/// Can reply with an audio
pub trait CanReplySendAudio {
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanReplySendAudio for M
where
    M: ToMessageId + ToSourceChat,
{
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        let mut req = SendAudio::new(self.to_source_chat(), audio);
        req.reply_to(self);
        req
    }
}

/// Send an audio
pub trait CanSendAudio {
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanSendAudio for M
where
    M: ToChatRef,
{
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        SendAudio::new(self.to_chat_ref(), audio)
    }
}
<commit_msg>feat: add field thumb to sendAudio request<commit_after>use std::borrow::Cow;

use crate::requests::*;
use crate::types::*;

/// Use this method to send an audio
#[derive(Debug, Clone, PartialEq, PartialOrd)]
#[must_use = "requests do nothing unless sent"]
pub struct SendAudio<'c, 'p, 't> {
    chat_id: ChatRef,
    audio: InputFile,
    caption: Option<Cow<'c, str>>,
    parse_mode: Option<ParseMode>,
    duration: Option<i64>,
    performer: Option<Cow<'p, str>>,
    title: Option<Cow<'t, str>>,
    thumb: Option<InputFile>,
    reply_to_message_id: Option<MessageId>,
    disable_notification: bool,
    reply_markup: Option<ReplyMarkup>,
}

impl<'c, 'p, 't> ToMultipart for SendAudio<'c, 'p, 't> {
    fn to_multipart(&self) -> Result<Multipart, Error> {
        multipart_map! {
            self,
            (chat_id (text));
            (audio (raw));
            (caption (text), optional);
            (parse_mode (text), optional);
            (duration (text), optional);
            (performer (text), optional);
            (title (text), optional);
            (thumb (raw), optional);
            (reply_to_message_id (text), optional);
            (disable_notification (text), when_true);
            (reply_markup (json), optional);
        }
    }
}

impl<'c, 'p, 't> Request for SendAudio<'c, 'p, 't> {
    type Type = MultipartRequestType<Self>;
    type Response = JsonIdResponse<Message>;

    fn serialize(&self) -> Result<HttpRequest, Error> {
        Self::Type::serialize(RequestUrl::method("sendAudio"), self)
    }
}

impl<'c, 'p, 't> SendAudio<'c, 'p, 't> {
    pub fn new<C, V>(chat: C, audio: V) -> Self
    where
        C: ToChatRef,
        V: Into<InputFile>,
    {
        Self {
            chat_id: chat.to_chat_ref(),
            audio: audio.into(),
            caption: None,
            parse_mode: None,
            duration: None,
            performer: None,
            title: None,
            thumb: None,
            reply_to_message_id: None,
            reply_markup: None,
            disable_notification: false,
        }
    }

    pub fn thumb<V>(&mut self, thumb: V) -> &mut Self
    where
        V: Into<InputFileUpload>,
    {
        self.thumb = Some(thumb.into().into());
        self
    }

    pub fn caption<T>(&mut self, caption: T) -> &mut Self
    where
        T: Into<Cow<'c, str>>,
    {
        self.caption = Some(caption.into());
        self
    }

    pub fn parse_mode(&mut self, parse_mode: ParseMode) -> &mut Self {
        self.parse_mode = Some(parse_mode);
        self
    }

    pub fn duration(&mut self, duration: i64) -> &mut Self {
        self.duration = Some(duration);
        self
    }

    pub fn performer<T>(&mut self, performer: T) -> &mut Self
    where
        T: Into<Cow<'p, str>>,
    {
        self.performer = Some(performer.into());
        self
    }

    pub fn title<T>(&mut self, title: T) -> &mut Self
    where
        T: Into<Cow<'t, str>>,
    {
        self.title = Some(title.into());
        self
    }

    pub fn reply_to<R>(&mut self, to: R) -> &mut Self
    where
        R: ToMessageId,
    {
        self.reply_to_message_id = Some(to.to_message_id());
        self
    }

    pub fn reply_markup<R>(&mut self, reply_markup: R) -> &mut Self
    where
        R: Into<ReplyMarkup>,
    {
        self.reply_markup = Some(reply_markup.into());
        self
    }
}

/// Can reply with an audio
pub trait CanReplySendAudio {
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanReplySendAudio for M
where
    M: ToMessageId + ToSourceChat,
{
    fn audio_reply<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        let mut req = SendAudio::new(self.to_source_chat(), audio);
        req.reply_to(self);
        req
    }
}

/// Send an audio
pub trait CanSendAudio {
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>;
}

impl<M> CanSendAudio for M
where
    M: ToChatRef,
{
    fn audio<'c, 'p, 't, T>(&self, audio: T) -> SendAudio<'c, 'p, 't>
    where
        T: Into<InputFile>,
    {
        SendAudio::new(self.to_chat_ref(), audio)
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cssparser::SourceLocation;
use euclid::ScaleFactor;
use euclid::TypedSize2D;
use html5ever::LocalName;
use selectors::parser::{AncestorHashes, Selector};
use selectors::parser::LocalName as LocalNameSelector;
use servo_arc::Arc;
use servo_atoms::Atom;
use style::context::QuirksMode;
use style::media_queries::{Device, MediaType};
use style::properties::{PropertyDeclarationBlock, PropertyDeclaration};
use style::properties::{longhands, Importance};
use style::selector_map::{self, SelectorMap};
use style::selector_parser::{SelectorImpl, SelectorParser};
use style::shared_lock::SharedRwLock;
use style::stylesheets::StyleRule;
use style::stylist::{Stylist, Rule};
use style::stylist::needs_revalidation_for_testing;
use style::thread_state;

/// Helper method to get some Rules from selector strings.
/// Each sublist of the result contains the Rules for one StyleRule.
fn get_mock_rules(css_selectors: &[&str]) -> (Vec<Vec<Rule>>, SharedRwLock) {
    let shared_lock = SharedRwLock::new();
    (css_selectors.iter().enumerate().map(|(i, selectors)| {
        let selectors = SelectorParser::parse_author_origin_no_namespace(selectors).unwrap();

        let locked = Arc::new(shared_lock.wrap(StyleRule {
            selectors: selectors,
            block: Arc::new(shared_lock.wrap(PropertyDeclarationBlock::with_one(
                PropertyDeclaration::Display(
                    longhands::display::SpecifiedValue::block),
                Importance::Normal
            ))),
            source_location: SourceLocation {
                line: 0,
                column: 0,
            },
        }));

        let guard = shared_lock.read();
        let rule = locked.read_with(&guard);
        rule.selectors.0.iter().map(|s| {
            Rule::new(s.clone(), AncestorHashes::new(s, QuirksMode::NoQuirks), locked.clone(), i as u32)
        }).collect()
    }).collect(), shared_lock)
}

fn parse_selectors(selectors: &[&str]) -> Vec<Selector<SelectorImpl>> {
    selectors.iter()
             .map(|x| SelectorParser::parse_author_origin_no_namespace(x).unwrap().0
                                                                         .into_iter()
                                                                         .nth(0)
                                                                         .unwrap())
             .collect()
}

#[test]
fn test_revalidation_selectors() {
    let test = parse_selectors(&[
        // Not revalidation selectors.
        "div",
        "div:not(.foo)",
        "div span",
        "div > span",

        // ID selectors.
        "#foo1",
        "#foo2::before",
        "#foo3 > span",
        "#foo1 > span", // FIXME(bz): This one should not be a
                        // revalidation selector, since #foo1 should be in the
                        // rule hash.

        // Attribute selectors.
        "div[foo]",
        "div:not([foo])",
        "div[foo = \"bar\"]",
        "div[foo ~= \"bar\"]",
        "div[foo |= \"bar\"]",
        "div[foo ^= \"bar\"]",
        "div[foo $= \"bar\"]",
        "div[foo *= \"bar\"]",
        "*|div[foo][bar = \"baz\"]",

        // Non-state-based pseudo-classes.
        "div:empty",
        "div:first-child",
        "div:last-child",
        "div:only-child",
        "div:nth-child(2)",
        "div:nth-last-child(2)",
        "div:nth-of-type(2)",
        "div:nth-last-of-type(2)",
        "div:first-of-type",
        "div:last-of-type",
        "div:only-of-type",

        // Note: it would be nice to test :moz-any and the various other non-TS
        // pseudo classes supported by gecko, but we don't have access to those
        // in these unit tests. :-(

        // Sibling combinators.
        "span + div",
        "span ~ div",

        // Selectors in the ancestor chain (needed for cousin sharing).
        "p:first-child span",
    ]).into_iter()
      .filter(|s| needs_revalidation_for_testing(&s))
      .collect::<Vec<_>>();

    let reference = parse_selectors(&[
        // ID selectors.
        "#foo3 > span",
        "#foo1 > span",

        // Attribute selectors.
        "div[foo]",
        "div:not([foo])",
        "div[foo = \"bar\"]",
        "div[foo ~= \"bar\"]",
        "div[foo |= \"bar\"]",
        "div[foo ^= \"bar\"]",
        "div[foo $= \"bar\"]",
        "div[foo *= \"bar\"]",
        "*|div[foo][bar = \"baz\"]",

        // Non-state-based pseudo-classes.
        "div:empty",
        "div:first-child",
        "div:last-child",
        "div:only-child",
        "div:nth-child(2)",
        "div:nth-last-child(2)",
        "div:nth-of-type(2)",
        "div:nth-last-of-type(2)",
        "div:first-of-type",
        "div:last-of-type",
        "div:only-of-type",

        // Sibling combinators.
        "span + div",
        "span ~ div",

        // Selectors in the ancestor chain (needed for cousin sharing).
        "p:first-child span",
    ]).into_iter()
      .collect::<Vec<_>>();

    assert_eq!(test.len(), reference.len());
    for (t, r) in test.into_iter().zip(reference.into_iter()) {
        assert_eq!(t, r)
    }
}

#[test]
fn test_rule_ordering_same_specificity() {
    let (rules_list, _) = get_mock_rules(&["a.intro", "img.sidebar"]);
    let a = &rules_list[0][0];
    let b = &rules_list[1][0];
    assert!((a.specificity(), a.source_order) < ((b.specificity(), b.source_order)),
            "The rule that comes later should win.");
}

#[test]
fn test_insert() {
    let (rules_list, _) = get_mock_rules(&[".intro.foo", "#top"]);
    let mut selector_map = SelectorMap::new();
    selector_map.insert(rules_list[1][0].clone(), QuirksMode::NoQuirks);
    assert_eq!(1, selector_map.id_hash.get(&Atom::from("top"), QuirksMode::NoQuirks).unwrap()[0].source_order);
    selector_map.insert(rules_list[0][0].clone(), QuirksMode::NoQuirks);
    assert_eq!(0, selector_map.class_hash.get(&Atom::from("foo"), QuirksMode::NoQuirks).unwrap()[0].source_order);
    assert!(selector_map.class_hash.get(&Atom::from("intro"), QuirksMode::NoQuirks).is_none());
}

fn mock_stylist() -> Stylist {
    let device = Device::new(MediaType::screen(), TypedSize2D::new(0f32, 0f32), ScaleFactor::new(1.0));
    Stylist::new(device, QuirksMode::NoQuirks)
}

#[test]
fn test_stylist_device_accessors() {
    thread_state::initialize(thread_state::LAYOUT);
    let stylist = mock_stylist();
    assert_eq!(stylist.device().media_type(), MediaType::screen());
    let mut stylist_mut = mock_stylist();
    assert_eq!(stylist_mut.device_mut().media_type(), MediaType::screen());
}

#[test]
fn test_stylist_rule_tree_accessors() {
    thread_state::initialize(thread_state::LAYOUT);
    let stylist = mock_stylist();
    stylist.rule_tree();
    stylist.rule_tree().root();
}
<commit_msg>Remove unused imports from stylist tests<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cssparser::SourceLocation;
use euclid::ScaleFactor;
use euclid::TypedSize2D;
use selectors::parser::{AncestorHashes, Selector};
use servo_arc::Arc;
use servo_atoms::Atom;
use style::context::QuirksMode;
use style::media_queries::{Device, MediaType};
use style::properties::{PropertyDeclarationBlock, PropertyDeclaration};
use style::properties::{longhands, Importance};
use style::selector_map::SelectorMap;
use style::selector_parser::{SelectorImpl, SelectorParser};
use style::shared_lock::SharedRwLock;
use style::stylesheets::StyleRule;
use style::stylist::{Stylist, Rule};
use style::stylist::needs_revalidation_for_testing;
use style::thread_state;

/// Helper method to get some Rules from selector strings.
/// Each sublist of the result contains the Rules for one StyleRule.
fn get_mock_rules(css_selectors: &[&str]) -> (Vec<Vec<Rule>>, SharedRwLock) {
    let shared_lock = SharedRwLock::new();
    (css_selectors.iter().enumerate().map(|(i, selectors)| {
        let selectors = SelectorParser::parse_author_origin_no_namespace(selectors).unwrap();

        let locked = Arc::new(shared_lock.wrap(StyleRule {
            selectors: selectors,
            block: Arc::new(shared_lock.wrap(PropertyDeclarationBlock::with_one(
                PropertyDeclaration::Display(
                    longhands::display::SpecifiedValue::block),
                Importance::Normal
            ))),
            source_location: SourceLocation {
                line: 0,
                column: 0,
            },
        }));

        let guard = shared_lock.read();
        let rule = locked.read_with(&guard);
        rule.selectors.0.iter().map(|s| {
            Rule::new(s.clone(), AncestorHashes::new(s, QuirksMode::NoQuirks), locked.clone(), i as u32)
        }).collect()
    }).collect(), shared_lock)
}

fn parse_selectors(selectors: &[&str]) -> Vec<Selector<SelectorImpl>> {
    selectors.iter()
             .map(|x| SelectorParser::parse_author_origin_no_namespace(x).unwrap().0
                                                                         .into_iter()
                                                                         .nth(0)
                                                                         .unwrap())
             .collect()
}

#[test]
fn test_revalidation_selectors() {
    let test = parse_selectors(&[
        // Not revalidation selectors.
        "div",
        "div:not(.foo)",
        "div span",
        "div > span",

        // ID selectors.
        "#foo1",
        "#foo2::before",
        "#foo3 > span",
        "#foo1 > span", // FIXME(bz): This one should not be a
                        // revalidation selector, since #foo1 should be in the
                        // rule hash.

        // Attribute selectors.
        "div[foo]",
        "div:not([foo])",
        "div[foo = \"bar\"]",
        "div[foo ~= \"bar\"]",
        "div[foo |= \"bar\"]",
        "div[foo ^= \"bar\"]",
        "div[foo $= \"bar\"]",
        "div[foo *= \"bar\"]",
        "*|div[foo][bar = \"baz\"]",

        // Non-state-based pseudo-classes.
        "div:empty",
        "div:first-child",
        "div:last-child",
        "div:only-child",
        "div:nth-child(2)",
        "div:nth-last-child(2)",
        "div:nth-of-type(2)",
        "div:nth-last-of-type(2)",
        "div:first-of-type",
        "div:last-of-type",
        "div:only-of-type",

        // Note: it would be nice to test :moz-any and the various other non-TS
        // pseudo classes supported by gecko, but we don't have access to those
        // in these unit tests. :-(

        // Sibling combinators.
        "span + div",
        "span ~ div",

        // Selectors in the ancestor chain (needed for cousin sharing).
        "p:first-child span",
    ]).into_iter()
      .filter(|s| needs_revalidation_for_testing(&s))
      .collect::<Vec<_>>();

    let reference = parse_selectors(&[
        // ID selectors.
        "#foo3 > span",
        "#foo1 > span",

        // Attribute selectors.
        "div[foo]",
        "div:not([foo])",
        "div[foo = \"bar\"]",
        "div[foo ~= \"bar\"]",
        "div[foo |= \"bar\"]",
        "div[foo ^= \"bar\"]",
        "div[foo $= \"bar\"]",
        "div[foo *= \"bar\"]",
        "*|div[foo][bar = \"baz\"]",

        // Non-state-based pseudo-classes.
        "div:empty",
        "div:first-child",
        "div:last-child",
        "div:only-child",
        "div:nth-child(2)",
        "div:nth-last-child(2)",
        "div:nth-of-type(2)",
        "div:nth-last-of-type(2)",
        "div:first-of-type",
        "div:last-of-type",
        "div:only-of-type",

        // Sibling combinators.
        "span + div",
        "span ~ div",

        // Selectors in the ancestor chain (needed for cousin sharing).
        "p:first-child span",
    ]).into_iter()
      .collect::<Vec<_>>();

    assert_eq!(test.len(), reference.len());
    for (t, r) in test.into_iter().zip(reference.into_iter()) {
        assert_eq!(t, r)
    }
}

#[test]
fn test_rule_ordering_same_specificity() {
    let (rules_list, _) = get_mock_rules(&["a.intro", "img.sidebar"]);
    let a = &rules_list[0][0];
    let b = &rules_list[1][0];
    assert!((a.specificity(), a.source_order) < ((b.specificity(), b.source_order)),
            "The rule that comes later should win.");
}

#[test]
fn test_insert() {
    let (rules_list, _) = get_mock_rules(&[".intro.foo", "#top"]);
    let mut selector_map = SelectorMap::new();
    selector_map.insert(rules_list[1][0].clone(), QuirksMode::NoQuirks);
    assert_eq!(1, selector_map.id_hash.get(&Atom::from("top"), QuirksMode::NoQuirks).unwrap()[0].source_order);
    selector_map.insert(rules_list[0][0].clone(), QuirksMode::NoQuirks);
    assert_eq!(0, selector_map.class_hash.get(&Atom::from("foo"), QuirksMode::NoQuirks).unwrap()[0].source_order);
    assert!(selector_map.class_hash.get(&Atom::from("intro"), QuirksMode::NoQuirks).is_none());
}

fn mock_stylist() -> Stylist {
    let device = Device::new(MediaType::screen(), TypedSize2D::new(0f32, 0f32), ScaleFactor::new(1.0));
    Stylist::new(device, QuirksMode::NoQuirks)
}

#[test]
fn test_stylist_device_accessors() {
    thread_state::initialize(thread_state::LAYOUT);
    let stylist = mock_stylist();
    assert_eq!(stylist.device().media_type(), MediaType::screen());
    let mut stylist_mut = mock_stylist();
    assert_eq!(stylist_mut.device_mut().media_type(), MediaType::screen());
}

#[test]
fn test_stylist_rule_tree_accessors() {
    thread_state::initialize(thread_state::LAYOUT);
    let stylist = mock_stylist();
    stylist.rule_tree();
    stylist.rule_tree().root();
}
<|endoftext|>


<commit_before>#![allow(clippy::borrowed_box)]

use crate::error::*;

use crate::buffer::Buffered;
use std::any::Any;
use std::io::SeekFrom;
use std::sync::Arc;

use crate::common::*;

use crate::data::packet::Packet;
use crate::stream::Stream;

/// Events processed by a demuxer analyzing a source.
#[non_exhaustive]
#[derive(Clone, Debug)]
pub enum Event {
    /// A new packet is found by a demuxer.
    NewPacket(Packet),
    /// A new stream is found by a demuxer.
    NewStream(Stream),
    /// More data are needed by a demuxer to complete its operations.
    MoreDataNeeded(usize),
    /// Event not processable by a demuxer.
    ///
    /// Demux the next event.
    Continue,
    /// End of File.
    ///
    /// Stop demuxing data.
    Eof,
}

/// Used to implement demuxing operations.
pub trait Demuxer: Send + Sync {
    /// Reads stream headers and global information from a data structure
    /// implementing the `Buffered` trait.
    ///
    /// Global information are saved into a `GlobalInfo` structure.
    fn read_headers(&mut self, buf: &mut dyn Buffered, info: &mut GlobalInfo) -> Result<SeekFrom>;
    /// Reads an event from a data structure implementing the `Buffered` trait.
    fn read_event(&mut self, buf: &mut dyn Buffered) -> Result<(SeekFrom, Event)>;
}

/// Auxiliary structure to encapsulate a demuxer object and
/// its additional data.
pub struct Context<R: Buffered> {
    demuxer: Box<dyn Demuxer>,
    reader: R,
    /// Global media file information.
    pub info: GlobalInfo,
    /// User private data.
    ///
    /// This data cannot be cloned.
    pub user_private: Option<Arc<dyn Any + Send + Sync>>,
}

impl<R: Buffered> Context<R> {
    /// Creates a new `Context` instance.
    pub fn new(demuxer: Box<dyn Demuxer>, reader: R) -> Self {
        Context {
            demuxer,
            reader,
            info: GlobalInfo {
                duration: None,
                timebase: None,
                streams: Vec::with_capacity(2),
            },
            user_private: None,
        }
    }

    fn read_headers_internal(&mut self) -> Result<()> {
        let demux = &mut self.demuxer;

        let res = demux.read_headers(&mut self.reader, &mut self.info);
        match res {
            Err(e) => Err(e),
            Ok(seek) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                trace!("stream now at index: {:?}", res);
                Ok(())
            }
        }
    }

    /// Reads stream headers and global information from a data source.
    pub fn read_headers(&mut self) -> Result<()> {
        loop {
            // TODO: wrap fill_buf() with a check for Eof
            self.reader.fill_buf()?;
            match self.read_headers_internal() {
                Err(e) => match e {
                    Error::MoreDataNeeded(needed) => {
                        self.reader.grow(needed);
                    }
                    _ => return Err(e),
                },
                Ok(_) => return Ok(()),
            }
        }
    }

    fn read_event_internal(&mut self) -> Result<Event> {
        let demux = &mut self.demuxer;

        let res = demux.read_event(&mut self.reader);
        match res {
            Err(e) => Err(e),
            Ok((seek, mut event)) => {
                //TODO: handle seeking here
                let _ = self.reader.seek(seek)?;
                if let Event::NewStream(ref st) = event {
                    self.info.streams.push(st.clone());
                }
                if let Event::MoreDataNeeded(size) = event {
                    return Err(Error::MoreDataNeeded(size));
                }
                if let Event::NewPacket(ref mut pkt) = event {
                    if pkt.t.timebase.is_none() {
                        if let Some(st) = self
                            .info
                            .streams
                            .iter()
                            .find(|s| s.index as isize == pkt.stream_index)
                        {
                            pkt.t.timebase = Some(st.timebase);
                        }
                    }
                }
                Ok(event)
            }
        }
    }

    /// Reads an event from a data source.
    pub fn read_event(&mut self) -> Result<Event> {
        // TODO: guard against infiniloops and maybe factor the loop.
        loop {
            match self.read_event_internal() {
                Err(e) => match e {
                    Error::MoreDataNeeded(needed) => {
                        let len = self.reader.data().len();

                        // we might have sent MoreDatNeeded(0) to request a new call
                        if len >= needed {
                            continue;
                        }
                        self.reader.grow(needed);
                        self.reader.fill_buf()?;
                        if self.reader.data().len() <= len {
                            return Ok(Event::Eof);
                        }
                    }
                    _ => return Err(e),
                },
                Ok(ev) => return Ok(ev),
            }
        }
    }
}

/// Format descriptor.
///
/// Contains information on a format and its own demuxer.
#[derive(Clone, Debug, PartialEq)]
pub struct Descr {
    /// Format name.
    pub name: &'static str,
    /// Demuxer name.
    pub demuxer: &'static str,
    /// Format description.
    pub description: &'static str,
    /// Format media file extensions.
    pub extensions: &'static [&'static str],
    /// Format MIME.
    pub mime: &'static [&'static str],
}

/// Used to get a format descriptor and create a new demuxer.
pub trait Descriptor {
    /// Creates a new demuxer for the requested format.
    fn create(&self) -> Box<dyn Demuxer>;
    /// Returns the descriptor of a format.
    fn describe(&self) -> &Descr;

    /// Returns a score which represents how much the input data are associated
    /// to a format.
    fn probe(&self, data: &[u8]) -> u8;
}

/// Maximum data size to probe a format.
pub const PROBE_DATA: usize = 4 * 1024;

/// Data whose probe score is equal or greater than the value of this constant
/// surely is associated to the format currently being analyzed.
pub const PROBE_SCORE_EXTENSION: u8 = 50;

/// Used to define different ways to probe a format.
pub trait Probe {
    /// Probes whether the input data is associated to a determined format.
    fn probe(&self, data: &[u8]) -> Option<&'static dyn Descriptor>;
}

impl<'a> Probe for [&'static dyn Descriptor] {
    fn probe(&self, data: &[u8]) -> Option<&'static dyn Descriptor> {
        let mut max = u8::min_value();
        let mut candidate: Option<&'static dyn Descriptor> = None;
        for desc in self {
            let score = desc.probe(data);

            if score > max {
                max = score;
                candidate = Some(*desc);
            }
        }

        if max > PROBE_SCORE_EXTENSION {
            candidate
        } else {
            None
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::data::packet::Packet;
    use std::io::SeekFrom;

    struct DummyDes {
        d: Descr,
    }

    struct DummyDemuxer {}

    impl Demuxer for DummyDemuxer {
        fn read_headers(
            &mut self,
            buf: &mut dyn Buffered,
            _info: &mut GlobalInfo,
        ) -> Result<SeekFrom> {
            let len = buf.data().len();
            if 9 > len {
                let needed = 9 - len;
                Err(Error::MoreDataNeeded(needed))
            } else {
                Ok(SeekFrom::Current(9))
            }
        }
        fn read_event(&mut self, buf: &mut dyn Buffered) -> Result<(SeekFrom, Event)> {
            let size = 2;
            let len = buf.data().len();
            if size > len {
                Err(Error::MoreDataNeeded(size - len))
            } else {
                debug!("{:?}", buf.data());
                match &buf.data()[..2] {
                    b"p1" => Ok((SeekFrom::Current(3), Event::NewPacket(Packet::new()))),
                    b"e1" => Ok((SeekFrom::Current(3), Event::MoreDataNeeded(0))),
                    _ => Err(Error::InvalidData),
                }
            }
        }
    }

    impl Descriptor for DummyDes {
        fn create(&self) -> Box<dyn Demuxer> {
            Box::new(DummyDemuxer {})
        }
        fn describe<'a>(&'_ self) -> &'_ Descr {
            &self.d
        }
        fn probe(&self, data: &[u8]) -> u8 {
            match data {
                b"dummy" => 100,
                _ => 0,
            }
        }
    }

    const DUMMY_DES: &dyn Descriptor = &DummyDes {
        d: Descr {
            name: "dummy",
            demuxer: "dummy",
            description: "Dummy dem",
            extensions: &["dm", "dum"],
            mime: &["application/dummy"],
        },
    };

    #[test]
    fn probe() {
        let demuxers: &[&'static dyn Descriptor] = &[DUMMY_DES];

        demuxers.probe(b"dummy").unwrap();
    }

    use crate::buffer::*;
    use std::io::Cursor;

    #[test]
    fn read_headers() {
        let buf = b"dummy header";
        let r = AccReader::with_capacity(4, Cursor::new(buf));
        let d = DUMMY_DES.create();
        let mut c = Context::new(d, r);

        c.read_headers().unwrap();
    }

    #[test]
    fn read_event() {
        let buf = b"dummy header p1 e1 p1 ";

        let r = AccReader::with_capacity(4, Cursor::new(buf));
        let d = DUMMY_DES.create();
        let mut c = Context::new(d, r);

        c.read_headers().unwrap();

        println!("{:?}", c.read_event());
        println!("{:?}", c.read_event());
        println!("{:?}", c.read_event());
        println!("{:?}", c.read_event());
    }
}
<commit_msg>format: Replace Box with a generic for Demuxer<commit_after>#![allow(clippy::borrowed_box)]

use crate::error::*;

use crate::buffer::Buffered;
use std::any::Any;
use std::io::SeekFrom;
use std::sync::Arc;

use crate::common::*;

use crate::data::packet::Packet;
use crate::stream::Stream;

/// Events processed by a demuxer analyzing a source.
#[non_exhaustive]
#[derive(Clone, Debug)]
pub enum Event {
    /// A new packet is found by a demuxer.
    NewPacket(Packet),
    /// A new stream is found by a demuxer.
    NewStream(Stream),
    /// More data are needed by a demuxer to complete its operations.
    MoreDataNeeded(usize),
    /// Event not processable by a demuxer.
    ///
    /// Demux the next event.
    Continue,
    /// End of File.
    ///
    /// Stop demuxing data.
    Eof,
}

/// Used to implement demuxing operations.
pub trait Demuxer: Send + Sync {
    /// Reads stream headers and global information from a data structure
    /// implementing the `Buffered` trait.
    ///
    /// Global information are saved into a `GlobalInfo` structure.
    fn read_headers(&mut self, buf: &mut dyn Buffered, info: &mut GlobalInfo) -> Result<SeekFrom>;
    /// Reads an event from a data structure implementing the `Buffered` trait.
    fn read_event(&mut self, buf: &mut dyn Buffered) -> Result<(SeekFrom, Event)>;
}

/// Auxiliary structure to encapsulate a demuxer object and
/// its additional data.
pub struct Context<D: Demuxer, R: Buffered> {
    demuxer: D,
    reader: R,
    /// Global media file information.
    pub info: GlobalInfo,
    /// User private data.
    ///
    /// This data cannot be cloned.
    pub user_private: Option<Arc<dyn Any + Send + Sync>>,
}

impl<D: Demuxer, R: Buffered> Context<D, R> {
    /// Creates a new `Context` instance.
    pub fn new(demuxer: D, reader: R) -> Self {
        Context {
            demuxer,
            reader,
            info: GlobalInfo {
                duration: None,
                timebase: None,
                streams: Vec::with_capacity(2),
            },
            user_private: None,
        }
    }

    fn read_headers_internal(&mut self) -> Result<()> {
        let demux = &mut self.demuxer;

        let res = demux.read_headers(&mut self.reader, &mut self.info);
        match res {
            Err(e) => Err(e),
            Ok(seek) => {
                //TODO: handle seeking here
                let res = self.reader.seek(seek);
                trace!("stream now at index: {:?}", res);
                Ok(())
            }
        }
    }

    /// Reads stream headers and global information from a data source.
    pub fn read_headers(&mut self) -> Result<()> {
        loop {
            // TODO: wrap fill_buf() with a check for Eof
            self.reader.fill_buf()?;
            match self.read_headers_internal() {
                Err(e) => match e {
                    Error::MoreDataNeeded(needed) => {
                        self.reader.grow(needed);
                    }
                    _ => return Err(e),
                },
                Ok(_) => return Ok(()),
            }
        }
    }

    fn read_event_internal(&mut self) -> Result<Event> {
        let demux = &mut self.demuxer;

        let res = demux.read_event(&mut self.reader);
        match res {
            Err(e) => Err(e),
            Ok((seek, mut event)) => {
                //TODO: handle seeking here
                let _ = self.reader.seek(seek)?;
                if let Event::NewStream(ref st) = event {
                    self.info.streams.push(st.clone());
                }
                if let Event::MoreDataNeeded(size) = event {
                    return Err(Error::MoreDataNeeded(size));
                }
                if let Event::NewPacket(ref mut pkt) = event {
                    if pkt.t.timebase.is_none() {
                        if let Some(st) = self
                            .info
                            .streams
                            .iter()
                            .find(|s| s.index as isize == pkt.stream_index)
                        {
                            pkt.t.timebase = Some(st.timebase);
                        }
                    }
                }
                Ok(event)
            }
        }
    }

    /// Reads an event from a data source.
    pub fn read_event(&mut self) -> Result<Event> {
        // TODO: guard against infiniloops and maybe factor the loop.
        loop {
            match self.read_event_internal() {
                Err(e) => match e {
                    Error::MoreDataNeeded(needed) => {
                        let len = self.reader.data().len();

                        // we might have sent MoreDatNeeded(0) to request a new call
                        if len >= needed {
                            continue;
                        }
                        self.reader.grow(needed);
                        self.reader.fill_buf()?;
                        if self.reader.data().len() <= len {
                            return Ok(Event::Eof);
                        }
                    }
                    _ => return Err(e),
                },
                Ok(ev) => return Ok(ev),
            }
        }
    }
}

/// Format descriptor.
///
/// Contains information on a format and its own demuxer.
#[derive(Clone, Debug, PartialEq)]
pub struct Descr {
    /// Format name.
    pub name: &'static str,
    /// Demuxer name.
    pub demuxer: &'static str,
    /// Format description.
    pub description: &'static str,
    /// Format media file extensions.
    pub extensions: &'static [&'static str],
    /// Format MIME.
    pub mime: &'static [&'static str],
}

/// Used to get a format descriptor and create a new demuxer.
pub trait Descriptor {
    type OutputDemuxer: Demuxer;

    /// Creates a new demuxer for the requested format.
    fn create(&self) -> Self::OutputDemuxer;
    /// Returns the descriptor of a format.
    fn describe(&self) -> &Descr;

    /// Returns a score which represents how much the input data are associated
    /// to a format.
    fn probe(&self, data: &[u8]) -> u8;
}

/// Maximum data size to probe a format.
pub const PROBE_DATA: usize = 4 * 1024;

/// Data whose probe score is equal or greater than the value of this constant
/// surely is associated to the format currently being analyzed.
pub const PROBE_SCORE_EXTENSION: u8 = 50;

/// Used to define different ways to probe a format.
pub trait Probe<T: Descriptor + ?Sized> {
    /// Probes whether the input data is associated to a determined format.
    fn probe(&self, data: &[u8]) -> Option<&'static T>;
}

impl<'a, T: Descriptor + ?Sized> Probe<T> for [&'static T] {
    fn probe(&self, data: &[u8]) -> Option<&'static T> {
        let mut max = u8::min_value();
        let mut candidate: Option<&'static T> = None;
        for desc in self {
            let score = desc.probe(data);

            if score > max {
                max = score;
                candidate = Some(*desc);
            }
        }

        if max > PROBE_SCORE_EXTENSION {
            candidate
        } else {
            None
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use crate::data::packet::Packet;
    use std::io::SeekFrom;

    struct DummyDes {
        d: Descr,
    }

    struct DummyDemuxer {}

    impl Demuxer for DummyDemuxer {
        fn read_headers(
            &mut self,
            buf: &mut dyn Buffered,
            _info: &mut GlobalInfo,
        ) -> Result<SeekFrom> {
            let len = buf.data().len();
            if 9 > len {
                let needed = 9 - len;
                Err(Error::MoreDataNeeded(needed))
            } else {
                Ok(SeekFrom::Current(9))
            }
        }
        fn read_event(&mut self, buf: &mut dyn Buffered) -> Result<(SeekFrom, Event)> {
            let size = 2;
            let len = buf.data().len();
            if size > len {
                Err(Error::MoreDataNeeded(size - len))
            } else {
                debug!("{:?}", buf.data());
                match &buf.data()[..2] {
                    b"p1" => Ok((SeekFrom::Current(3), Event::NewPacket(Packet::new()))),
                    b"e1" => Ok((SeekFrom::Current(3), Event::MoreDataNeeded(0))),
                    _ => Err(Error::InvalidData),
                }
            }
        }
    }

    impl Descriptor for DummyDes {
        type OutputDemuxer = DummyDemuxer;

        fn create(&self) -> Self::OutputDemuxer {
            DummyDemuxer {}
        }
        fn describe<'a>(&'_ self) -> &'_ Descr {
            &self.d
        }
        fn probe(&self, data: &[u8]) -> u8 {
            match data {
                b"dummy" => 100,
                _ => 0,
            }
        }
    }

    const DUMMY_DES: &dyn Descriptor<OutputDemuxer = DummyDemuxer> = &DummyDes {
        d: Descr {
            name: "dummy",
            demuxer: "dummy",
            description: "Dummy dem",
            extensions: &["dm", "dum"],
            mime: &["application/dummy"],
        },
    };

    #[test]
    fn probe() {
        let demuxers: &[&'static dyn Descriptor<OutputDemuxer = DummyDemuxer>] = &[DUMMY_DES];

        demuxers.probe(b"dummy").unwrap();
    }

    use crate::buffer::*;
    use std::io::Cursor;

    #[test]
    fn read_headers() {
        let buf = b"dummy header";
        let r = AccReader::with_capacity(4, Cursor::new(buf));
        let d = DUMMY_DES.create();
        let mut c = Context::new(d, r);

        c.read_headers().unwrap();
    }

    #[test]
    fn read_event() {
        let buf = b"dummy header p1 e1 p1 ";

        let r = AccReader::with_capacity(4, Cursor::new(buf));
        let d = DUMMY_DES.create();
        let mut c = Context::new(d, r);

        c.read_headers().unwrap();

        println!("{:?}", c.read_event());
        println!("{:?}", c.read_event());
        println!("{:?}", c.read_event());
        println!("{:?}", c.read_event());
    }
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals, non_camel_case_types)]

extern crate libc;

use std::ffi::CString;
use std::ptr;
use std::str;

pub type UInt32 = ::std::os::raw::c_uint;
pub type SInt16 = ::std::os::raw::c_short;
pub type SInt32 = ::std::os::raw::c_int;

pub type FourCharCode = UInt32;
pub type OSType = FourCharCode;
pub type OSErr = SInt16;

pub const gestaltSystemVersion: ::std::os::raw::c_uint = 1937339254;
pub const gestaltSystemVersionMajor: ::std::os::raw::c_uint = 1937339185;
pub const gestaltSystemVersionMinor: ::std::os::raw::c_uint = 1937339186;
pub const gestaltSystemVersionBugFix: ::std::os::raw::c_uint = 1937339187;

pub type CFRef = *mut ::std::os::raw::c_void;

pub type CFIndex = ::std::os::raw::c_long;
pub type CFTimeInterval = f64;

#[doc(hidden)]
pub enum CFError {}

pub type CFMutableArrayRef = CFRef;
pub type CFURLRef = CFRef;
pub type CFErrorRef = *mut CFError;
pub type CFStringRef = CFRef;
pub type CFRunLoopRef = CFRef;

pub const NULL: CFRef = 0 as CFRef;
pub const NULL_REF_PTR: *mut CFRef = 0 as *mut CFRef;

pub type CFURLPathStyle = ::std::os::raw::c_uint;

pub const kCFAllocatorDefault: CFRef = NULL;
pub const kCFURLPOSIXPathStyle: CFURLPathStyle = 0;
pub const kCFURLHFSPathStyle: CFURLPathStyle = 1;
pub const kCFURLWindowsPathStyle: CFURLPathStyle = 2;

pub const kCFStringEncodingUTF8: u32 = 0x08000100;
pub type CFStringEncoding = u32;

pub const kCFCompareEqualTo: i32 = 0;
pub type CFComparisonResult = i32;

// MacOS uses Case Insensitive path
pub const kCFCompareCaseInsensitive: u32 = 1;
pub type CFStringCompareFlags = u32;

// CFStringEncoding
pub type kCFStringEncoding = u32;
pub const UTF8: kCFStringEncoding = 0x08000100;

#[repr(C)]
pub struct CFArrayCallBacks {
    version: CFIndex,
    retain: CFRef,
    release: CFRef,
    cp: CFRef,
    equal: CFRef,
}
//impl Clone for CFArrayCallBacks { }

#[link(name = "CoreServices", kind = "framework")]
extern "C" {
    pub static kCFTypeArrayCallBacks: CFArrayCallBacks;
    pub static kCFRunLoopDefaultMode: CFStringRef;

    pub fn Gestalt(selector: OSType, response: *const SInt32) -> OSErr;
    pub fn CFRelease(res: CFRef);
    pub fn CFShow(res: CFRef);
    pub fn CFCopyDescription(cf: CFRef) -> CFStringRef;

    pub fn CFRunLoopRun();
    pub fn CFRunLoopStop(run_loop: CFRunLoopRef);
    pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;

    pub fn CFArrayCreateMutable(
        allocator: CFRef,
        capacity: CFIndex,
        callbacks: *const CFArrayCallBacks,
    ) -> CFMutableArrayRef;
    pub fn CFArrayInsertValueAtIndex(arr: CFMutableArrayRef, position: CFIndex, element: CFRef);
    pub fn CFArrayAppendValue(aff: CFMutableArrayRef, element: CFRef);
    pub fn CFArrayGetCount(arr: CFMutableArrayRef) -> CFIndex;
    pub fn CFArrayGetValueAtIndex(arr: CFMutableArrayRef, index: CFIndex) -> CFRef;

    pub fn CFURLCreateFileReferenceURL(
        allocator: CFRef,
        url: CFURLRef,
        err: *mut CFErrorRef,
    ) -> CFURLRef;
    pub fn CFURLCreateFilePathURL(
        allocator: CFRef,
        url: CFURLRef,
        err: *mut CFErrorRef,
    ) -> CFURLRef;
    pub fn CFURLCreateFromFileSystemRepresentation(
        allocator: CFRef,
        path: *const ::std::os::raw::c_char,
        len: CFIndex,
        is_directory: bool,
    ) -> CFURLRef;
    pub fn CFURLCopyAbsoluteURL(res: CFURLRef) -> CFURLRef;
    pub fn CFURLCopyLastPathComponent(res: CFURLRef) -> CFStringRef;
    pub fn CFURLCreateCopyDeletingLastPathComponent(allocator: CFRef, url: CFURLRef) -> CFURLRef;
    pub fn CFURLCreateCopyAppendingPathComponent(
        allocation: CFRef,
        url: CFURLRef,
        path: CFStringRef,
        is_directory: bool,
    ) -> CFURLRef;
    pub fn CFURLCopyFileSystemPath(anUrl: CFURLRef, path_style: CFURLPathStyle) -> CFStringRef;

    pub fn CFURLResourceIsReachable(res: CFURLRef, err: *mut CFErrorRef) -> bool;

    pub fn CFShowStr(str: CFStringRef);
    pub fn CFStringGetCString(
        theString: CFStringRef,
        buffer: *mut ::std::os::raw::c_char,
        buffer_size: CFIndex,
        encoding: CFStringEncoding,
    ) -> bool;
    pub fn CFStringGetCStringPtr(
        theString: CFStringRef,
        encoding: CFStringEncoding,
    ) -> *const ::std::os::raw::c_char;
    pub fn CFStringCreateWithCString(
        alloc: CFRef,
        source: *const ::std::os::raw::c_char,
        encoding: kCFStringEncoding,
    ) -> CFStringRef;

    pub fn CFStringCompare(
        theString1: CFStringRef,
        theString2: CFStringRef,
        compareOptions: CFStringCompareFlags,
    ) -> CFComparisonResult;
    pub fn CFArrayRemoveValueAtIndex(theArray: CFMutableArrayRef, idx: CFIndex);

}

pub fn system_version_major() -> SInt32 {
    unsafe {
        let ret: SInt32 = 0;
        let err = Gestalt(gestaltSystemVersionMajor, &ret);
        if err != 0 {
            panic!(
                "Gestalt call failed with error {} for gestaltSystemVersionMajor",
                err
            );
        }
        return ret;
    }
}

pub fn system_version_minor() -> SInt32 {
    unsafe {
        let ret: SInt32 = 0;
        let err = Gestalt(gestaltSystemVersionMinor, &ret);
        if err != 0 {
            panic!(
                "Gestalt call failed with error {} for gestaltSystemVersionMinor",
                err
            );
        }
        return ret;
    }
}

pub fn system_version_bugfix() -> SInt32 {
    unsafe {
        let ret: SInt32 = 0;
        let err = Gestalt(gestaltSystemVersionBugFix, &ret);
        if err != 0 {
            panic!(
                "Gestalt call failed with error {} for gestaltSystemVersionBugFix",
                err
            );
        }
        return ret;
    }
}

pub unsafe fn str_path_to_cfstring_ref(source: &str, err: &mut CFErrorRef) -> CFStringRef {
    let c_path = CString::new(source).unwrap();
    let c_len = libc::strlen(c_path.as_ptr());
    let mut url = CFURLCreateFromFileSystemRepresentation(
        kCFAllocatorDefault,
        c_path.as_ptr(),
        c_len as CFIndex,
        false,
    );
    let mut placeholder = CFURLCopyAbsoluteURL(url);
    CFRelease(url);

    let imaginary: CFRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);

    while !CFURLResourceIsReachable(placeholder, ptr::null_mut()) {
        let child = CFURLCopyLastPathComponent(placeholder);
        CFArrayInsertValueAtIndex(imaginary, 0, child);
        CFRelease(child);

        url = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, placeholder);
        CFRelease(placeholder);
        placeholder = url;
    }

    url = CFURLCreateFileReferenceURL(kCFAllocatorDefault, placeholder, err);
    if *err != ptr::null_mut() {
        return ptr::null_mut();
    }

    CFRelease(placeholder);
    placeholder = CFURLCreateFilePathURL(kCFAllocatorDefault, url, err);
    if *err != ptr::null_mut() {
        return ptr::null_mut();
    }

    CFRelease(url);

    if imaginary != kCFAllocatorDefault {
        let mut count = 0;
        while count < CFArrayGetCount(imaginary) {
            let component = CFArrayGetValueAtIndex(imaginary, count);
            url = CFURLCreateCopyAppendingPathComponent(
                kCFAllocatorDefault,
                placeholder,
                component,
                false,
            );
            CFRelease(placeholder);
            placeholder = url;
            count = count + 1;
        }
        CFRelease(imaginary);
    }

    let cf_path = CFURLCopyFileSystemPath(placeholder, kCFURLPOSIXPathStyle);
    CFRelease(placeholder);
    cf_path
}
<commit_msg>fsevent-sys: Remove useless uses of return.<commit_after>#![allow(non_upper_case_globals, non_camel_case_types)]

extern crate libc;

use std::ffi::CString;
use std::ptr;
use std::str;

pub type UInt32 = ::std::os::raw::c_uint;
pub type SInt16 = ::std::os::raw::c_short;
pub type SInt32 = ::std::os::raw::c_int;

pub type FourCharCode = UInt32;
pub type OSType = FourCharCode;
pub type OSErr = SInt16;

pub const gestaltSystemVersion: ::std::os::raw::c_uint = 1937339254;
pub const gestaltSystemVersionMajor: ::std::os::raw::c_uint = 1937339185;
pub const gestaltSystemVersionMinor: ::std::os::raw::c_uint = 1937339186;
pub const gestaltSystemVersionBugFix: ::std::os::raw::c_uint = 1937339187;

pub type CFRef = *mut ::std::os::raw::c_void;

pub type CFIndex = ::std::os::raw::c_long;
pub type CFTimeInterval = f64;

#[doc(hidden)]
pub enum CFError {}

pub type CFMutableArrayRef = CFRef;
pub type CFURLRef = CFRef;
pub type CFErrorRef = *mut CFError;
pub type CFStringRef = CFRef;
pub type CFRunLoopRef = CFRef;

pub const NULL: CFRef = 0 as CFRef;
pub const NULL_REF_PTR: *mut CFRef = 0 as *mut CFRef;

pub type CFURLPathStyle = ::std::os::raw::c_uint;

pub const kCFAllocatorDefault: CFRef = NULL;
pub const kCFURLPOSIXPathStyle: CFURLPathStyle = 0;
pub const kCFURLHFSPathStyle: CFURLPathStyle = 1;
pub const kCFURLWindowsPathStyle: CFURLPathStyle = 2;

pub const kCFStringEncodingUTF8: u32 = 0x08000100;
pub type CFStringEncoding = u32;

pub const kCFCompareEqualTo: i32 = 0;
pub type CFComparisonResult = i32;

// MacOS uses Case Insensitive path
pub const kCFCompareCaseInsensitive: u32 = 1;
pub type CFStringCompareFlags = u32;

// CFStringEncoding
pub type kCFStringEncoding = u32;
pub const UTF8: kCFStringEncoding = 0x08000100;

#[repr(C)]
pub struct CFArrayCallBacks {
    version: CFIndex,
    retain: CFRef,
    release: CFRef,
    cp: CFRef,
    equal: CFRef,
}
//impl Clone for CFArrayCallBacks { }

#[link(name = "CoreServices", kind = "framework")]
extern "C" {
    pub static kCFTypeArrayCallBacks: CFArrayCallBacks;
    pub static kCFRunLoopDefaultMode: CFStringRef;

    pub fn Gestalt(selector: OSType, response: *const SInt32) -> OSErr;
    pub fn CFRelease(res: CFRef);
    pub fn CFShow(res: CFRef);
    pub fn CFCopyDescription(cf: CFRef) -> CFStringRef;

    pub fn CFRunLoopRun();
    pub fn CFRunLoopStop(run_loop: CFRunLoopRef);
    pub fn CFRunLoopGetCurrent() -> CFRunLoopRef;

    pub fn CFArrayCreateMutable(
        allocator: CFRef,
        capacity: CFIndex,
        callbacks: *const CFArrayCallBacks,
    ) -> CFMutableArrayRef;
    pub fn CFArrayInsertValueAtIndex(arr: CFMutableArrayRef, position: CFIndex, element: CFRef);
    pub fn CFArrayAppendValue(aff: CFMutableArrayRef, element: CFRef);
    pub fn CFArrayGetCount(arr: CFMutableArrayRef) -> CFIndex;
    pub fn CFArrayGetValueAtIndex(arr: CFMutableArrayRef, index: CFIndex) -> CFRef;

    pub fn CFURLCreateFileReferenceURL(
        allocator: CFRef,
        url: CFURLRef,
        err: *mut CFErrorRef,
    ) -> CFURLRef;
    pub fn CFURLCreateFilePathURL(
        allocator: CFRef,
        url: CFURLRef,
        err: *mut CFErrorRef,
    ) -> CFURLRef;
    pub fn CFURLCreateFromFileSystemRepresentation(
        allocator: CFRef,
        path: *const ::std::os::raw::c_char,
        len: CFIndex,
        is_directory: bool,
    ) -> CFURLRef;
    pub fn CFURLCopyAbsoluteURL(res: CFURLRef) -> CFURLRef;
    pub fn CFURLCopyLastPathComponent(res: CFURLRef) -> CFStringRef;
    pub fn CFURLCreateCopyDeletingLastPathComponent(allocator: CFRef, url: CFURLRef) -> CFURLRef;
    pub fn CFURLCreateCopyAppendingPathComponent(
        allocation: CFRef,
        url: CFURLRef,
        path: CFStringRef,
        is_directory: bool,
    ) -> CFURLRef;
    pub fn CFURLCopyFileSystemPath(anUrl: CFURLRef, path_style: CFURLPathStyle) -> CFStringRef;

    pub fn CFURLResourceIsReachable(res: CFURLRef, err: *mut CFErrorRef) -> bool;

    pub fn CFShowStr(str: CFStringRef);
    pub fn CFStringGetCString(
        theString: CFStringRef,
        buffer: *mut ::std::os::raw::c_char,
        buffer_size: CFIndex,
        encoding: CFStringEncoding,
    ) -> bool;
    pub fn CFStringGetCStringPtr(
        theString: CFStringRef,
        encoding: CFStringEncoding,
    ) -> *const ::std::os::raw::c_char;
    pub fn CFStringCreateWithCString(
        alloc: CFRef,
        source: *const ::std::os::raw::c_char,
        encoding: kCFStringEncoding,
    ) -> CFStringRef;

    pub fn CFStringCompare(
        theString1: CFStringRef,
        theString2: CFStringRef,
        compareOptions: CFStringCompareFlags,
    ) -> CFComparisonResult;
    pub fn CFArrayRemoveValueAtIndex(theArray: CFMutableArrayRef, idx: CFIndex);

}

pub fn system_version_major() -> SInt32 {
    unsafe {
        let ret: SInt32 = 0;
        let err = Gestalt(gestaltSystemVersionMajor, &ret);
        if err != 0 {
            panic!(
                "Gestalt call failed with error {} for gestaltSystemVersionMajor",
                err
            );
        }
        ret
    }
}

pub fn system_version_minor() -> SInt32 {
    unsafe {
        let ret: SInt32 = 0;
        let err = Gestalt(gestaltSystemVersionMinor, &ret);
        if err != 0 {
            panic!(
                "Gestalt call failed with error {} for gestaltSystemVersionMinor",
                err
            );
        }
        ret
    }
}

pub fn system_version_bugfix() -> SInt32 {
    unsafe {
        let ret: SInt32 = 0;
        let err = Gestalt(gestaltSystemVersionBugFix, &ret);
        if err != 0 {
            panic!(
                "Gestalt call failed with error {} for gestaltSystemVersionBugFix",
                err
            );
        }
        ret
    }
}

pub unsafe fn str_path_to_cfstring_ref(source: &str, err: &mut CFErrorRef) -> CFStringRef {
    let c_path = CString::new(source).unwrap();
    let c_len = libc::strlen(c_path.as_ptr());
    let mut url = CFURLCreateFromFileSystemRepresentation(
        kCFAllocatorDefault,
        c_path.as_ptr(),
        c_len as CFIndex,
        false,
    );
    let mut placeholder = CFURLCopyAbsoluteURL(url);
    CFRelease(url);

    let imaginary: CFRef = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);

    while !CFURLResourceIsReachable(placeholder, ptr::null_mut()) {
        let child = CFURLCopyLastPathComponent(placeholder);
        CFArrayInsertValueAtIndex(imaginary, 0, child);
        CFRelease(child);

        url = CFURLCreateCopyDeletingLastPathComponent(kCFAllocatorDefault, placeholder);
        CFRelease(placeholder);
        placeholder = url;
    }

    url = CFURLCreateFileReferenceURL(kCFAllocatorDefault, placeholder, err);
    if *err != ptr::null_mut() {
        return ptr::null_mut();
    }

    CFRelease(placeholder);
    placeholder = CFURLCreateFilePathURL(kCFAllocatorDefault, url, err);
    if *err != ptr::null_mut() {
        return ptr::null_mut();
    }

    CFRelease(url);

    if imaginary != kCFAllocatorDefault {
        let mut count = 0;
        while count < CFArrayGetCount(imaginary) {
            let component = CFArrayGetValueAtIndex(imaginary, count);
            url = CFURLCreateCopyAppendingPathComponent(
                kCFAllocatorDefault,
                placeholder,
                component,
                false,
            );
            CFRelease(placeholder);
            placeholder = url;
            count = count + 1;
        }
        CFRelease(imaginary);
    }

    let cf_path = CFURLCopyFileSystemPath(placeholder, kCFURLPOSIXPathStyle);
    CFRelease(placeholder);
    cf_path
}
<|endoftext|>


<commit_before>mod advent_of_code;

use advent_of_code::get_line;
use advent_of_code::get_pieces;
use advent_of_code::parse_single_number;

use std::collections::HashSet;
use std::io;
use std::str::FromStr;

enum Direction {
    North,
    East,
    South,
    West,
}

fn turn_left(current_direction: Direction)
    -> Direction
{
    match current_direction {
        Direction::North => Direction::West,
        Direction::West => Direction::South,
        Direction::South => Direction::East,
        Direction::East => Direction::North,
    }
}

fn turn_right(current_direction: Direction)
    -> Direction
{
    match current_direction {
        Direction::West => Direction::North,
        Direction::South => Direction::West,
        Direction::East => Direction::South,
        Direction::North => Direction::East,
    }
}

#[derive(PartialEq, Eq, Hash)]
struct Location
{
    north: i32,
    east: i32,
}

pub fn main()
{
    let stdin = io::stdin();
    let pieces = get_pieces(get_line(stdin.lock()));

    let mut delta_east = 0;
    let mut delta_north = 0;

    let mut facing_direction = Direction::North;
    let mut locations = HashSet::new();

    let puzzle_a = false;

    for piece in pieces
    {
        if piece.starts_with('R')
        {
            facing_direction = turn_right(facing_direction);
        }
        else if piece.starts_with('L')
        {
            facing_direction = turn_left(facing_direction);
        }
        else
        {
            panic!("Unexpected input ({:?}) does not start with L or R.");
        }

        let rest = String::from_str(&piece[1..]).unwrap();
        let num = parse_single_number(rest);

        if puzzle_a
        {
            // part 1 simple handling:
            match facing_direction {
                Direction::North => delta_north += num,
                Direction::East => delta_east += num,
                Direction::South => delta_north -= num,
                Direction::West => delta_east -= num,
            }
        }
        else
        {
            // part 2 extension:
            for _ in 0..num
            {
                match facing_direction {
                    Direction::North => delta_north += 1,
                    Direction::East => delta_east += 1,
                    Direction::South => delta_north -= 1,
                    Direction::West => delta_east -= 1,
                }

                let location = Location { north: delta_north, east: delta_east };
                if locations.contains(&location)
                {
                    break;
                }
                else
                {
                    locations.insert(location);
                }
            }
        }
    }

    print_location(delta_north, delta_east);
}

fn print_location(north: i32, east: i32)
{
    let total = north.abs() + east.abs();
    println!("{:?} North, {:?} East: {:?} Total", north, east, total);
}
<commit_msg>Add debug prints<commit_after>mod advent_of_code;

use advent_of_code::get_line;
use advent_of_code::get_pieces;
use advent_of_code::parse_single_number;

use std::collections::HashSet;
use std::io;
use std::str::FromStr;

enum Direction {
    North,
    East,
    South,
    West,
}

fn turn_left(current_direction: Direction)
    -> Direction
{
    match current_direction {
        Direction::North => Direction::West,
        Direction::West => Direction::South,
        Direction::South => Direction::East,
        Direction::East => Direction::North,
    }
}

fn turn_right(current_direction: Direction)
    -> Direction
{
    match current_direction {
        Direction::West => Direction::North,
        Direction::South => Direction::West,
        Direction::East => Direction::South,
        Direction::North => Direction::East,
    }
}

#[derive(PartialEq, Eq, Hash)]
struct Location
{
    north: i32,
    east: i32,
}

pub fn main()
{
    let stdin = io::stdin();
    let pieces = get_pieces(get_line(stdin.lock()));

    let mut delta_east = 0;
    let mut delta_north = 0;

    let mut facing_direction = Direction::North;
    let mut locations = HashSet::new();

    let puzzle_a = false;

    for piece in pieces
    {
        if piece.starts_with('R')
        {
            facing_direction = turn_right(facing_direction);
        }
        else if piece.starts_with('L')
        {
            facing_direction = turn_left(facing_direction);
        }
        else
        {
            panic!("Unexpected input ({:?}) does not start with L or R.");
        }

        let rest = String::from_str(&piece[1..]).unwrap();
        let num = parse_single_number(rest);

        //println!("{:?} : {:?}", piece, num);
        if puzzle_a
        {
            // part 1 simple handling:
            match facing_direction {
                Direction::North => delta_north += num,
                Direction::East => delta_east += num,
                Direction::South => delta_north -= num,
                Direction::West => delta_east -= num,
            }
        }
        else
        {
            // part 2 extension:
            for _ in 0..num
            {
                match facing_direction {
                    Direction::North => delta_north += 1,
                    Direction::East => delta_east += 1,
                    Direction::South => delta_north -= 1,
                    Direction::West => delta_east -= 1,
                }

                let location = Location { north: delta_north, east: delta_east };
                if locations.contains(&location)
                {
                    break;
                }
                else
                {
                    locations.insert(location);
                }

                //print_location(delta_north, delta_east);
            }
        }
    }

    print_location(delta_north, delta_east);
}

fn print_location(north: i32, east: i32)
{
    let total = north.abs() + east.abs();
    println!("{:?} North, {:?} East: {:?} Total", north, east, total);
}
<|endoftext|>


<commit_before>//! Inference of closure parameter types based on the closure's expected type.

use chalk_ir::{AliasTy, FnSubst, WhereClause};
use hir_def::HasModule;
use smallvec::SmallVec;

use crate::{
    to_chalk_trait_id, utils, ChalkTraitId, DynTy, FnPointer, FnSig, Interner, Substitution, Ty,
    TyExt, TyKind,
};

use super::{Expectation, InferenceContext};

impl InferenceContext<'_> {
    pub(super) fn deduce_closure_type_from_expectations(
        &mut self,
        closure_ty: &Ty,
        sig_ty: &Ty,
        expectation: &Expectation,
    ) {
        let expected_ty = match expectation.to_option(&mut self.table) {
            Some(ty) => ty,
            None => return,
        };

        // Deduction from where-clauses in scope, as well as fn-pointer coercion are handled here.
        self.coerce(closure_ty, &expected_ty);

        // Deduction based on the expected `dyn Fn` is done separately.
        if let TyKind::Dyn(dyn_ty) = expected_ty.kind(&Interner) {
            if let Some(sig) = self.deduce_sig_from_dyn_ty(dyn_ty) {
                let expected_sig_ty = TyKind::Function(sig).intern(&Interner);

                self.unify(sig_ty, &expected_sig_ty);
            }
        }
    }

    fn deduce_sig_from_dyn_ty(&self, dyn_ty: &DynTy) -> Option<FnPointer> {
        // Search for a predicate like `<$self as FnX<Args>>::Output == Ret`

        let fn_traits: SmallVec<[ChalkTraitId; 3]> =
            utils::fn_traits(self.db.upcast(), self.owner.module(self.db.upcast()).krate())
                .map(|tid| to_chalk_trait_id(tid))
                .collect();

        for bound in dyn_ty.bounds.map_ref(|b| b.iter(&Interner)) {
            let bound = bound.map(|b| b.clone()).fuse_binders(&Interner);

            // NOTE(skip_binders): the extracted types are rebound by the returned `FnPointer`
            match bound.skip_binders() {
                WhereClause::AliasEq(eq) => match &eq.alias {
                    AliasTy::Projection(projection) => {
                        let assoc_data = self.db.associated_ty_data(projection.associated_ty_id);
                        if !fn_traits.contains(&assoc_data.trait_id) {
                            return None;
                        }

                        // Skip `Self`, get the type argument.
                        let arg = projection.substitution.as_slice(&Interner).get(1)?;
                        if let Some(subst) = arg.ty(&Interner)?.as_tuple() {
                            let generic_args = subst.as_slice(&Interner);
                            let mut sig_tys = Vec::new();
                            for arg in generic_args {
                                sig_tys.push(arg.ty(&Interner)?.clone());
                            }
                            sig_tys.push(eq.ty.clone());

                            cov_mark::hit!(dyn_fn_param_informs_call_site_closure_signature);
                            return Some(FnPointer {
                                num_binders: 0,
                                sig: FnSig {
                                    abi: (),
                                    safety: chalk_ir::Safety::Safe,
                                    variadic: false,
                                },
                                substitution: FnSubst(Substitution::from_iter(
                                    &Interner,
                                    sig_tys.clone(),
                                )),
                            });
                        }
                    }
                    AliasTy::Opaque(_) => {}
                },
                _ => {}
            }
        }

        None
    }
}
<commit_msg>Bind the right number of variables in the `FnPointer`<commit_after>//! Inference of closure parameter types based on the closure's expected type.

use chalk_ir::{AliasTy, FnSubst, WhereClause};
use hir_def::HasModule;
use smallvec::SmallVec;

use crate::{
    to_chalk_trait_id, utils, ChalkTraitId, DynTy, FnPointer, FnSig, Interner, Substitution, Ty,
    TyExt, TyKind,
};

use super::{Expectation, InferenceContext};

impl InferenceContext<'_> {
    pub(super) fn deduce_closure_type_from_expectations(
        &mut self,
        closure_ty: &Ty,
        sig_ty: &Ty,
        expectation: &Expectation,
    ) {
        let expected_ty = match expectation.to_option(&mut self.table) {
            Some(ty) => ty,
            None => return,
        };

        // Deduction from where-clauses in scope, as well as fn-pointer coercion are handled here.
        self.coerce(closure_ty, &expected_ty);

        // Deduction based on the expected `dyn Fn` is done separately.
        if let TyKind::Dyn(dyn_ty) = expected_ty.kind(&Interner) {
            if let Some(sig) = self.deduce_sig_from_dyn_ty(dyn_ty) {
                let expected_sig_ty = TyKind::Function(sig).intern(&Interner);

                self.unify(sig_ty, &expected_sig_ty);
            }
        }
    }

    fn deduce_sig_from_dyn_ty(&self, dyn_ty: &DynTy) -> Option<FnPointer> {
        // Search for a predicate like `<$self as FnX<Args>>::Output == Ret`

        let fn_traits: SmallVec<[ChalkTraitId; 3]> =
            utils::fn_traits(self.db.upcast(), self.owner.module(self.db.upcast()).krate())
                .map(|tid| to_chalk_trait_id(tid))
                .collect();

        for bound in dyn_ty.bounds.map_ref(|b| b.iter(&Interner)) {
            let bound = bound.map(|b| b.clone()).fuse_binders(&Interner);

            // NOTE(skip_binders): the extracted types are rebound by the returned `FnPointer`
            match bound.skip_binders() {
                WhereClause::AliasEq(eq) => match &eq.alias {
                    AliasTy::Projection(projection) => {
                        let assoc_data = self.db.associated_ty_data(projection.associated_ty_id);
                        if !fn_traits.contains(&assoc_data.trait_id) {
                            return None;
                        }

                        // Skip `Self`, get the type argument.
                        let arg = projection.substitution.as_slice(&Interner).get(1)?;
                        if let Some(subst) = arg.ty(&Interner)?.as_tuple() {
                            let generic_args = subst.as_slice(&Interner);
                            let mut sig_tys = Vec::new();
                            for arg in generic_args {
                                sig_tys.push(arg.ty(&Interner)?.clone());
                            }
                            sig_tys.push(eq.ty.clone());

                            cov_mark::hit!(dyn_fn_param_informs_call_site_closure_signature);
                            return Some(FnPointer {
                                num_binders: bound.len(&Interner),
                                sig: FnSig {
                                    abi: (),
                                    safety: chalk_ir::Safety::Safe,
                                    variadic: false,
                                },
                                substitution: FnSubst(Substitution::from_iter(
                                    &Interner,
                                    sig_tys.clone(),
                                )),
                            });
                        }
                    }
                    AliasTy::Opaque(_) => {}
                },
                _ => {}
            }
        }

        None
    }
}
<|endoftext|>


<commit_before>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

extern mod grust (name="grust", vers="0.1");
extern mod gio (name="grust-Gio", vers="2.0");

use std::result::{Result,Ok};
use std::comm::{Port,stream};
use std::task::TaskResult;
use std::util;
// use std::timer::recv_timeout;
// use std::uv_global_loop;
use grust::eventloop::EventLoop;

// Test timeout in milliseconds
static TEST_TIMEOUT: uint = 3000u;

fn spawn_with_future(func: ~fn()) -> Port<TaskResult> {
    let mut (port, _) = stream::<TaskResult>();
    let mut task = task::task();
    do task.future_result |p| { port = p; };
    task.spawn(func);
    port
}

fn tcase(test: ~fn()) {
    grust::init();

    let port = spawn_with_future(test);

    // recv_timeout is broken, see https://github.com/mozilla/rust/issues/6089
    match Some(port.recv()) /* recv_timeout(&uv_global_loop::get(), TEST_TIMEOUT, &port) */ {
        Some(task::Success) => {}
        Some(task::Failure) => {
            fail!(~"test failed");
        }
        None => {
            error!("test timed out");
            unsafe { libc::abort(); }
        }
    }
}

fn tcase_result(test: ~fn() -> Result<(),()>) {
    do tcase {
        let result = test();
        assert!(result == Ok(()));
    }
}

#[test]
fn simple() {
    do tcase {
        let fobj = gio::file_new_for_path("/dev/null");
        let f = fobj.interface() as &gio::File;
        assert!(f.get_path().to_str() == ~"/dev/null");
    }
}

#[test]
fn as_interface() {
    do tcase {
        do gio::file_new_for_path("/dev/null").as_interface |fobj| {
            let f = fobj as &gio::File;
            assert!(f.get_path().to_str() == ~"/dev/null");
        };
    }
}

#[test]
fn new_ref() {
    do tcase {
        let fobj = gio::file_new_for_path("/dev/null");
        let gobj = fobj.interface().new_ref();
        let g = gobj.interface() as &gio::File;
        assert!(g.get_path().to_str() == ~"/dev/null");
    }
}

#[test]
fn clone() {
    do tcase {
        let fobj = gio::file_new_for_path("/dev/null");
        do fobj.clone().as_interface |gobj| {
            let g = gobj as &gio::File;
            assert!(g.get_path().to_str() == ~"/dev/null");
        };
    }
}

#[test]
fn off_task() {
    do tcase_result {
        let f = ~gio::file_new_for_path("/dev/null");
        do task::try {
            let f = f.interface() as &gio::File;
            let p = f.get_path();
            assert!(p.to_str() == ~"/dev/null");
        }
    }
}

#[test]
fn off_task_as_interface() {
    do tcase_result {
        let fobj = ~gio::file_new_for_path("/dev/null");
        do task::try {
            do fobj.as_interface |fifa| {
                let f = fifa as &gio::File;
                let p = f.get_path();
                assert!(p.to_str() == ~"/dev/null");
            };
        }
    }
}

#[test]
fn async() {
    do tcase {
        let fobj = gio::file_new_for_path("/dev/null");
        let f = fobj.interface() as &gio::File;
        let el = EventLoop::new();
        let elo = ~el.clone();
        do f.read_async(0, None) |obj, res| {
            let f: &gio::File = obj.cast::<gio::raw::GFile>()
                                as &gio::File;
            let in = f.read_finish(res);
            util::ignore(in);
            elo.quit();
        };
        el.run();
    }
}

#[test]
#[ignore]  // See https://github.com/mzabaluev/grust/issues/4
fn async_off_task() {
    do tcase {
        let fobj = ~gio::file_new_for_path("/dev/null");
        let el = EventLoop::new();
        let elo = ~el.clone();
        do spawn {
            let f = fobj.interface() as &gio::File;
            let elo2 = ~elo.clone();
            do f.read_async(0, None) |obj, res| {
                let fifa: &gio::interfaces::File = obj.cast();
                let f = fifa as &gio::File;
                f.read_finish(res);
                elo2.quit();
            };
        }
        el.run();
    }
}

#[test]
fn async_off_stack() {
    do tcase {
        let fobj = ~gio::file_new_for_path("/dev/null");
        let el = EventLoop::new();
        let elo = ~el.clone();
        do task::spawn_sched(task::ThreadPerCore) {
            let f = fobj.interface() as &gio::File;
            let elo2 = ~elo.clone();
            do f.read_async(0, None) |obj, res| {
                let f = obj.cast::<gio::raw::GFile>() as &gio::File;
                f.read_finish(res);
                elo2.quit();
            };
        };
        el.run();
    }
}
<commit_msg>Use the SingleThreaded scheduler for the async_off_stack test<commit_after>/* This file is part of Grust, GObject introspection bindings for Rust
 *
 * Copyright (C) 2013  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

extern mod grust (name="grust", vers="0.1");
extern mod gio (name="grust-Gio", vers="2.0");

use std::result::{Result,Ok};
use std::comm::{Port,stream};
use std::task::TaskResult;
use std::util;
// use std::timer::recv_timeout;
// use std::uv_global_loop;
use grust::eventloop::EventLoop;

// Test timeout in milliseconds
static TEST_TIMEOUT: uint = 3000u;

fn spawn_with_future(func: ~fn()) -> Port<TaskResult> {
    let mut (port, _) = stream::<TaskResult>();
    let mut task = task::task();
    do task.future_result |p| { port = p; };
    task.spawn(func);
    port
}

fn tcase(test: ~fn()) {
    grust::init();

    let port = spawn_with_future(test);

    // recv_timeout is broken, see https://github.com/mozilla/rust/issues/6089
    match Some(port.recv()) /* recv_timeout(&uv_global_loop::get(), TEST_TIMEOUT, &port) */ {
        Some(task::Success) => {}
        Some(task::Failure) => {
            fail!(~"test failed");
        }
        None => {
            error!("test timed out");
            unsafe { libc::abort(); }
        }
    }
}

fn tcase_result(test: ~fn() -> Result<(),()>) {
    do tcase {
        let result = test();
        assert!(result == Ok(()));
    }
}

#[test]
fn simple() {
    do tcase {
        let fobj = gio::file_new_for_path("/dev/null");
        let f = fobj.interface() as &gio::File;
        assert!(f.get_path().to_str() == ~"/dev/null");
    }
}

#[test]
fn as_interface() {
    do tcase {
        do gio::file_new_for_path("/dev/null").as_interface |fobj| {
            let f = fobj as &gio::File;
            assert!(f.get_path().to_str() == ~"/dev/null");
        };
    }
}

#[test]
fn new_ref() {
    do tcase {
        let fobj = gio::file_new_for_path("/dev/null");
        let gobj = fobj.interface().new_ref();
        let g = gobj.interface() as &gio::File;
        assert!(g.get_path().to_str() == ~"/dev/null");
    }
}

#[test]
fn clone() {
    do tcase {
        let fobj = gio::file_new_for_path("/dev/null");
        do fobj.clone().as_interface |gobj| {
            let g = gobj as &gio::File;
            assert!(g.get_path().to_str() == ~"/dev/null");
        };
    }
}

#[test]
fn off_task() {
    do tcase_result {
        let f = ~gio::file_new_for_path("/dev/null");
        do task::try {
            let f = f.interface() as &gio::File;
            let p = f.get_path();
            assert!(p.to_str() == ~"/dev/null");
        }
    }
}

#[test]
fn off_task_as_interface() {
    do tcase_result {
        let fobj = ~gio::file_new_for_path("/dev/null");
        do task::try {
            do fobj.as_interface |fifa| {
                let f = fifa as &gio::File;
                let p = f.get_path();
                assert!(p.to_str() == ~"/dev/null");
            };
        }
    }
}

#[test]
fn async() {
    do tcase {
        let fobj = gio::file_new_for_path("/dev/null");
        let f = fobj.interface() as &gio::File;
        let el = EventLoop::new();
        let elo = ~el.clone();
        do f.read_async(0, None) |obj, res| {
            let f: &gio::File = obj.cast::<gio::raw::GFile>()
                                as &gio::File;
            let in = f.read_finish(res);
            util::ignore(in);
            elo.quit();
        };
        el.run();
    }
}

#[test]
#[ignore]  // See https://github.com/mzabaluev/grust/issues/4
fn async_off_task() {
    do tcase {
        let fobj = ~gio::file_new_for_path("/dev/null");
        let el = EventLoop::new();
        let elo = ~el.clone();
        do spawn {
            let f = fobj.interface() as &gio::File;
            let elo2 = ~elo.clone();
            do f.read_async(0, None) |obj, res| {
                let fifa: &gio::interfaces::File = obj.cast();
                let f = fifa as &gio::File;
                f.read_finish(res);
                elo2.quit();
            };
        }
        el.run();
    }
}

#[test]
fn async_off_stack() {
    do tcase {
        let fobj = ~gio::file_new_for_path("/dev/null");
        let el = EventLoop::new();
        let elo = ~el.clone();
        do task::spawn_sched(task::SingleThreaded) {
            let f = fobj.interface() as &gio::File;
            let elo2 = ~elo.clone();
            do f.read_async(0, None) |obj, res| {
                let f = obj.cast::<gio::raw::GFile>() as &gio::File;
                f.read_finish(res);
                elo2.quit();
            };
        };
        el.run();
    }
}
<|endoftext|>