<commit_before>use prelude::*;

cfg_if! {
    if #[cfg(feature = "std")] {
        use std::sync::atomic;
    } else if #[cfg(not(feature = "v1"))] {
        use core::sync::atomic;
    }
}

/// A thread-safe, stateful context for the v1 generator to help ensure
/// process-wide uniqueness.
pub struct UuidContext {
    count: atomic::AtomicUsize,
}

/// A trait that abstracts over generation of Uuid v1 "Clock Sequence" values.
pub trait UuidClockSequence {
    /// Return a 16-bit number that will be used as the "clock sequence" in
    /// the Uuid. The number must be different if the time has changed since
    /// the last time a clock sequence was requested.
    fn generate_sequence(&self, seconds: u64, nano_seconds: u32) -> u16;
}

impl Uuid {
    /// Create a new [`Uuid`] (version 1) using a time value + sequence +
    /// *NodeId*.
    ///
    /// This expects two values representing a monotonically increasing value
    /// as well as a unique 6 byte NodeId, and an implementation of
    /// [`UuidClockSequence`]. This function is only guaranteed to produce
    /// unique values if the following conditions hold:
    ///
    /// 1. The *NodeId* is unique for this process,
    /// 2. The *Context* is shared across all threads which are generating v1
    ///    [`Uuid`]s,
    /// 3. The [`UuidClockSequence`] implementation reliably returns unique
    ///    clock sequences (this crate provides [`UuidV1Context`] for this
    ///    purpose. However you can create your own [`UuidClockSequence`]
    ///    implementation, if [`UuidContext`] does not meet your needs).
    ///
    /// The NodeID must be exactly 6 bytes long. If the NodeID is not a valid
    /// length this will return a [`ParseError`]`::InvalidLength`.
    ///
    /// The function is not guaranteed to produce monotonically increasing
    /// values however.  There is a slight possibility that two successive
    /// equal time values could be supplied and the sequence counter wraps back
    /// over to 0.
    ///
    /// If uniqueness and monotonicity is required, the user is responsible for
    /// ensuring that the time value always increases between calls (including
    /// between restarts of the process and device).
    ///
    /// Note that usage of this method requires the `v1` feature of this crate
    /// to be enabled.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```rust
    /// use uuid::Uuid;
    /// use uuid::v1::UuidContext;
    ///
    /// let context = UuidContext::new(42);
    /// if let Ok(uuid) = Uuid::new_v1(&context, 1497624119, 1234, &[1,2,3,4,5,6]) {
    ///     assert_eq!(uuid.hyphenated().to_string(), "f3b4958c-52a1-11e7-802a-010203040506")
    /// } else {
    ///     panic!()
    /// }
    /// ```
    ///
    /// [`ParseError`]: ../enum.ParseError.html
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidClockSequence`]: struct.UuidClockSequence.html
    /// [`UuidContext`]: struct.UuidContext.html
    pub fn new_v1<T>(
        context: &T,
        seconds: u64,
        nano_seconds: u32,
        node_id: &[u8],
    ) -> Result<Self, ParseError>
    where
        T: UuidClockSequence,
    {
        if node_id.len() != 6 {
            return Err(ParseError::InvalidLength(node_id.len()));
        }

        let time_low;
        let time_mid;
        let time_high_and_version;

        {
            /// The number of 100 ns ticks between the UUID epoch
            /// `1582-10-15 00:00:00` and the Unix epoch `1970-01-01 00:00:00`.
            const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;

            let timestamp = seconds * 10_000_000 + u64::from(nano_seconds / 100);
            let uuid_time = timestamp + UUID_TICKS_BETWEEN_EPOCHS;

            time_low = (uuid_time & 0xFFFF_FFFF) as u32;
            time_mid = ((uuid_time >> 32) & 0xFFFF) as u16;
            time_high_and_version = (((uuid_time >> 48) & 0x0FFF) as u16) | (1 << 12);
        }

        let mut d4 = [0_u8; 8];

        {
            let count = context.generate_sequence(seconds, nano_seconds);
            d4[0] = (((count & 0x3F00) >> 8) as u8) | 0x80;
            d4[1] = (count & 0xFF) as u8;
        }

        d4[2..].copy_from_slice(node_id);

        Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
    }
}

impl UuidContext {
    /// Creates a thread-safe, internally mutable context to help ensure
    /// uniqueness.
    ///
    /// This is a context which can be shared across threads. It maintains an
    /// internal counter that is incremented at every request, the value ends
    /// up in the clock_seq portion of the [`Uuid`] (the fourth group). This
    /// will improve the probability that the [`Uuid`] is unique across the
    /// process.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn new(count: u16) -> Self {
        Self {
            count: atomic::AtomicUsize::new(count as usize),
        }
    }
}

impl UuidClockSequence for UuidContext {
    fn generate_sequence(&self, _: u64, _: u32) -> u16 {
        (self.count.fetch_add(1, atomic::Ordering::SeqCst) & 0xffff) as u16
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_new_v1() {
        use super::UuidContext;
        use UuidVersion;
        use prelude::*;

        let time: u64 = 1_496_854_535;
        let time_fraction: u32 = 812_946_000;
        let node = [1, 2, 3, 4, 5, 6];
        let context = UuidContext::new(0);

        {
            let uuid = Uuid::new_v1(&context, time, time_fraction, &node).unwrap();

            assert_eq!(uuid.get_version(), Some(UuidVersion::Mac));
            assert_eq!(uuid.get_variant(), Some(UuidVariant::RFC4122));
            assert_eq!(
                uuid.hyphenated().to_string(),
                "20616934-4ba2-11e7-8000-010203040506"
            );

            let ts = uuid.to_timestamp().unwrap();

            assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
            assert_eq!(ts.1, 0);
        };

        {
            let uuid2 = Uuid::new_v1(&context, time, time_fraction, &node).unwrap();

            assert_eq!(
                uuid2.hyphenated().to_string(),
                "20616934-4ba2-11e7-8001-010203040506"
            );
            assert_eq!(uuid2.to_timestamp().unwrap().1, 1)
        };
    }
}
<commit_msg>Add documentation for `v1` mod<commit_after>//! The implementation for Version 1 [`Uuid`]s.
//!
//! Note that you need feature `v1` in order to use these features.
//!
//! [`Uuid`]: ../struct.Uuid.html

use prelude::*;

cfg_if! {
    if #[cfg(feature = "std")] {
        use std::sync::atomic;
    } else if #[cfg(not(feature = "v1"))] {
        use core::sync::atomic;
    }
}

/// A thread-safe, stateful context for the v1 generator to help ensure
/// process-wide uniqueness.
pub struct UuidContext {
    count: atomic::AtomicUsize,
}

/// A trait that abstracts over generation of Uuid v1 "Clock Sequence" values.
pub trait UuidClockSequence {
    /// Return a 16-bit number that will be used as the "clock sequence" in
    /// the Uuid. The number must be different if the time has changed since
    /// the last time a clock sequence was requested.
    fn generate_sequence(&self, seconds: u64, nano_seconds: u32) -> u16;
}

impl Uuid {
    /// Create a new [`Uuid`] (version 1) using a time value + sequence +
    /// *NodeId*.
    ///
    /// This expects two values representing a monotonically increasing value
    /// as well as a unique 6 byte NodeId, and an implementation of
    /// [`UuidClockSequence`]. This function is only guaranteed to produce
    /// unique values if the following conditions hold:
    ///
    /// 1. The *NodeId* is unique for this process,
    /// 2. The *Context* is shared across all threads which are generating v1
    ///    [`Uuid`]s,
    /// 3. The [`UuidClockSequence`] implementation reliably returns unique
    ///    clock sequences (this crate provides [`UuidV1Context`] for this
    ///    purpose. However you can create your own [`UuidClockSequence`]
    ///    implementation, if [`UuidContext`] does not meet your needs).
    ///
    /// The NodeID must be exactly 6 bytes long. If the NodeID is not a valid
    /// length this will return a [`ParseError`]`::InvalidLength`.
    ///
    /// The function is not guaranteed to produce monotonically increasing
    /// values however.  There is a slight possibility that two successive
    /// equal time values could be supplied and the sequence counter wraps back
    /// over to 0.
    ///
    /// If uniqueness and monotonicity is required, the user is responsible for
    /// ensuring that the time value always increases between calls (including
    /// between restarts of the process and device).
    ///
    /// Note that usage of this method requires the `v1` feature of this crate
    /// to be enabled.
    ///
    /// # Examples
    ///
    /// Basic usage:
    ///
    /// ```rust
    /// use uuid::Uuid;
    /// use uuid::v1::UuidContext;
    ///
    /// let context = UuidContext::new(42);
    /// if let Ok(uuid) = Uuid::new_v1(&context, 1497624119, 1234, &[1,2,3,4,5,6]) {
    ///     assert_eq!(uuid.hyphenated().to_string(), "f3b4958c-52a1-11e7-802a-010203040506")
    /// } else {
    ///     panic!()
    /// }
    /// ```
    ///
    /// [`ParseError`]: ../enum.ParseError.html
    /// [`Uuid`]: ../struct.Uuid.html
    /// [`UuidClockSequence`]: struct.UuidClockSequence.html
    /// [`UuidContext`]: struct.UuidContext.html
    pub fn new_v1<T>(
        context: &T,
        seconds: u64,
        nano_seconds: u32,
        node_id: &[u8],
    ) -> Result<Self, ParseError>
    where
        T: UuidClockSequence,
    {
        if node_id.len() != 6 {
            return Err(ParseError::InvalidLength(node_id.len()));
        }

        let time_low;
        let time_mid;
        let time_high_and_version;

        {
            /// The number of 100 ns ticks between the UUID epoch
            /// `1582-10-15 00:00:00` and the Unix epoch `1970-01-01 00:00:00`.
            const UUID_TICKS_BETWEEN_EPOCHS: u64 = 0x01B2_1DD2_1381_4000;

            let timestamp = seconds * 10_000_000 + u64::from(nano_seconds / 100);
            let uuid_time = timestamp + UUID_TICKS_BETWEEN_EPOCHS;

            time_low = (uuid_time & 0xFFFF_FFFF) as u32;
            time_mid = ((uuid_time >> 32) & 0xFFFF) as u16;
            time_high_and_version = (((uuid_time >> 48) & 0x0FFF) as u16) | (1 << 12);
        }

        let mut d4 = [0_u8; 8];

        {
            let count = context.generate_sequence(seconds, nano_seconds);
            d4[0] = (((count & 0x3F00) >> 8) as u8) | 0x80;
            d4[1] = (count & 0xFF) as u8;
        }

        d4[2..].copy_from_slice(node_id);

        Uuid::from_fields(time_low, time_mid, time_high_and_version, &d4)
    }
}

impl UuidContext {
    /// Creates a thread-safe, internally mutable context to help ensure
    /// uniqueness.
    ///
    /// This is a context which can be shared across threads. It maintains an
    /// internal counter that is incremented at every request, the value ends
    /// up in the clock_seq portion of the [`Uuid`] (the fourth group). This
    /// will improve the probability that the [`Uuid`] is unique across the
    /// process.
    ///
    /// [`Uuid`]: ../struct.Uuid.html
    pub fn new(count: u16) -> Self {
        Self {
            count: atomic::AtomicUsize::new(count as usize),
        }
    }
}

impl UuidClockSequence for UuidContext {
    fn generate_sequence(&self, _: u64, _: u32) -> u16 {
        (self.count.fetch_add(1, atomic::Ordering::SeqCst) & 0xffff) as u16
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_new_v1() {
        use super::UuidContext;
        use UuidVersion;
        use prelude::*;

        let time: u64 = 1_496_854_535;
        let time_fraction: u32 = 812_946_000;
        let node = [1, 2, 3, 4, 5, 6];
        let context = UuidContext::new(0);

        {
            let uuid = Uuid::new_v1(&context, time, time_fraction, &node).unwrap();

            assert_eq!(uuid.get_version(), Some(UuidVersion::Mac));
            assert_eq!(uuid.get_variant(), Some(UuidVariant::RFC4122));
            assert_eq!(
                uuid.hyphenated().to_string(),
                "20616934-4ba2-11e7-8000-010203040506"
            );

            let ts = uuid.to_timestamp().unwrap();

            assert_eq!(ts.0 - 0x01B2_1DD2_1381_4000, 14_968_545_358_129_460);
            assert_eq!(ts.1, 0);
        };

        {
            let uuid2 = Uuid::new_v1(&context, time, time_fraction, &node).unwrap();

            assert_eq!(
                uuid2.hyphenated().to_string(),
                "20616934-4ba2-11e7-8001-010203040506"
            );
            assert_eq!(uuid2.to_timestamp().unwrap().1, 1)
        };
    }
}
<|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 rustc_serialize::json::Json;
use std::env;
use std::fs::{File, remove_file};
use std::path::Path;
use std::process::Command;

#[test]
fn properties_list_json() {
    let top = Path::new(file!()).parent().unwrap().join("..").join("..").join("..");
    let json = top.join("target").join("doc").join("servo").join("css-properties.json");
    if json.exists() {
        remove_file(&json).unwrap()
    }
    let python = env::var("PYTHON").ok().unwrap_or_else(find_python);
    let script = top.join("components").join("style").join("properties").join("build.py");
    let status = Command::new(python)
        .arg(&script)
        .arg("servo")
        .arg("html")
        .status()
        .unwrap();
    assert!(status.success());
    let properties = Json::from_reader(&mut File::open(json).unwrap()).unwrap();
    assert!(properties.as_object().unwrap().len() > 100);
    assert!(properties.find("margin").is_some());
    assert!(properties.find("margin-top").is_some());
}

#[cfg(windows)]
fn find_python() -> String {
    if Command::new("python27.exe").arg("--version").output().is_ok() {
        return "python27.exe".to_owned();
    }

    if Command::new("python.exe").arg("--version").output().is_ok() {
        return "python.exe".to_owned();
    }

    panic!("Can't find python (tried python27.exe and python.exe)! Try fixing PATH or setting the PYTHON env var");
}

#[cfg(not(windows))]
fn find_python() -> String {
    if Command::new("python2.7").arg("--version").output().unwrap().status.success() {
        "python2.7"
    } else {
        "python"
    }.to_owned()
}
<commit_msg>Added test for serialize method<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 rustc_serialize::json::Json;
use std::env;
use std::fs::{File, remove_file};
use std::path::Path;
use std::process::Command;
use std::sync::Arc;
use style::computed_values::display::T::inline_block;
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, DeclaredValue};
use style::values::specified::{Length, LengthOrPercentageOrAuto, LengthOrPercentage};

#[test]
fn properties_list_json() {
    let top = Path::new(file!()).parent().unwrap().join("..").join("..").join("..");
    let json = top.join("target").join("doc").join("servo").join("css-properties.json");
    if json.exists() {
        remove_file(&json).unwrap()
    }
    let python = env::var("PYTHON").ok().unwrap_or_else(find_python);
    let script = top.join("components").join("style").join("properties").join("build.py");
    let status = Command::new(python)
        .arg(&script)
        .arg("servo")
        .arg("html")
        .status()
        .unwrap();
    assert!(status.success());
    let properties = Json::from_reader(&mut File::open(json).unwrap()).unwrap();
    assert!(properties.as_object().unwrap().len() > 100);
    assert!(properties.find("margin").is_some());
    assert!(properties.find("margin-top").is_some());
}

#[cfg(windows)]
fn find_python() -> String {
    if Command::new("python27.exe").arg("--version").output().is_ok() {
        return "python27.exe".to_owned();
    }

    if Command::new("python.exe").arg("--version").output().is_ok() {
        return "python.exe".to_owned();
    }

    panic!("Can't find python (tried python27.exe and python.exe)! Try fixing PATH or setting the PYTHON env var");
}

#[cfg(not(windows))]
fn find_python() -> String {
    if Command::new("python2.7").arg("--version").output().unwrap().status.success() {
        "python2.7"
    } else {
        "python"
    }.to_owned()
}

#[test]
fn property_declaration_block_should_serialize_correctly() {
    let mut normal = Vec::new();
    let mut important = Vec::new();

    let length = LengthOrPercentageOrAuto::Length(Length::from_px(70f32));
    let value = DeclaredValue::Value(length);
    normal.push(PropertyDeclaration::Width(value));

    let min_height = LengthOrPercentage::Length(Length::from_px(20f32));
    let value = DeclaredValue::Value(min_height);
    normal.push(PropertyDeclaration::MinHeight(value));

    let value = DeclaredValue::Value(inline_block);
    normal.push(PropertyDeclaration::Display(value));

    let height = LengthOrPercentageOrAuto::Length(Length::from_px(20f32));
    let value = DeclaredValue::Value(height);
    important.push(PropertyDeclaration::Height(value));

    normal.reverse();
    important.reverse();
    let block = PropertyDeclarationBlock {
        normal: Arc::new(normal),
        important: Arc::new(important)
    };

    let css_string = block.serialize();

    assert_eq!(
        css_string,
        "width: 70px; min-height: 20px; display: inline-block; height: 20px ! important;"
    );
}
<|endoftext|>


<commit_before>
#[ allow( unused_imports ) ]
use wpublisher as TheModule;

mod inc;
<commit_msg>Fix tests of utility `wpublisher`, setup tests under features<commit_after>
#[ allow( unused_imports ) ]
use wpublisher as TheModule;

#[ cfg( feature = "use_std" ) ]
mod inc;
<|endoftext|>


<commit_before>extern crate codespan;
extern crate termcolor;

use std::fmt;
use termcolor::Color;

mod diagnostic;
mod emitter;

pub use self::diagnostic::{Diagnostic, Label, LabelStyle};
pub use self::emitter::emit;

/// A severity level for diagnostic messages
#[derive(Copy, PartialEq, Clone, Hash, Debug)]
pub enum Severity {
    /// An unexpected bug.
    Bug,
    /// An error.
    Error,
    /// A warning.
    Warning,
    /// A note.
    Note,
    /// A help message.
    Help,
}

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

impl Severity {
    /// Return the termcolor to use when rendering messages of this diagnostic severity
    pub fn color(self) -> Color {
        match self {
            Severity::Bug | Severity::Error => Color::Red,
            Severity::Warning => Color::Yellow,
            Severity::Note => Color::Green,
            Severity::Help => Color::Cyan,
        }
    }

    /// A string that explains this diagnostic severity
    pub fn to_str(self) -> &'static str {
        match self {
            Severity::Bug => "error: internal compiler error",
            Severity::Error => "error",
            Severity::Warning => "warning",
            Severity::Note => "note",
            Severity::Help => "help",
        }
    }
}
<commit_msg>Add a partial ordering on severity<commit_after>extern crate codespan;
extern crate termcolor;

use std::cmp::Ordering;
use std::fmt;
use termcolor::Color;

mod diagnostic;
mod emitter;

pub use self::diagnostic::{Diagnostic, Label, LabelStyle};
pub use self::emitter::emit;

/// A severity level for diagnostic messages
///
/// These are ordered in the following way:
///
/// ```rust
/// use codespan_reporting::Severity;
///
/// assert!(Severity::Bug > Severity::Error);
/// assert!(Severity::Error > Severity::Warning);
/// assert!(Severity::Warning > Severity::Note);
/// assert!(Severity::Note > Severity::Help);
/// ```
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
pub enum Severity {
    /// An unexpected bug.
    Bug,
    /// An error.
    Error,
    /// A warning.
    Warning,
    /// A note.
    Note,
    /// A help message.
    Help,
}

impl Severity {
    /// We want bugs to be the maximum severity, errors next, etc...
    fn to_cmp_int(self) -> u8 {
        match self {
            Severity::Bug => 5,
            Severity::Error => 4,
            Severity::Warning => 3,
            Severity::Note => 2,
            Severity::Help => 1,
        }
    }
}

impl PartialOrd for Severity {
    fn partial_cmp(&self, other: &Severity) -> Option<Ordering> {
        u8::partial_cmp(&self.to_cmp_int(), &other.to_cmp_int())
    }
}

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

impl Severity {
    /// Return the termcolor to use when rendering messages of this diagnostic severity
    pub fn color(self) -> Color {
        match self {
            Severity::Bug | Severity::Error => Color::Red,
            Severity::Warning => Color::Yellow,
            Severity::Note => Color::Green,
            Severity::Help => Color::Cyan,
        }
    }

    /// A string that explains this diagnostic severity
    pub fn to_str(self) -> &'static str {
        match self {
            Severity::Bug => "error: internal compiler error",
            Severity::Error => "error",
            Severity::Warning => "warning",
            Severity::Note => "note",
            Severity::Help => "help",
        }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "rust-hl-lua-modules"]
#![feature(plugin_registrar)]
#![feature(quote)]

extern crate rustc;
extern crate syntax;

use std::gc::{GC, Gc};
use syntax::parse::token;
use syntax::ast;
use syntax::attr::AttrMetaMethods;
use syntax::ext::build::AstBuilder;
use syntax::ext::base;
use syntax::ext::quote::rt::ToSource;
use syntax::codemap;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_syntax_extension(token::intern("export_lua_module"),
        base::ItemModifier(expand_lua_module));
}

// handler for export_lua_module
pub fn expand_lua_module(ecx: &mut base::ExtCtxt, span: codemap::Span,
                        _: Gc<ast::MetaItem>, input_item: Gc<ast::Item>)
    -> Gc<ast::Item>
{
    let ecx: &base::ExtCtxt = &*ecx;

    // checking that the input item is a module
    let module = match input_item.node {
        ast::ItemMod(ref module) => module,
        _ => {
            ecx.span_err(input_item.span,
                "`export_lua_module` extension is only allowed on modules");
            return input_item
        }
    };

    // creating the new item that will be returned by the function
    // it is just a clone of the input with more elements added to it
    let mut new_item = input_item.deref().clone();
    new_item.vis = ast::Public;
    if input_item.vis != ast::Public {
        ecx.span_warn(input_item.span,
            "`export_lua_module` will turn the module into a public module");
    }

    // creating an array of the statements to add to the main Lua entry point
    let module_handler_body: Vec<Gc<ast::Stmt>> = {
        let mut module_handler_body = Vec::new();

        // iterating over elements inside the module
        for moditem in module.items.iter() {
            let moditem_name = moditem.ident.to_source();

            match moditem.node {
                ast::ItemFn(..) | ast::ItemStatic(..) => {
                    let moditem_name_slice = moditem_name.as_slice();
                    let moditem_name_item = ecx.ident_of(moditem_name_slice);
                    module_handler_body.push(
                        quote_stmt!(&*ecx,
                            table.set($moditem_name_slice.to_string(), $moditem_name_item);
                        )
                    )
                },

                _ => {
                    ecx.span_warn(moditem.span,
                        format!("item `{}` is neiter a function nor a static
                            and will thus be ignored by `export_lua_module`",
                            moditem_name).as_slice());
                    continue
                }
            };

            // handling lua_module_init
            if moditem.attrs.iter().find(|at| at.check_name("lua_module_init")).is_some() {
                let moditem_name_item = ecx.ident_of(moditem.ident.to_source().as_slice());
                module_handler_body.push(
                    quote_stmt!(ecx, $moditem_name_item())
                );
            }
        }

        module_handler_body
    };

    // adding extern crate declarations
    {
        let view_items = quote_item!(ecx,
            mod x {
                extern crate lua = "rust-hl-lua";
                extern crate libc;
            }
        );

        let view_items = match view_items {
            Some(a) => a,
            None => {
                ecx.span_err(input_item.span,
                    "internal error in the library (could not parse view items)");
                return input_item;
            }
        };

        // getting all the items
        let view_items = match view_items.node {
            ast::ItemMod(ref m) => m,
            _ => { ecx.span_err(span, "internal error in the library"); return input_item; }
        };

        let ref mut mut_new_item = match &mut new_item.node {
            &ast::ItemMod(ref mut m) => m,
            _ => { ecx.span_err(span, "internal error in the library"); return input_item; }
        };

        for i in view_items.view_items.iter() {
            mut_new_item.view_items.insert(0, i.clone())
        }
    }

    // generating the function that we will add inside the module
    {
        let function_body = {
            let mut function_body = Vec::new();

            function_body.push(quote_stmt!(ecx,
                let mut lua = self::lua::Lua::from_existing_state(lua, false);
            ));

            function_body.push(quote_stmt!(ecx,
                let mut table = lua.load_new_table();
            ));

            function_body.push_all_move(module_handler_body);

            function_body.push(quote_stmt!(ecx,
                ::std::mem::forget(table);
            ));

            ecx.block(span.clone(), function_body, Some(
                quote_expr!(ecx, 1)
            ))
        };

        // identifier for "luaopen_mylib"
        let luaopen_id = ecx.ident_of(format!("luaopen_{}", input_item.ident.to_source())
            .as_slice());

        // building the function itself
        let function = quote_item!(ecx,
            #[no_mangle]
            pub extern "C" fn $luaopen_id(lua: *mut self::libc::c_void)
                                                    -> self::libc::c_int {
                unsafe {
                    $function_body
               }
            }
        );

        let function = match function {
            Some(f) => f,
            None => {
                ecx.span_err(input_item.span,
                    "internal error in the library (could not parse function body)");
                return input_item;
            }
        };

        // adding the function to the module
        match &mut new_item.node {
            &ast::ItemMod(ref mut m) => {
                m.items.push(function)
            },
            _ => { ecx.span_err(span, "internal error in the library"); return input_item; }
        };
    }

    // returning
    box(GC) new_item
}
<commit_msg>Native runtime now loaded by rust-hl-lua-modules See #15<commit_after>#![crate_name = "rust-hl-lua-modules"]
#![feature(plugin_registrar)]
#![feature(quote)]

extern crate rustc;
extern crate syntax;

use std::gc::{GC, Gc};
use syntax::ast;
use syntax::ast::Item;
use syntax::attr::AttrMetaMethods;
use syntax::codemap;
use syntax::ext::build::AstBuilder;
use syntax::ext::base;
use syntax::ext::quote::rt::ToSource;
use syntax::parse::token;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut ::rustc::plugin::Registry) {
    reg.register_syntax_extension(token::intern("export_lua_module"),
        base::ItemModifier(expand_lua_module));
}

// handler for export_lua_module
pub fn expand_lua_module(ecx: &mut base::ExtCtxt, span: codemap::Span,
                        _: Gc<ast::MetaItem>, input_item: Gc<ast::Item>)
    -> Gc<ast::Item>
{
    let ecx: &base::ExtCtxt = &*ecx;

    // checking that the input item is a module
    // and creating the new item that will be returned by the function
    let (module, mut new_item) = match input_item.node {
        ast::ItemMod(ref module) => {
            (module, module.clone())
        },
        _ => {
            ecx.span_err(input_item.span,
                "`export_lua_module` extension is only allowed on modules");
            return input_item
        }
    };

    // cleaning the content of `new_item`
    new_item.items.clear();

    // creating an array of the statements to add to the main Lua entry point
    let module_handler_body: Vec<Gc<ast::Stmt>> = {
        let mut module_handler_body = Vec::new();

        // iterating over elements inside the module
        for moditem in module.items.iter() {
            let moditem_name = moditem.ident.to_source();

            match moditem.node {
                ast::ItemFn(ref decl, ref style, ref abi, ref generics, ref block) => {
                    let moditem_name_slice = moditem_name.as_slice();
                    let moditem_name_item = ecx.ident_of(moditem_name_slice);

                    module_handler_body.push(
                        quote_stmt!(&*ecx,
                            table.set($moditem_name_slice.to_string(), $moditem_name_item);
                        )
                    );

                    new_item.items.push(box (GC) Item {
                        ident: moditem.ident.clone(),
                        attrs: moditem.attrs.clone(),
                        id: moditem.id.clone(),
                        node: ast::ItemFn(
                            decl.clone(),
                            style.clone(),
                            abi.clone(),
                            generics.clone(),
                            ecx.block_expr(
                                quote_expr!(&*ecx,
                                    {
                                        let (tx, rx) = channel();
                                        native::start(0, core::ptr::null(), proc() {
                                            tx.send({
                                                $block
                                            })
                                        });
                                        rx.recv()
                                    }
                                )
                            )
                        ),
                        vis: moditem.vis.clone(),
                        span: moditem.span.clone(),
                    });
                },

                ast::ItemStatic(..) => {
                    let moditem_name_slice = moditem_name.as_slice();
                    let moditem_name_item = ecx.ident_of(moditem_name_slice);

                    module_handler_body.push(
                        quote_stmt!(&*ecx,
                            table.set($moditem_name_slice.to_string(), $moditem_name_item);
                        )
                    );

                    new_item.items.push(moditem.clone());
                },

                _ => {
                    ecx.span_warn(moditem.span,
                        format!("item `{}` is neiter a function nor a static
                            and will thus be ignored by `export_lua_module`",
                            moditem_name).as_slice());
                    new_item.items.push(moditem.clone());
                    continue;
                }
            };

            // handling lua_module_init
            if moditem.attrs.iter().find(|at| at.check_name("lua_module_init")).is_some() {
                let moditem_name_item = ecx.ident_of(moditem.ident.to_source().as_slice());
                module_handler_body.push(
                    quote_stmt!(ecx, $moditem_name_item())
                );
            }
        }

        module_handler_body
    };

    // adding extern crate declarations
    {
        let view_items = quote_item!(ecx,
            mod x {
                extern crate core;
                extern crate lua = "rust-hl-lua";
                extern crate libc;
                extern crate native;
            }
        );

        let view_items = match view_items {
            Some(a) => a,
            None => {
                ecx.span_err(input_item.span,
                    "internal error in the library (could not parse view items)");
                return input_item;
            }
        };

        // getting all the items
        let view_items = match view_items.node {
            ast::ItemMod(ref m) => m,
            _ => { ecx.span_err(span, "internal error in the library"); return input_item; }
        };

        for i in view_items.view_items.iter() {
            new_item.view_items.insert(0, i.clone())
        }
    }

    // generating the function that we will add inside the module
    {
        let function_body = {
            let mut function_body = Vec::new();

            function_body.push(quote_stmt!(ecx,
                let mut lua = self::lua::Lua::from_existing_state(lua, false);
            ));

            function_body.push(quote_stmt!(ecx,
                let mut table = lua.load_new_table();
            ));

            function_body.push_all_move(module_handler_body);

            function_body.push(quote_stmt!(ecx,
                ::std::mem::forget(table);
            ));

            ecx.block(span.clone(), function_body, Some(
                quote_expr!(ecx, 1)
            ))
        };

        // identifier for "luaopen_mylib"
        let luaopen_id = ecx.ident_of(format!("luaopen_{}", input_item.ident.to_source())
            .as_slice());

        // building the function itself
        let function = quote_item!(ecx,
            #[no_mangle]
            pub extern "C" fn $luaopen_id(lua: *mut self::libc::c_void)
                                                    -> self::libc::c_int {
                unsafe {
                    $function_body
               }
            }
        );

        let function = match function {
            Some(f) => f,
            None => {
                ecx.span_err(input_item.span,
                    "internal error in the library (could not parse function body)");
                return input_item;
            }
        };

        // adding the function to the module
        new_item.items.push(function);
    }

    // returning
    box(GC) Item {
        ident: input_item.ident.clone(),
        attrs: input_item.attrs.clone(),
        id: input_item.id.clone(),
        node: ast::ItemMod(new_item),
        vis: {
            if input_item.vis != ast::Public {
                ecx.span_warn(input_item.span,
                    "`export_lua_module` will turn the module into a public module");
            }
            ast::Public
        },
        span: input_item.span.clone(),
    }
}
<|endoftext|>


<commit_before>export build_request;

import std::net::url;
import std::net::url::Url;

fn build_request(url: Url) -> ~str {

    let host = copy url.host;
    let path = if url.path.is_not_empty() { copy url.path } else { ~"/" };

    let request_header = #fmt("GET %s HTTP/1.0\u000D\u000AHost: %s\u000D\u000A\u000D\u000A",
                              path, host);

    return request_header;
}

#[test]
#[allow(non_implicitly_copyable_typarams)]
fn should_request_slash_when_path_is_empty() {
    let url = url::from_str(~"http://host").get();
    assert url.path.is_empty();
    let headers = build_request(url);
    assert headers.contains(~"GET / ");
}
<commit_msg>Add query parameter support<commit_after>export build_request;

import std::net::url;
import std::net::url::Url;

fn build_request(url: Url) -> ~str {

    let host = copy url.host;
    let mut path = if url.path.is_not_empty() { copy url.path } else { ~"/" };

    if url.query.len() > 0 {
        let kvps = do url.query.map |pair| {
            match pair {
                (key, value) => fmt!("%s=%s", key, value)
            }
        };
        path += ~"?" + str::connect(kvps, "&");
    }

    let request_header = #fmt("GET %s HTTP/1.0\u000D\u000AHost: %s\u000D\u000A\u000D\u000A",
                              path, host);

    return request_header;
}

#[test]
#[allow(non_implicitly_copyable_typarams)]
fn should_request_slash_when_path_is_empty() {
    let url = url::from_str(~"http://host").get();
    assert url.path.is_empty();
    let headers = build_request(url);
    assert headers.contains(~"GET / ");
}
<|endoftext|>


<commit_before>use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::collections::HashSet;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use common::Point;
use common::Solution;

type Coordinate = (usize, usize);

#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Copy, Clone, Debug)]
struct State {
    pos: Coordinate,
    climbing: bool,
    torch: bool,
}

impl State {
    pub fn is_valid(&self, terrain: usize) -> bool {
        match terrain {
            0 => self.torch || self.climbing,
            1 => !self.torch,
            2 => !self.climbing,
            _ => panic!(),
        }
    }
}

const MOD_BASE: usize = 20183;

#[derive(Default)]
pub struct Day22 {}

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

fn compute_table((x, y): Coordinate, depth: usize) -> Vec<Vec<usize>> {
    let mut table = vec![vec![0usize; x + 1]; y + 1];
    table[0][0] = 0;
    for (x, entry) in table[0].iter_mut().enumerate().skip(1) {
        *entry = (16807 * x + depth) % MOD_BASE;
    }

    for (y, entry) in table.iter_mut().enumerate().skip(1) {
        entry[0] = (48271 * y + depth) % MOD_BASE;
    }

    for y in 1..=y {
        for x in 1..=x {
            table[y][x] = (table[y - 1][x] * table[y][x - 1] + depth) % MOD_BASE;
        }
    }

    for c in table.iter_mut().flat_map(|x| x.iter_mut()) {
        *c %= 3;
    }

    table
}

fn read_input(input: &mut dyn Read) -> (usize, Coordinate) {
    let mut buf = String::new();
    let mut reader = BufReader::new(input);
    reader.read_line(&mut buf).unwrap();

    let depth: usize;
    {
        let mut parts = buf.trim().split(' ');
        depth = parts.nth(1).unwrap().parse().unwrap();
    }
    buf.clear();
    reader.read_line(&mut buf).unwrap();

    let target: Coordinate;
    {
        let mut parts = buf.trim().split(|c| c == ',' || c == ' ');
        let x: usize = parts.nth(1).unwrap().parse().unwrap();
        let y: usize = parts.next().unwrap().parse().unwrap();
        target = (x, y);
    }

    (depth, target)
}

impl Solution for Day22 {
    fn part1(&mut self, input: &mut dyn Read) -> String {
        let (depth, target) = read_input(input);
        let mut table = compute_table(target, depth);
        table[target.1][target.0] = 0;

        let result: usize = table.iter().flat_map(|x| x.iter()).sum();
        result.to_string()
    }

    fn part2(&mut self, input: &mut dyn Read) -> String {
        let (depth, target) = read_input(input);
        let mut table = compute_table((target.0 + 200, target.1 + 200), depth);
        table[target.1][target.0] = 0;

        let mut todo = BinaryHeap::new();
        let mut visited: HashSet<State> = HashSet::new();
        let target_state = State {
            pos: target,
            climbing: false,
            torch: true,
        };

        todo.push((
            Reverse((0, 0).manhattan(target)),
            Reverse(0),
            State {
                pos: (0, 0),
                climbing: false,
                torch: true,
            },
        ));

        while let Some((Reverse(approx), Reverse(dist), state)) = todo.pop() {
            if visited.contains(&state) {
                continue;
            }
            visited.insert(state);
            if state == target_state {
                return dist.to_string();
            }

            let (x, y) = state.pos;

            // Handle equipment changes
            let changes = [
                State {
                    pos: state.pos,
                    climbing: state.climbing,
                    torch: !state.torch,
                },
                State {
                    pos: state.pos,
                    climbing: !state.climbing,
                    torch: state.torch,
                },
                State {
                    pos: state.pos,
                    climbing: !state.climbing,
                    torch: !state.torch,
                },
            ];

            for state in changes.iter().cloned() {
                if visited.contains(&state) || !state.is_valid(table[y][x]) {
                    continue;
                }

                todo.push((Reverse(approx + 7), Reverse(dist + 7), state));
            }

            let xmin = if x == 0 { 0 } else { x - 1 };
            let ymin = if y == 0 { 0 } else { y - 1 };

            for xn in xmin..=(x + 1) {
                for yn in ymin..=(y + 1) {
                    let new_state = State {
                        pos: (xn, yn),
                        torch: state.torch,
                        climbing: state.climbing,
                    };

                    if !visited.contains(&new_state)
                        && new_state.is_valid(table[yn][xn])
                        && (x == xn || y == yn)
                    {
                        todo.push((
                            Reverse(dist + 1 + target.manhattan(new_state.pos)),
                            Reverse(dist + 1),
                            new_state,
                        ));
                    }
                }
            }
        }
        unreachable!();
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;

    use super::*;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/22.txt");

    #[test]
    fn sample_part1() {
        let mut instance = Day22::new();
        assert_eq!("114", instance.part1(&mut SAMPLE_INPUT));
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day22::new();
        assert_eq!("45", instance.part2(&mut SAMPLE_INPUT));
    }
}
<commit_msg>Switch loop order for locality.<commit_after>use std::cmp::Reverse;
use std::collections::BinaryHeap;
use std::collections::HashSet;
use std::io::BufRead;
use std::io::BufReader;
use std::io::Read;

use common::Point;
use common::Solution;

type Coordinate = (usize, usize);

#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Copy, Clone, Debug)]
struct State {
    pos: Coordinate,
    climbing: bool,
    torch: bool,
}

impl State {
    pub fn is_valid(&self, terrain: usize) -> bool {
        match terrain {
            0 => self.torch || self.climbing,
            1 => !self.torch,
            2 => !self.climbing,
            _ => panic!(),
        }
    }
}

const MOD_BASE: usize = 20183;

#[derive(Default)]
pub struct Day22 {}

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

fn compute_table((x, y): Coordinate, depth: usize) -> Vec<Vec<usize>> {
    let mut table = vec![vec![0usize; x + 1]; y + 1];
    table[0][0] = 0;
    for (x, entry) in table[0].iter_mut().enumerate().skip(1) {
        *entry = (16807 * x + depth) % MOD_BASE;
    }

    for (y, entry) in table.iter_mut().enumerate().skip(1) {
        entry[0] = (48271 * y + depth) % MOD_BASE;
    }

    for y in 1..=y {
        for x in 1..=x {
            table[y][x] = (table[y - 1][x] * table[y][x - 1] + depth) % MOD_BASE;
        }
    }

    for c in table.iter_mut().flat_map(|x| x.iter_mut()) {
        *c %= 3;
    }

    table
}

fn read_input(input: &mut dyn Read) -> (usize, Coordinate) {
    let mut buf = String::new();
    let mut reader = BufReader::new(input);
    reader.read_line(&mut buf).unwrap();

    let depth: usize;
    {
        let mut parts = buf.trim().split(' ');
        depth = parts.nth(1).unwrap().parse().unwrap();
    }
    buf.clear();
    reader.read_line(&mut buf).unwrap();

    let target: Coordinate;
    {
        let mut parts = buf.trim().split(|c| c == ',' || c == ' ');
        let x: usize = parts.nth(1).unwrap().parse().unwrap();
        let y: usize = parts.next().unwrap().parse().unwrap();
        target = (x, y);
    }

    (depth, target)
}

impl Solution for Day22 {
    fn part1(&mut self, input: &mut dyn Read) -> String {
        let (depth, target) = read_input(input);
        let mut table = compute_table(target, depth);
        table[target.1][target.0] = 0;

        let result: usize = table.iter().flat_map(|x| x.iter()).sum();
        result.to_string()
    }

    fn part2(&mut self, input: &mut dyn Read) -> String {
        let (depth, target) = read_input(input);
        let mut table = compute_table((target.0 + 200, target.1 + 200), depth);
        table[target.1][target.0] = 0;

        let mut todo = BinaryHeap::new();
        let mut visited: HashSet<State> = HashSet::new();
        let target_state = State {
            pos: target,
            climbing: false,
            torch: true,
        };

        todo.push((
            Reverse((0, 0).manhattan(target)),
            Reverse(0),
            State {
                pos: (0, 0),
                climbing: false,
                torch: true,
            },
        ));

        while let Some((Reverse(approx), Reverse(dist), state)) = todo.pop() {
            if visited.contains(&state) {
                continue;
            }
            visited.insert(state);
            if state == target_state {
                return dist.to_string();
            }

            let (x, y) = state.pos;

            // Handle equipment changes
            let changes = [
                State {
                    pos: state.pos,
                    climbing: state.climbing,
                    torch: !state.torch,
                },
                State {
                    pos: state.pos,
                    climbing: !state.climbing,
                    torch: state.torch,
                },
                State {
                    pos: state.pos,
                    climbing: !state.climbing,
                    torch: !state.torch,
                },
            ];

            for state in changes.iter().cloned() {
                if visited.contains(&state) || !state.is_valid(table[y][x]) {
                    continue;
                }

                todo.push((Reverse(approx + 7), Reverse(dist + 7), state));
            }

            let xmin = if x == 0 { 0 } else { x - 1 };
            let ymin = if y == 0 { 0 } else { y - 1 };

            for yn in ymin..=(y + 1) {
                for xn in xmin..=(x + 1) {
                    let new_state = State {
                        pos: (xn, yn),
                        torch: state.torch,
                        climbing: state.climbing,
                    };

                    if !visited.contains(&new_state)
                        && new_state.is_valid(table[yn][xn])
                        && (x == xn || y == yn)
                    {
                        todo.push((
                            Reverse(dist + 1 + target.manhattan(new_state.pos)),
                            Reverse(dist + 1),
                            new_state,
                        ));
                    }
                }
            }
        }
        unreachable!();
    }
}

#[cfg(test)]
mod tests {
    use common::Solution;

    use super::*;

    const SAMPLE_INPUT: &[u8] = include_bytes!("samples/22.txt");

    #[test]
    fn sample_part1() {
        let mut instance = Day22::new();
        assert_eq!("114", instance.part1(&mut SAMPLE_INPUT));
    }

    #[test]
    fn sample_part2() {
        let mut instance = Day22::new();
        assert_eq!("45", instance.part2(&mut SAMPLE_INPUT));
    }
}
<|endoftext|>


<commit_before>use crate::time::driver::{Handle, TimerEntry};
use crate::time::{error::Error, Duration, Instant};

use pin_project_lite::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};

/// Waits until `deadline` is reached.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
// Alias for old name in 0.x
#[cfg_attr(docsrs, doc(alias = "delay_until"))]
pub fn sleep_until(deadline: Instant) -> Sleep {
    Sleep::new_timeout(deadline)
}

/// Waits until `duration` has elapsed.
///
/// Equivalent to `sleep_until(Instant::now() + duration)`. An asynchronous
/// analog to `std::thread::sleep`.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// To run something regularly on a schedule, see [`interval`].
///
/// The maximum duration for a sleep is 68719476734 milliseconds (approximately 2.2 years).
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
///
/// # Examples
///
/// Wait 100ms and print "100 ms have elapsed".
///
/// ```
/// use tokio::time::{sleep, Duration};
///
/// #[tokio::main]
/// async fn main() {
///     sleep(Duration::from_millis(100)).await;
///     println!("100 ms have elapsed");
/// }
/// ```
///
/// [`interval`]: crate::time::interval()
// Alias for old name in 0.x
#[cfg_attr(docsrs, doc(alias = "delay_for"))]
pub fn sleep(duration: Duration) -> Sleep {
    match Instant::now().checked_add(duration) {
        Some(deadline) => sleep_until(deadline),
        None => sleep_until(Instant::far_future()),
    }
}

pin_project! {
    /// Future returned by [`sleep`](sleep) and [`sleep_until`](sleep_until).
    ///
    /// This type does not implement the `Unpin` trait, which means that if you
    /// use it with [`select!`] or by calling `poll`, you have to pin it first.
    /// If you use it with `.await`, this does not apply.
    ///
    /// # Examples
    ///
    /// Wait 100ms and print "100 ms have elapsed".
    ///
    /// ```
    /// use tokio::time::{sleep, Duration};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     sleep(Duration::from_millis(100)).await;
    ///     println!("100 ms have elapsed");
    /// }
    /// ```
    ///
    /// Use with [`select!`]. Pinning the `Sleep` with [`tokio::pin!`] is
    /// necessary when the same `Sleep` is selected on multiple times.
    /// ```no_run
    /// use tokio::time::{self, Duration, Instant};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let sleep = time::sleep(Duration::from_millis(10));
    ///     tokio::pin!(sleep);
    ///
    ///     loop {
    ///         tokio::select! {
    ///             () = &mut sleep => {
    ///                 println!("timer elapsed");
    ///                 sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
    ///             },
    ///         }
    ///     }
    /// }
    /// ```
    /// Use in a struct with boxing. By pinning the `Sleep` with a `Box`, the
    /// `HasSleep` struct implements `Unpin`, even though `Sleep` does not.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    ///
    /// struct HasSleep {
    ///     sleep: Pin<Box<Sleep>>,
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.sleep.as_mut().poll(cx)
    ///     }
    /// }
    /// ```
    /// Use in a struct with pin projection. This method avoids the `Box`, but
    /// the `HasSleep` struct will not be `Unpin` as a consequence.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    /// use pin_project_lite::pin_project;
    ///
    /// pin_project! {
    ///     struct HasSleep {
    ///         #[pin]
    ///         sleep: Sleep,
    ///     }
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.project().sleep.poll(cx)
    ///     }
    /// }
    /// ```
    ///
    /// [`select!`]: ../macro.select.html
    /// [`tokio::pin!`]: ../macro.pin.html
    // Alias for old name in 0.2
    #[cfg_attr(docsrs, doc(alias = "Delay"))]
    #[derive(Debug)]
    #[must_use = "futures do nothing unless you `.await` or poll them"]
    pub struct Sleep {
        deadline: Instant,

        // The link between the `Sleep` instance and the timer that drives it.
        #[pin]
        entry: TimerEntry,
    }
}

impl Sleep {
    pub(crate) fn new_timeout(deadline: Instant) -> Sleep {
        let handle = Handle::current();
        let entry = TimerEntry::new(&handle, deadline);

        Sleep { deadline, entry }
    }

    pub(crate) fn far_future() -> Sleep {
        Self::new_timeout(Instant::far_future())
    }

    /// Returns the instant at which the future will complete.
    pub fn deadline(&self) -> Instant {
        self.deadline
    }

    /// Returns `true` if `Sleep` has elapsed.
    ///
    /// A `Sleep` instance is elapsed when the requested duration has elapsed.
    pub fn is_elapsed(&self) -> bool {
        self.entry.is_elapsed()
    }

    /// Resets the `Sleep` instance to a new deadline.
    ///
    /// Calling this function allows changing the instant at which the `Sleep`
    /// future completes without having to create new associated state.
    ///
    /// This function can be called both before and after the future has
    /// completed.
    ///
    /// To call this method, you will usually combine the call with
    /// [`Pin::as_mut`], which lets you call the method without consuming the
    /// `Sleep` itself.
    ///
    /// # Example
    ///
    /// ```
    /// use tokio::time::{Duration, Instant};
    ///
    /// # #[tokio::main(flavor = "current_thread")]
    /// # async fn main() {
    /// let sleep = tokio::time::sleep(Duration::from_millis(10));
    /// tokio::pin!(sleep);
    ///
    /// sleep.as_mut().reset(Instant::now() + Duration::from_millis(20));
    /// # }
    /// ```
    ///
    /// [`Pin::as_mut`]: fn@std::pin::Pin::as_mut
    pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
        let me = self.project();
        me.entry.reset(deadline);
        *me.deadline = deadline;
    }

    fn poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
        let me = self.project();

        // Keep track of task budget
        let coop = ready!(crate::coop::poll_proceed(cx));

        me.entry.poll_elapsed(cx).map(move |r| {
            coop.made_progress();
            r
        })
    }
}

impl Future for Sleep {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // `poll_elapsed` can return an error in two cases:
        //
        // - AtCapacity: this is a pathological case where far too many
        //   sleep instances have been scheduled.
        // - Shutdown: No timer has been setup, which is a mis-use error.
        //
        // Both cases are extremely rare, and pretty accurately fit into
        // "logic errors", so we just panic in this case. A user couldn't
        // really do much better if we passed the error onwards.
        match ready!(self.as_mut().poll_elapsed(cx)) {
            Ok(()) => Poll::Ready(()),
            Err(e) => panic!("timer error: {}", e),
        }
    }
}
<commit_msg>time: add wait alias to sleep (#3897)<commit_after>use crate::time::driver::{Handle, TimerEntry};
use crate::time::{error::Error, Duration, Instant};

use pin_project_lite::pin_project;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};

/// Waits until `deadline` is reached.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
// Alias for old name in 0.x
#[cfg_attr(docsrs, doc(alias = "delay_until"))]
pub fn sleep_until(deadline: Instant) -> Sleep {
    Sleep::new_timeout(deadline)
}

/// Waits until `duration` has elapsed.
///
/// Equivalent to `sleep_until(Instant::now() + duration)`. An asynchronous
/// analog to `std::thread::sleep`.
///
/// No work is performed while awaiting on the sleep future to complete. `Sleep`
/// operates at millisecond granularity and should not be used for tasks that
/// require high-resolution timers.
///
/// To run something regularly on a schedule, see [`interval`].
///
/// The maximum duration for a sleep is 68719476734 milliseconds (approximately 2.2 years).
///
/// # Cancellation
///
/// Canceling a sleep instance is done by dropping the returned future. No additional
/// cleanup work is required.
///
/// # Examples
///
/// Wait 100ms and print "100 ms have elapsed".
///
/// ```
/// use tokio::time::{sleep, Duration};
///
/// #[tokio::main]
/// async fn main() {
///     sleep(Duration::from_millis(100)).await;
///     println!("100 ms have elapsed");
/// }
/// ```
///
/// [`interval`]: crate::time::interval()
// Alias for old name in 0.x
#[cfg_attr(docsrs, doc(alias = "delay_for"))]
#[cfg_attr(docsrs, doc(alias = "wait"))]
pub fn sleep(duration: Duration) -> Sleep {
    match Instant::now().checked_add(duration) {
        Some(deadline) => sleep_until(deadline),
        None => sleep_until(Instant::far_future()),
    }
}

pin_project! {
    /// Future returned by [`sleep`](sleep) and [`sleep_until`](sleep_until).
    ///
    /// This type does not implement the `Unpin` trait, which means that if you
    /// use it with [`select!`] or by calling `poll`, you have to pin it first.
    /// If you use it with `.await`, this does not apply.
    ///
    /// # Examples
    ///
    /// Wait 100ms and print "100 ms have elapsed".
    ///
    /// ```
    /// use tokio::time::{sleep, Duration};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     sleep(Duration::from_millis(100)).await;
    ///     println!("100 ms have elapsed");
    /// }
    /// ```
    ///
    /// Use with [`select!`]. Pinning the `Sleep` with [`tokio::pin!`] is
    /// necessary when the same `Sleep` is selected on multiple times.
    /// ```no_run
    /// use tokio::time::{self, Duration, Instant};
    ///
    /// #[tokio::main]
    /// async fn main() {
    ///     let sleep = time::sleep(Duration::from_millis(10));
    ///     tokio::pin!(sleep);
    ///
    ///     loop {
    ///         tokio::select! {
    ///             () = &mut sleep => {
    ///                 println!("timer elapsed");
    ///                 sleep.as_mut().reset(Instant::now() + Duration::from_millis(50));
    ///             },
    ///         }
    ///     }
    /// }
    /// ```
    /// Use in a struct with boxing. By pinning the `Sleep` with a `Box`, the
    /// `HasSleep` struct implements `Unpin`, even though `Sleep` does not.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    ///
    /// struct HasSleep {
    ///     sleep: Pin<Box<Sleep>>,
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.sleep.as_mut().poll(cx)
    ///     }
    /// }
    /// ```
    /// Use in a struct with pin projection. This method avoids the `Box`, but
    /// the `HasSleep` struct will not be `Unpin` as a consequence.
    /// ```
    /// use std::future::Future;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    /// use tokio::time::Sleep;
    /// use pin_project_lite::pin_project;
    ///
    /// pin_project! {
    ///     struct HasSleep {
    ///         #[pin]
    ///         sleep: Sleep,
    ///     }
    /// }
    ///
    /// impl Future for HasSleep {
    ///     type Output = ();
    ///
    ///     fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {
    ///         self.project().sleep.poll(cx)
    ///     }
    /// }
    /// ```
    ///
    /// [`select!`]: ../macro.select.html
    /// [`tokio::pin!`]: ../macro.pin.html
    // Alias for old name in 0.2
    #[cfg_attr(docsrs, doc(alias = "Delay"))]
    #[derive(Debug)]
    #[must_use = "futures do nothing unless you `.await` or poll them"]
    pub struct Sleep {
        deadline: Instant,

        // The link between the `Sleep` instance and the timer that drives it.
        #[pin]
        entry: TimerEntry,
    }
}

impl Sleep {
    pub(crate) fn new_timeout(deadline: Instant) -> Sleep {
        let handle = Handle::current();
        let entry = TimerEntry::new(&handle, deadline);

        Sleep { deadline, entry }
    }

    pub(crate) fn far_future() -> Sleep {
        Self::new_timeout(Instant::far_future())
    }

    /// Returns the instant at which the future will complete.
    pub fn deadline(&self) -> Instant {
        self.deadline
    }

    /// Returns `true` if `Sleep` has elapsed.
    ///
    /// A `Sleep` instance is elapsed when the requested duration has elapsed.
    pub fn is_elapsed(&self) -> bool {
        self.entry.is_elapsed()
    }

    /// Resets the `Sleep` instance to a new deadline.
    ///
    /// Calling this function allows changing the instant at which the `Sleep`
    /// future completes without having to create new associated state.
    ///
    /// This function can be called both before and after the future has
    /// completed.
    ///
    /// To call this method, you will usually combine the call with
    /// [`Pin::as_mut`], which lets you call the method without consuming the
    /// `Sleep` itself.
    ///
    /// # Example
    ///
    /// ```
    /// use tokio::time::{Duration, Instant};
    ///
    /// # #[tokio::main(flavor = "current_thread")]
    /// # async fn main() {
    /// let sleep = tokio::time::sleep(Duration::from_millis(10));
    /// tokio::pin!(sleep);
    ///
    /// sleep.as_mut().reset(Instant::now() + Duration::from_millis(20));
    /// # }
    /// ```
    ///
    /// [`Pin::as_mut`]: fn@std::pin::Pin::as_mut
    pub fn reset(self: Pin<&mut Self>, deadline: Instant) {
        let me = self.project();
        me.entry.reset(deadline);
        *me.deadline = deadline;
    }

    fn poll_elapsed(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Result<(), Error>> {
        let me = self.project();

        // Keep track of task budget
        let coop = ready!(crate::coop::poll_proceed(cx));

        me.entry.poll_elapsed(cx).map(move |r| {
            coop.made_progress();
            r
        })
    }
}

impl Future for Sleep {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // `poll_elapsed` can return an error in two cases:
        //
        // - AtCapacity: this is a pathological case where far too many
        //   sleep instances have been scheduled.
        // - Shutdown: No timer has been setup, which is a mis-use error.
        //
        // Both cases are extremely rare, and pretty accurately fit into
        // "logic errors", so we just panic in this case. A user couldn't
        // really do much better if we passed the error onwards.
        match ready!(self.as_mut().poll_elapsed(cx)) {
            Ok(()) => Poll::Ready(()),
            Err(e) => panic!("timer error: {}", e),
        }
    }
}
<|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/. */

//! The [`@font-face`][ff] at-rule.
//!
//! [ff]: https://drafts.csswg.org/css-fonts/#at-font-face-rule

use computed_values::font_family::FontFamily;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
use parser::{ParserContext, log_css_error, Parse};
use properties::longhands::font_family::parse_one_family;
use std::fmt;
use std::iter;
use style_traits::ToCss;
use values::specified::url::SpecifiedUrl;

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub enum Source {
    Url(UrlSource),
    Local(FontFamily),
}

impl ToCss for Source {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        match *self {
            Source::Url(ref url) => {
                try!(dest.write_str("url(\""));
                try!(url.to_css(dest));
            },
            Source::Local(ref family) => {
                try!(dest.write_str("local(\""));
                try!(family.to_css(dest));
            },
        }
        dest.write_str("\")")
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub struct UrlSource {
    pub url: SpecifiedUrl,
    pub format_hints: Vec<String>,
}

impl ToCss for UrlSource {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        dest.write_str(self.url.as_str())
    }
}

#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontFaceRule {
    pub family: FontFamily,
    pub sources: Vec<Source>,
}

impl ToCss for FontFaceRule {
    // Serialization of FontFaceRule is not specced.
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
        try!(dest.write_str("@font-face { font-family: "));
        try!(self.family.to_css(dest));
        try!(dest.write_str(";"));

        if self.sources.len() > 0 {
            try!(dest.write_str(" src: "));
            let mut iter = self.sources.iter();
            try!(iter.next().unwrap().to_css(dest));
            for source in iter {
                try!(dest.write_str(", "));
                try!(source.to_css(dest));
            }
            try!(dest.write_str(";"));
        }

        dest.write_str(" }")
    }
}

pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
                             -> Result<FontFaceRule, ()> {
    let mut family = None;
    let mut src = None;
    let mut iter = DeclarationListParser::new(input, FontFaceRuleParser { context: context });
    while let Some(declaration) = iter.next() {
        match declaration {
            Err(range) => {
                let pos = range.start;
                let message = format!("Unsupported @font-face descriptor declaration: '{}'",
                                      iter.input.slice(range));
                log_css_error(iter.input, pos, &*message, context);
            }
            Ok(FontFaceDescriptorDeclaration::Family(value)) => {
                family = Some(value);
            }
            Ok(FontFaceDescriptorDeclaration::Src(value)) => {
                src = Some(value);
            }
        }
    }
    match (family, src) {
        (Some(family), Some(src)) => {
            Ok(FontFaceRule {
                family: family,
                sources: src,
            })
        }
        _ => Err(())
    }
}

#[derive(Clone, Debug)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub struct EffectiveSources(Vec<Source>);

impl FontFaceRule {
    /// Returns the list of effective sources for that font-face, that is the
    /// sources which don't list any format hint, or the ones which list at
    /// least "truetype" or "opentype".
    pub fn effective_sources(&self) -> EffectiveSources {
        EffectiveSources(self.sources.iter().rev().filter(|source| {
            if let Source::Url(ref url_source) = **source {
                let hints = &url_source.format_hints;
                // We support only opentype fonts and truetype is an alias for
                // that format. Sources without format hints need to be
                // downloaded in case we support them.
                hints.is_empty() || hints.iter().any(|hint| {
                    hint == "truetype" || hint == "opentype" || hint == "woff"
                })
            } else {
                true
            }
        }).cloned().collect())
    }
}

impl iter::Iterator for EffectiveSources {
    type Item = Source;
    fn next(&mut self) -> Option<Source> {
        self.0.pop()
    }
}

enum FontFaceDescriptorDeclaration {
    Family(FontFamily),
    Src(Vec<Source>),
}

struct FontFaceRuleParser<'a, 'b: 'a> {
    context: &'a ParserContext<'b>,
}

/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for FontFaceRuleParser<'a, 'b> {
    type Prelude = ();
    type AtRule = FontFaceDescriptorDeclaration;
}

impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> {
    type Declaration = FontFaceDescriptorDeclaration;

    fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<FontFaceDescriptorDeclaration, ()> {
        match_ignore_ascii_case! { name,
            "font-family" => {
                Ok(FontFaceDescriptorDeclaration::Family(try!(
                            parse_one_family(input))))
            },
            "src" => {
                Ok(FontFaceDescriptorDeclaration::Src(try!(input.parse_comma_separated(|input| {
                    parse_one_src(self.context, input)
                }))))
            },
            _ => Err(())
        }
    }
}

fn parse_one_src(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> {
    if input.try(|input| input.expect_function_matching("local")).is_ok() {
        return Ok(Source::Local(try!(input.parse_nested_block(parse_one_family))))
    }

    let url = try!(SpecifiedUrl::parse(context, input));

    // Parsing optional format()
    let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() {
        try!(input.parse_nested_block(|input| {
            input.parse_comma_separated(|input| {
                Ok((try!(input.expect_string())).into_owned())
            })
        }))
    } else {
        vec![]
    };

    Ok(Source::Url(UrlSource {
        url: url,
        format_hints: format_hints,
    }))
}
<commit_msg>style: Document the font_face module.<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/. */

//! The [`@font-face`][ff] at-rule.
//!
//! [ff]: https://drafts.csswg.org/css-fonts/#at-font-face-rule

#![deny(missing_docs)]

use computed_values::font_family::FontFamily;
use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser};
use parser::{ParserContext, log_css_error, Parse};
use properties::longhands::font_family::parse_one_family;
use std::fmt;
use std::iter;
use style_traits::ToCss;
use values::specified::url::SpecifiedUrl;

/// A source for a font-face rule.
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub enum Source {
    /// A `url()` source.
    Url(UrlSource),
    /// A `local()` source.
    Local(FontFamily),
}

impl ToCss for Source {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
        where W: fmt::Write,
    {
        match *self {
            Source::Url(ref url) => {
                try!(dest.write_str("url(\""));
                try!(url.to_css(dest));
            },
            Source::Local(ref family) => {
                try!(dest.write_str("local(\""));
                try!(family.to_css(dest));
            },
        }
        dest.write_str("\")")
    }
}

/// A `UrlSource` represents a font-face source that has been specified with a
/// `url()` function.
///
/// https://drafts.csswg.org/css-fonts/#src-desc
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
pub struct UrlSource {
    /// The specified url.
    pub url: SpecifiedUrl,
    /// The format hints specified with the `format()` function.
    pub format_hints: Vec<String>,
}

impl ToCss for UrlSource {
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
        where W: fmt::Write,
    {
        dest.write_str(self.url.as_str())
    }
}

/// A `@font-face` rule.
///
/// https://drafts.csswg.org/css-fonts/#font-face-rule
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct FontFaceRule {
    /// The font family specified with the `font-family` property declaration.
    pub family: FontFamily,
    /// The list of sources specified with the different `src` property
    /// declarations.
    pub sources: Vec<Source>,
}

impl ToCss for FontFaceRule {
    // Serialization of FontFaceRule is not specced.
    fn to_css<W>(&self, dest: &mut W) -> fmt::Result
        where W: fmt::Write,
    {
        try!(dest.write_str("@font-face { font-family: "));
        try!(self.family.to_css(dest));
        try!(dest.write_str(";"));

        if self.sources.len() > 0 {
            try!(dest.write_str(" src: "));
            let mut iter = self.sources.iter();
            try!(iter.next().unwrap().to_css(dest));
            for source in iter {
                try!(dest.write_str(", "));
                try!(source.to_css(dest));
            }
            try!(dest.write_str(";"));
        }

        dest.write_str(" }")
    }
}

/// Parse the block inside a `@font-face` rule.
///
/// Note that the prelude parsing code lives in the `stylesheets` module.
pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
                             -> Result<FontFaceRule, ()> {
    let mut family = None;
    let mut src = None;
    let mut iter = DeclarationListParser::new(input, FontFaceRuleParser { context: context });
    while let Some(declaration) = iter.next() {
        match declaration {
            Err(range) => {
                let pos = range.start;
                let message = format!("Unsupported @font-face descriptor declaration: '{}'",
                                      iter.input.slice(range));
                log_css_error(iter.input, pos, &*message, context);
            }
            Ok(FontFaceDescriptorDeclaration::Family(value)) => {
                family = Some(value);
            }
            Ok(FontFaceDescriptorDeclaration::Src(value)) => {
                src = Some(value);
            }
        }
    }
    match (family, src) {
        (Some(family), Some(src)) => {
            Ok(FontFaceRule {
                family: family,
                sources: src,
            })
        }
        _ => Err(())
    }
}

/// A list of effective sources that we send over through IPC to the font cache.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub struct EffectiveSources(Vec<Source>);

impl FontFaceRule {
    /// Returns the list of effective sources for that font-face, that is the
    /// sources which don't list any format hint, or the ones which list at
    /// least "truetype" or "opentype".
    pub fn effective_sources(&self) -> EffectiveSources {
        EffectiveSources(self.sources.iter().rev().filter(|source| {
            if let Source::Url(ref url_source) = **source {
                let hints = &url_source.format_hints;
                // We support only opentype fonts and truetype is an alias for
                // that format. Sources without format hints need to be
                // downloaded in case we support them.
                hints.is_empty() || hints.iter().any(|hint| {
                    hint == "truetype" || hint == "opentype" || hint == "woff"
                })
            } else {
                true
            }
        }).cloned().collect())
    }
}

impl iter::Iterator for EffectiveSources {
    type Item = Source;
    fn next(&mut self) -> Option<Source> {
        self.0.pop()
    }
}

enum FontFaceDescriptorDeclaration {
    Family(FontFamily),
    Src(Vec<Source>),
}

struct FontFaceRuleParser<'a, 'b: 'a> {
    context: &'a ParserContext<'b>,
}

/// Default methods reject all at rules.
impl<'a, 'b> AtRuleParser for FontFaceRuleParser<'a, 'b> {
    type Prelude = ();
    type AtRule = FontFaceDescriptorDeclaration;
}

impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> {
    type Declaration = FontFaceDescriptorDeclaration;

    fn parse_value(&mut self, name: &str, input: &mut Parser) -> Result<FontFaceDescriptorDeclaration, ()> {
        match_ignore_ascii_case! { name,
            "font-family" => {
                Ok(FontFaceDescriptorDeclaration::Family(try!(
                            parse_one_family(input))))
            },
            "src" => {
                Ok(FontFaceDescriptorDeclaration::Src(try!(input.parse_comma_separated(|input| {
                    parse_one_src(self.context, input)
                }))))
            },
            _ => Err(())
        }
    }
}

fn parse_one_src(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> {
    if input.try(|input| input.expect_function_matching("local")).is_ok() {
        return Ok(Source::Local(try!(input.parse_nested_block(parse_one_family))))
    }

    let url = try!(SpecifiedUrl::parse(context, input));

    // Parsing optional format()
    let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() {
        try!(input.parse_nested_block(|input| {
            input.parse_comma_separated(|input| {
                Ok((try!(input.expect_string())).into_owned())
            })
        }))
    } else {
        vec![]
    };

    Ok(Source::Url(UrlSource {
        url: url,
        format_hints: format_hints,
    }))
}
<|endoftext|>