<commit_before>use std::sync::atomic::{AtomicUsize, Ordering};

pub type Timestamp = u64;

lazy_static! {
    static ref LAST_TIMESTAMP: AtomicUsize = AtomicUsize::new(0);
}

pub fn get_timestamp() -> Timestamp {
    LAST_TIMESTAMP.fetch_add(1, Ordering::SeqCst) as u64
}

#[test]
fn it_gives_unique_numbers() {
    let a = get_timestamp();
    let b = get_timestamp();

    assert!(a != b);
}
<commit_msg>Bring timestamp back to usize -- curse you, large_integer_atomics!<commit_after>use std::sync::atomic::{AtomicUsize, Ordering};

pub type Timestamp = usize;

lazy_static! {
    static ref LAST_TIMESTAMP: AtomicUsize = AtomicUsize::new(0);
}

pub fn get_timestamp() -> Timestamp {
    LAST_TIMESTAMP.fetch_add(1, Ordering::SeqCst)
}

#[test]
fn it_gives_unique_numbers() {
    let a = get_timestamp();
    let b = get_timestamp();

    assert!(a != b);
}
<|endoftext|>


<commit_before>use super::Tokens;

pub trait ToTokens {
    fn to_tokens(&self, &mut Tokens);
}

impl<'a, T: ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        if let Some(ref t) = *self {
            t.to_tokens(tokens);
        }
    }
}

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(&format!("{:?}", self));
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(&format!("{:?}", self));
    }
}

#[derive(Debug)]
pub struct ByteStr<'a>(pub &'a str);

impl<'a> ToTokens for ByteStr<'a> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(&format!("b{:?}", self.0));
    }
}

macro_rules! impl_to_tokens_display {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&self.to_string());
            }
        }
    };
}

impl_to_tokens_display!(Tokens);
impl_to_tokens_display!(bool);

macro_rules! impl_to_tokens_integer {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&format!(concat!("{}", stringify!($ty)), self));
            }
        }
    };
}

impl_to_tokens_integer!(i8);
impl_to_tokens_integer!(i16);
impl_to_tokens_integer!(i32);
impl_to_tokens_integer!(i64);
impl_to_tokens_integer!(isize);
impl_to_tokens_integer!(u8);
impl_to_tokens_integer!(u16);
impl_to_tokens_integer!(u32);
impl_to_tokens_integer!(u64);
impl_to_tokens_integer!(usize);

macro_rules! impl_to_tokens_floating {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                use std::num::FpCategory::*;
                match self.classify() {
                    Zero | Subnormal | Normal => {
                        tokens.append(&format!(concat!("{}", stringify!($ty)), self));
                    }
                    Nan => {
                        tokens.append("::");
                        tokens.append("std");
                        tokens.append("::");
                        tokens.append(stringify!($ty));
                        tokens.append("::");
                        tokens.append("NAN");
                    }
                    Infinite => {
                        tokens.append("::");
                        tokens.append("std");
                        tokens.append("::");
                        tokens.append(stringify!($ty));
                        tokens.append("::");
                        if self.is_sign_positive() {
                            tokens.append("INFINITY");
                        } else {
                            tokens.append("NEG_INFINITY");
                        }
                    }
                }
            }
        }
    };
}
impl_to_tokens_floating!(f32);
impl_to_tokens_floating!(f64);
<commit_msg>ToTokens for Box<T><commit_after>use super::Tokens;

pub trait ToTokens {
    fn to_tokens(&self, &mut Tokens);
}

impl<'a, T: ToTokens> ToTokens for &'a T {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ToTokens> ToTokens for Box<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        (**self).to_tokens(tokens);
    }
}

impl<T: ToTokens> ToTokens for Option<T> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        if let Some(ref t) = *self {
            t.to_tokens(tokens);
        }
    }
}

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(&format!("{:?}", self));
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(&format!("{:?}", self));
    }
}

#[derive(Debug)]
pub struct ByteStr<'a>(pub &'a str);

impl<'a> ToTokens for ByteStr<'a> {
    fn to_tokens(&self, tokens: &mut Tokens) {
        tokens.append(&format!("b{:?}", self.0));
    }
}

macro_rules! impl_to_tokens_display {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&self.to_string());
            }
        }
    };
}

impl_to_tokens_display!(Tokens);
impl_to_tokens_display!(bool);

macro_rules! impl_to_tokens_integer {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                tokens.append(&format!(concat!("{}", stringify!($ty)), self));
            }
        }
    };
}

impl_to_tokens_integer!(i8);
impl_to_tokens_integer!(i16);
impl_to_tokens_integer!(i32);
impl_to_tokens_integer!(i64);
impl_to_tokens_integer!(isize);
impl_to_tokens_integer!(u8);
impl_to_tokens_integer!(u16);
impl_to_tokens_integer!(u32);
impl_to_tokens_integer!(u64);
impl_to_tokens_integer!(usize);

macro_rules! impl_to_tokens_floating {
    ($ty:ty) => {
        impl ToTokens for $ty {
            fn to_tokens(&self, tokens: &mut Tokens) {
                use std::num::FpCategory::*;
                match self.classify() {
                    Zero | Subnormal | Normal => {
                        tokens.append(&format!(concat!("{}", stringify!($ty)), self));
                    }
                    Nan => {
                        tokens.append("::");
                        tokens.append("std");
                        tokens.append("::");
                        tokens.append(stringify!($ty));
                        tokens.append("::");
                        tokens.append("NAN");
                    }
                    Infinite => {
                        tokens.append("::");
                        tokens.append("std");
                        tokens.append("::");
                        tokens.append(stringify!($ty));
                        tokens.append("::");
                        if self.is_sign_positive() {
                            tokens.append("INFINITY");
                        } else {
                            tokens.append("NEG_INFINITY");
                        }
                    }
                }
            }
        }
    };
}
impl_to_tokens_floating!(f32);
impl_to_tokens_floating!(f64);
<|endoftext|>


<commit_before>use event::Event;
use sass::comment::SassComment;
use sass::rule::SassRule;
use sass::selector::SassSelector;
use sass::variable::SassVariable;
use top_level_event::TopLevelEvent;

use std::borrow::Cow::Borrowed;

fn is_ascii_whitespace(c: u8) -> bool {
   is_newline(c) || is_ascii_whitespace_no_nl(c)
}

fn is_ascii_whitespace_no_nl(c: u8) -> bool {
    c == b'\t' || c == 0x0b || c == 0x0c || c == b' '
}

fn is_newline(c: u8) -> bool {
    c == b'\n' || c == b'\r'
}

fn isnt_newline(c: u8) -> bool {
    !is_newline(c)
}

// unusual among "scan" functions in that it scans from the _back_ of the string
// TODO: should also scan unicode whitespace?
fn scan_trailing_whitespace(data: &str) -> usize {
    match data.as_bytes().iter().rev().position(|&c| !is_ascii_whitespace_no_nl(c)) {
        Some(i) => i,
        None => data.len()
    }
}

#[derive(Debug)]
pub struct Tokenizer<'a> {
    sass: &'a str,
    bytes: &'a [u8],
    offset: usize,
    state: State,
    sass_rule_stack: Vec<SassRule<'a>>,
    current_sass_rule_selectors_done: bool,
}

#[derive(PartialEq, Debug, Clone)]
enum State {
    OutsideRules,
    InVariable,
    InComment,
    InRule,
    InSelectors,
    InProperties,
    EndRule,
    Eof,
}

impl<'a> Tokenizer<'a> {
    pub fn new(sass: &'a str) -> Tokenizer<'a> {
        Tokenizer {
            sass: &sass,
            bytes: &sass.as_bytes(),
            offset: 0,
            state: State::OutsideRules,
            sass_rule_stack: Vec::new(),
            current_sass_rule_selectors_done: false,
        }
    }

    fn start_something(&mut self) -> Option<TopLevelEvent<'a>> {
        let mut current_sass_rule = SassRule::new();
        self.current_sass_rule_selectors_done = false;

        self.pick_something();
        while self.state != State::OutsideRules {
            if self.state == State::Eof { return None }

            if self.state == State::InSelectors {
                let sel = self.next_selector();
                if sel.is_some() {
                    current_sass_rule.selectors.push(sel.unwrap());
                }
            } else if self.state == State::InProperties {
                let prop = self.next_property();
                if prop.is_some() {
                    current_sass_rule.children.push(prop.unwrap());
                }
            } else if self.state == State::EndRule {
                // consume '}', should probably be checking that's what we actually have
                self.offset += 1;

                match self.sass_rule_stack.pop() {
                    Some(mut rule) => {
                        rule.children.push(Event::ChildRule(current_sass_rule));
                        current_sass_rule = rule;
                        self.pick_something();
                    },
                    None => self.state = State::OutsideRules,
                }
            } else if self.state == State::InRule {
                self.sass_rule_stack.push(current_sass_rule);
                current_sass_rule = SassRule::new();
                self.current_sass_rule_selectors_done = false;
                self.pick_something();
            } else if self.state == State::InVariable {
                let var = self.next_variable();
                if var.is_some() {
                    return var
                } else {
                    // is this really what we should be doing here? reachable?
                    self.state = State::Eof;
                }
            } else if self.state == State::InComment {
                let comment = self.next_comment();
                if comment.is_some() {
                    if self.sass_rule_stack.len() == 0 &&
                       current_sass_rule.selectors.len() == 0 &&
                       current_sass_rule.children.len() == 0 {
                           return Some(TopLevelEvent::Comment(SassComment { comment: comment.unwrap() }))
                    } else {
                        current_sass_rule.children.push(comment.unwrap());
                        self.pick_something();
                    }
                } else {
                    // is this really what we should be doing here? reachable?
                    self.state = State::Eof;
                }
            } else {
                println!("i dont know what to do for {:?}", self.state);
                println!("current sass rule = {:?}", current_sass_rule);
                self.state = State::Eof;
            }
        }

        Some(TopLevelEvent::Rule(current_sass_rule))
    }

    fn pick_something(&mut self) {
        self.skip_leading_whitespace();

        if self.offset == self.sass.len() {
            self.state = State::Eof;
            return
        }

        let c = self.bytes[self.offset];

        if c == b'}' {
            self.state = State::EndRule;
            return
        }

        if c == b'$' {
            self.state = State::InVariable;
            return
        }

        if c == b'/' && (self.offset + 1) < self.sass.len() {
            let d = self.bytes[self.offset + 1];
            if d == b'*' {
                self.state = State::InComment;
                return
            }
        }

        self.state = State::InSelectors;
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

    fn skip_leading_whitespace(&mut self) {
        let mut i = self.offset;
        let limit = self.sass.len();

        while i < limit {
            let c = self.bytes[i];
            if is_ascii_whitespace(c) {
                i += self.scan_while(&self.sass[i..self.sass.len()], is_ascii_whitespace);
            } else if c == b'/' && i + 1 < limit && self.bytes[i + 1] == b'/' {
                i += self.scan_while(&self.sass[i..self.sass.len()], isnt_newline);
            } else {
                self.offset = i;
                return
            }
        }
        self.offset = limit;
    }

    fn next_comment(&mut self) -> Option<Event<'a>> {
        let comment_body_beginning = self.offset;
        let mut i = comment_body_beginning + 2;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b'*' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            if self.bytes[i+1] == b'/' {
                self.offset = i + 2;
                return Some(Event::Comment(Borrowed(&self.sass[comment_body_beginning..i + 2])))
            } else {
                i += 1;
            }
        }
        None
    }

    fn next_variable(&mut self) -> Option<TopLevelEvent<'a>> {
        // TODO: can parts of this be deduplicated with properties?
        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Some(TopLevelEvent::Variable(SassVariable{
                    name: Borrowed(&self.sass[name_beginning..name_end]),
                    value: Borrowed(&self.sass[value_beginning..value_end]),
                }))
            }
        }
        self.offset = self.sass.len();
        None
    }

    fn next_property(&mut self) -> Option<Event<'a>> {
        self.skip_leading_whitespace();

        if self.offset == self.sass.len() {
            self.state = State::Eof;
            return None
        }

        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        let c = self.bytes[i];
        if c == b'}' {
            self.state = State::EndRule;
            return None
        }

        let d = self.bytes[i + 1];
        if c == b'/' && d == b'*' {
            self.state = State::InComment;
            return None
        }

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            // Inefficient since we already skipped the whitespace and we'll have to
            // do it again but oh well
            let c = self.bytes[i];
            if c == b'{' {
                self.state = State::InRule;
                return None
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                if self.bytes[name_beginning] == b'$' {
                    return Some(Event::Variable(SassVariable {
                        name: Borrowed(&self.sass[name_beginning..name_end]),
                        value: Borrowed(&self.sass[value_beginning..value_end])
                    }))
                } else {
                    return Some(Event::Property(
                        Borrowed(&self.sass[name_beginning..name_end]),
                        Borrowed(&self.sass[value_beginning..value_end])
                    ))
                }
            }
        }
        self.offset = self.sass.len();
        None
    }

    fn next_selector(&mut self) -> Option<SassSelector<'a>> {
        self.skip_leading_whitespace();

        let beginning = self.offset;
        let mut i = beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b',' || c == b'{' || c == b':') {
                Some(pos) => { i += pos; },
                None => { i = limit; break; },
            }

            let c = self.bytes[i];

            if c == b':' {
                self.state = State::InProperties;
                return None
            }

            if c == b',' || c == b'{' {
                let n = scan_trailing_whitespace(&self.sass[beginning..i]);
                let end = i - n;
                if end > beginning {
                    if c == b'{' {
                        if self.current_sass_rule_selectors_done {
                            self.state = State::InRule;
                            return None
                        } else {
                            self.current_sass_rule_selectors_done = true;
                            self.state = State::InProperties;
                        }
                    }
                    self.offset = i + 1;
                    if c == b',' && beginning + 1 == end {
                        self.offset += 1;
                        return self.next_selector()
                    }
                    return Some(SassSelector { name: Borrowed(&self.sass[beginning..end]) })
                } else {
                    // only whitespace between commas
                    self.offset += 1;
                    return self.next_selector()
                }
            }

            self.offset = i;
            if i > beginning {
                return Some(SassSelector { name: Borrowed(&self.sass[beginning..i]) })
            }
            i += 1;
        }

        if i > beginning {
            self.offset = i;
            Some(SassSelector { name: Borrowed(&self.sass[beginning..i]) })
        } else {
            self.state = State::Eof;
            None
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = TopLevelEvent<'a>;

    fn next(&mut self) -> Option<TopLevelEvent<'a>> {
        if self.offset < self.sass.len() {
            return self.start_something()
        }
        None
    }
}
<commit_msg>Yeah this was not the right fix for extra commas<commit_after>use event::Event;
use sass::comment::SassComment;
use sass::rule::SassRule;
use sass::selector::SassSelector;
use sass::variable::SassVariable;
use top_level_event::TopLevelEvent;

use std::borrow::Cow::Borrowed;

fn is_ascii_whitespace(c: u8) -> bool {
   is_newline(c) || is_ascii_whitespace_no_nl(c)
}

fn is_ascii_whitespace_no_nl(c: u8) -> bool {
    c == b'\t' || c == 0x0b || c == 0x0c || c == b' '
}

fn is_newline(c: u8) -> bool {
    c == b'\n' || c == b'\r'
}

fn isnt_newline(c: u8) -> bool {
    !is_newline(c)
}

// unusual among "scan" functions in that it scans from the _back_ of the string
// TODO: should also scan unicode whitespace?
fn scan_trailing_whitespace(data: &str) -> usize {
    match data.as_bytes().iter().rev().position(|&c| !is_ascii_whitespace_no_nl(c)) {
        Some(i) => i,
        None => data.len()
    }
}

#[derive(Debug)]
pub struct Tokenizer<'a> {
    sass: &'a str,
    bytes: &'a [u8],
    offset: usize,
    state: State,
    sass_rule_stack: Vec<SassRule<'a>>,
    current_sass_rule_selectors_done: bool,
}

#[derive(PartialEq, Debug, Clone)]
enum State {
    OutsideRules,
    InVariable,
    InComment,
    InRule,
    InSelectors,
    InProperties,
    EndRule,
    Eof,
}

impl<'a> Tokenizer<'a> {
    pub fn new(sass: &'a str) -> Tokenizer<'a> {
        Tokenizer {
            sass: &sass,
            bytes: &sass.as_bytes(),
            offset: 0,
            state: State::OutsideRules,
            sass_rule_stack: Vec::new(),
            current_sass_rule_selectors_done: false,
        }
    }

    fn start_something(&mut self) -> Option<TopLevelEvent<'a>> {
        let mut current_sass_rule = SassRule::new();
        self.current_sass_rule_selectors_done = false;

        self.pick_something();
        while self.state != State::OutsideRules {
            if self.state == State::Eof { return None }

            if self.state == State::InSelectors {
                let sel = self.next_selector();
                if sel.is_some() {
                    current_sass_rule.selectors.push(sel.unwrap());
                }
            } else if self.state == State::InProperties {
                let prop = self.next_property();
                if prop.is_some() {
                    current_sass_rule.children.push(prop.unwrap());
                }
            } else if self.state == State::EndRule {
                // consume '}', should probably be checking that's what we actually have
                self.offset += 1;

                match self.sass_rule_stack.pop() {
                    Some(mut rule) => {
                        rule.children.push(Event::ChildRule(current_sass_rule));
                        current_sass_rule = rule;
                        self.pick_something();
                    },
                    None => self.state = State::OutsideRules,
                }
            } else if self.state == State::InRule {
                self.sass_rule_stack.push(current_sass_rule);
                current_sass_rule = SassRule::new();
                self.current_sass_rule_selectors_done = false;
                self.pick_something();
            } else if self.state == State::InVariable {
                let var = self.next_variable();
                if var.is_some() {
                    return var
                } else {
                    // is this really what we should be doing here? reachable?
                    self.state = State::Eof;
                }
            } else if self.state == State::InComment {
                let comment = self.next_comment();
                if comment.is_some() {
                    if self.sass_rule_stack.len() == 0 &&
                       current_sass_rule.selectors.len() == 0 &&
                       current_sass_rule.children.len() == 0 {
                           return Some(TopLevelEvent::Comment(SassComment { comment: comment.unwrap() }))
                    } else {
                        current_sass_rule.children.push(comment.unwrap());
                        self.pick_something();
                    }
                } else {
                    // is this really what we should be doing here? reachable?
                    self.state = State::Eof;
                }
            } else {
                println!("i dont know what to do for {:?}", self.state);
                println!("current sass rule = {:?}", current_sass_rule);
                self.state = State::Eof;
            }
        }

        Some(TopLevelEvent::Rule(current_sass_rule))
    }

    fn pick_something(&mut self) {
        self.skip_leading_whitespace();

        if self.offset == self.sass.len() {
            self.state = State::Eof;
            return
        }

        let c = self.bytes[self.offset];

        if c == b'}' {
            self.state = State::EndRule;
            return
        }

        if c == b'$' {
            self.state = State::InVariable;
            return
        }

        if c == b'/' && (self.offset + 1) < self.sass.len() {
            let d = self.bytes[self.offset + 1];
            if d == b'*' {
                self.state = State::InComment;
                return
            }
        }

        self.state = State::InSelectors;
    }

    fn scan_while<F>(&mut self, data: &str, f: F) -> usize
            where F: Fn(u8) -> bool {
        match data.as_bytes().iter().position(|&c| !f(c)) {
            Some(i) => i,
            None => data.len()
        }
    }

    fn skip_leading_whitespace(&mut self) {
        let mut i = self.offset;
        let limit = self.sass.len();

        while i < limit {
            let c = self.bytes[i];
            if is_ascii_whitespace(c) {
                i += self.scan_while(&self.sass[i..self.sass.len()], is_ascii_whitespace);
            } else if c == b'/' && i + 1 < limit && self.bytes[i + 1] == b'/' {
                i += self.scan_while(&self.sass[i..self.sass.len()], isnt_newline);
            } else {
                self.offset = i;
                return
            }
        }
        self.offset = limit;
    }

    fn next_comment(&mut self) -> Option<Event<'a>> {
        let comment_body_beginning = self.offset;
        let mut i = comment_body_beginning + 2;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b'*' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            if self.bytes[i+1] == b'/' {
                self.offset = i + 2;
                return Some(Event::Comment(Borrowed(&self.sass[comment_body_beginning..i + 2])))
            } else {
                i += 1;
            }
        }
        None
    }

    fn next_variable(&mut self) -> Option<TopLevelEvent<'a>> {
        // TODO: can parts of this be deduplicated with properties?
        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' ) {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                return Some(TopLevelEvent::Variable(SassVariable{
                    name: Borrowed(&self.sass[name_beginning..name_end]),
                    value: Borrowed(&self.sass[value_beginning..value_end]),
                }))
            }
        }
        self.offset = self.sass.len();
        None
    }

    fn next_property(&mut self) -> Option<Event<'a>> {
        self.skip_leading_whitespace();

        if self.offset == self.sass.len() {
            self.state = State::Eof;
            return None
        }

        let name_beginning = self.offset;
        let mut i = name_beginning;
        let limit = self.sass.len();

        let c = self.bytes[i];
        if c == b'}' {
            self.state = State::EndRule;
            return None
        }

        let d = self.bytes[i + 1];
        if c == b'/' && d == b'*' {
            self.state = State::InComment;
            return None
        }

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b':' || c == b'{') {
                Some(pos) => { i += pos; },
                None => { break; },
            }

            // Inefficient since we already skipped the whitespace and we'll have to
            // do it again but oh well
            let c = self.bytes[i];
            if c == b'{' {
                self.state = State::InRule;
                return None
            }

            let name_end = i;

            i += 1;
            self.offset = i;
            self.skip_leading_whitespace();

            let value_beginning = self.offset;
            i = value_beginning;

            while i < limit {
                match self.bytes[i..limit].iter().position(|&c| c == b';') {
                    Some(pos) => { i += pos; },
                    None => { i = limit; break; },
                }

                let value_end = i;
                self.offset = i + 1;

                self.skip_leading_whitespace();

                if self.bytes[name_beginning] == b'$' {
                    return Some(Event::Variable(SassVariable {
                        name: Borrowed(&self.sass[name_beginning..name_end]),
                        value: Borrowed(&self.sass[value_beginning..value_end])
                    }))
                } else {
                    return Some(Event::Property(
                        Borrowed(&self.sass[name_beginning..name_end]),
                        Borrowed(&self.sass[value_beginning..value_end])
                    ))
                }
            }
        }
        self.offset = self.sass.len();
        None
    }

    fn next_selector(&mut self) -> Option<SassSelector<'a>> {
        self.skip_leading_whitespace();

        let beginning = self.offset;
        let mut i = beginning;
        let limit = self.sass.len();

        while i < limit {
            match self.bytes[i..limit].iter().position(|&c| c == b',' || c == b'{' || c == b':') {
                Some(pos) => { i += pos; },
                None => { i = limit; break; },
            }

            let c = self.bytes[i];

            if c == b':' {
                self.state = State::InProperties;
                return None
            }

            if c == b',' || c == b'{' {
                let n = scan_trailing_whitespace(&self.sass[beginning..i]);
                let end = i - n;
                if end > beginning {
                    if c == b'{' {
                        if self.current_sass_rule_selectors_done {
                            self.state = State::InRule;
                            return None
                        } else {
                            self.current_sass_rule_selectors_done = true;
                            self.state = State::InProperties;
                        }
                    }
                    self.offset = i + 1;
                    return Some(SassSelector { name: Borrowed(&self.sass[beginning..end]) })
                } else {
                    // only whitespace between commas
                    self.offset += 1;
                    return self.next_selector()
                }
            }

            self.offset = i;
            if i > beginning {
                return Some(SassSelector { name: Borrowed(&self.sass[beginning..i]) })
            }
            i += 1;
        }

        if i > beginning {
            self.offset = i;
            Some(SassSelector { name: Borrowed(&self.sass[beginning..i]) })
        } else {
            self.state = State::Eof;
            None
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = TopLevelEvent<'a>;

    fn next(&mut self) -> Option<TopLevelEvent<'a>> {
        if self.offset < self.sass.len() {
            return self.start_something()
        }
        None
    }
}
<|endoftext|>


<commit_before>//! This module contains functions references for reflection in generated code.

#![doc(hidden)]

pub mod v2;

pub use crate::reflect::accessor::map::make_map_accessor;
pub use crate::reflect::accessor::repeated::make_repeated_field_accessor;
pub use crate::reflect::accessor::repeated::make_vec_accessor;
pub use crate::reflect::accessor::singular::make_option_accessor;
pub use crate::reflect::accessor::singular::make_option_enum_accessor;
pub use crate::reflect::accessor::singular::make_option_get_copy_accessor;
pub use crate::reflect::accessor::singular::make_option_get_ref_accessor;
pub use crate::reflect::accessor::singular::make_simple_field_accessor;
pub use crate::reflect::accessor::singular::oneof::make_oneof_copy_has_get_set_accessors;
pub use crate::reflect::accessor::singular::oneof::make_oneof_deref_has_get_set_accessor;
pub use crate::reflect::accessor::singular::oneof::make_oneof_message_has_get_mut_set_accessor;
pub use crate::reflect::accessor::FieldAccessor;
<commit_msg>Remove old rt aliases<commit_after>//! This module contains functions references for reflection in generated code.

#![doc(hidden)]

pub mod v2;

pub use crate::reflect::accessor::FieldAccessor;
<|endoftext|>


<commit_before>use regex::Regex;
use time::Timespec;

use time_utils::parse_time_str;

pub struct FileNameInfo<'a> {
    pub file_name: &'a str,
    pub info: Info
}

#[derive(Eq, PartialEq, Debug)]
pub struct Info {
    pub tp: Type,
    pub compressed: bool,
    pub encrypted: bool
}

#[derive(Eq, PartialEq, Debug)]
pub enum Type {
    Full{
        time: Timespec,
        volume_number: i32
    },
    FullManifest{
        time: Timespec,
        partial: bool
    },
    Inc{
        start_time: Timespec,
        end_time: Timespec,
        volume_number: i32
    },
    IncManifest{
        start_time: Timespec,
        end_time: Timespec,
        partial: bool
    },
    FullSig{
        time: Timespec,
        partial: bool
    },
    NewSig{
        start_time: Timespec,
        end_time: Timespec,
        partial: bool
    }
}

pub struct FileNameParser {
    full_vol_re: Regex,
    full_manifest_re: Regex,
    inc_vol_re: Regex,
    inc_manifest_re: Regex,
    full_sig_re: Regex,
    new_sig_re: Regex
}

impl<'a> FileNameInfo<'a> {
    pub fn new(name: &'a str, info: Info) -> Self {
        FileNameInfo {
            file_name: &name,
            info: info
        }
    }
}

impl Type {
    pub fn time_range(&self) -> (Timespec, Timespec) {
        match *self {
            Type::Full{ time, .. } |
                Type::FullSig{ time, .. } |
                Type::FullManifest{ time, .. } => (time, time),
            Type::Inc{ start_time, end_time, .. } |
                Type::IncManifest{ start_time, end_time, .. } |
                Type::NewSig{ start_time, end_time, .. } => (start_time, end_time)
        }
    }
}

impl FileNameParser {
    pub fn new() -> Self {
        FileNameParser {
            full_vol_re: Regex::new(r"^duplicity-full\.(?P<time>.*?)\.vol(?P<num>[0-9]+)\.difftar(?P<partial>(\.part))?($|\.)").unwrap(),
            full_manifest_re: Regex::new(r"^duplicity-full\.(?P<time>.*?)\.manifest(?P<partial>(\.part))?($|\.)").unwrap(),
            inc_vol_re: Regex::new(r"^duplicity-inc\.(?P<start_time>.*?)\.to\.(?P<end_time>.*?)\.vol(?P<num>[0-9]+)\.difftar($|\.)").unwrap(),
            inc_manifest_re: Regex::new(r"^duplicity-inc\.(?P<start_time>.*?)\.to\.(?P<end_time>.*?)\.manifest(?P<partial>(\.part))?(\.|$)").unwrap(),
            full_sig_re: Regex::new(r"^duplicity-full-signatures\.(?P<time>.*?)\.sigtar(?P<partial>(\.part))?(\.|$)").unwrap(),
            new_sig_re: Regex::new(r"^duplicity-new-signatures\.(?P<start_time>.*?)\.to\.(?P<end_time>.*?)\.sigtar(?P<partial>(\.part))?(\.|$)").unwrap(),
        }
    }

    pub fn parse(&self, filename: &str) -> Option<Info> {
        use std::ascii::AsciiExt;

        let lower_fname = filename.to_ascii_lowercase();
        let opt_type = self.check_full(&lower_fname)
                           .or(self.check_inc(&lower_fname))
                           .or(self.check_sig(&lower_fname));
        opt_type.map(|t| Info{ tp: t,
            compressed: self.is_compressed(lower_fname.as_ref()),
            encrypted: self.is_encrypted(lower_fname.as_ref())
        })
    }

    fn check_full(&self, filename: &str) -> Option<Type> {
        if let Some(captures) = self.full_vol_re.captures(filename) {
            let time = try_opt!(parse_time_str(captures.name("time").unwrap()));
            let vol_num = try_opt!(self.get_vol_num(captures.name("num").unwrap()));
            return Some(Type::Full{
                time: time,
                volume_number: vol_num
            });
        }
        if let Some(captures) = self.full_manifest_re.captures(filename) {
            let time = try_opt!(parse_time_str(captures.name("time").unwrap()));
            return Some(Type::FullManifest{
                time: time,
                partial: captures.name("partial").is_some()
            });
        }
        None
    }

    fn check_inc(&self, filename: &str) -> Option<Type> {
        if let Some(captures) = self.inc_vol_re.captures(filename) {
            let start_time = try_opt!(parse_time_str(captures.name("start_time").unwrap()));
            let end_time = try_opt!(parse_time_str(captures.name("end_time").unwrap()));
            let vol_num = try_opt!(self.get_vol_num(captures.name("num").unwrap()));
            Some(Type::Inc{
                start_time: start_time,
                end_time: end_time,
                volume_number: vol_num
            })
        }
        else if let Some(captures) = self.inc_manifest_re.captures(filename) {
            let start_time = try_opt!(parse_time_str(captures.name("start_time").unwrap()));
            let end_time = try_opt!(parse_time_str(captures.name("end_time").unwrap()));
            Some(Type::IncManifest{
                start_time: start_time,
                end_time: end_time,
                partial: captures.name("partial").is_some()
            })
        }
        else {
            None
        }
    }

    fn check_sig(&self, filename: &str) -> Option<Type> {
        if let Some(captures) = self.full_sig_re.captures(filename) {
            let time = try_opt!(parse_time_str(captures.name("time").unwrap()));
            Some(Type::FullSig{
                time: time,
                partial: captures.name("partial").is_some()
            })
        }
        else if let Some(captures) = self.new_sig_re.captures(filename) {
            let start_time = try_opt!(parse_time_str(captures.name("start_time").unwrap()));
            let end_time = try_opt!(parse_time_str(captures.name("end_time").unwrap()));
            Some(Type::NewSig{
                start_time: start_time,
                end_time: end_time,
                partial: captures.name("partial").is_some()
            })
        }
        else {
            None
        }
    }

    fn get_vol_num(&self, s: &str) -> Option<i32> {
        s.parse::<i32>().ok()
    }

    fn is_encrypted(&self, s: &str) -> bool {
        s.ends_with(".gpg") || s.ends_with(".g")
    }

    fn is_compressed(&self, s: &str) -> bool {
        s.ends_with(".gz") || s.ends_with(".z")
    }
}

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

    #[test]
    fn parser_test() {
        let parser = FileNameParser::new();
        // invalid
        assert_eq!(parser.parse("invalid"), None);
        // full
        assert_eq!(parser.parse("duplicity-full.20150617T182545Z.vol1.difftar.gz"),
                   Some(Info{ tp: Type::Full{ time: parse_time_str("20150617t182545z").unwrap(),
                                              volume_number: 1 },
                              compressed: true,
                              encrypted: false }));
        // full manifest
        assert_eq!(parser.parse("duplicity-full.20150617T182545Z.manifest"),
                   Some(Info{ tp: Type::FullManifest{ time: parse_time_str("20150617t182545z").unwrap(),
                                                      partial: false },
                              compressed: false,
                              encrypted: false }));
        // inc
        assert_eq!(parser.parse("duplicity-inc.20150617T182629Z.to.20150617T182650Z.vol1.difftar.gz"),
                   Some(Info{ tp: Type::Inc{ start_time: parse_time_str("20150617t182629z").unwrap(),
                                             end_time: parse_time_str("20150617t182650z").unwrap(),
                                             volume_number: 1 },
                              compressed: true,
                              encrypted: false }));
        // inc manifest
        assert_eq!(parser.parse("duplicity-inc.20150617T182545Z.to.20150617T182629Z.manifest"),
                   Some(Info{ tp: Type::IncManifest{ start_time: parse_time_str("20150617t182545z").unwrap(),
                                                     end_time: parse_time_str("20150617t182629z").unwrap(),
                                                     partial: false },
                              compressed: false,
                              encrypted: false }));
        // new sig
        assert_eq!(parser.parse("duplicity-new-signatures.20150617T182545Z.to.20150617T182629Z.sigtar.gz"),
                   Some(Info{ tp: Type::NewSig{ start_time: parse_time_str("20150617t182545z").unwrap(),
                                                end_time: parse_time_str("20150617t182629z").unwrap(),
                                                partial: false },
                              compressed: true,
                              encrypted: false }));
        // full sig
        assert_eq!(parser.parse("duplicity-full-signatures.20150617T182545Z.sigtar.gz"),
                   Some(Info{ tp: Type::FullSig{ time: parse_time_str("20150617t182545z").unwrap(),
                                                 partial: false },
                              compressed: true,
                              encrypted: false }));
    }

    #[test]
    fn time_test() {
        use time::{strptime, strftime, at_utc, Tm};

        // parse
        let tm = strptime("20150617t182545Z", "%Y%m%dt%H%M%S%Z").unwrap();
        // format
        assert_eq!(strftime("%a %d/%m/%Y %H:%M:%S", &tm).unwrap(), "Sun 17/06/2015 18:25:45");
        assert_eq!(format!("{}", tm.rfc3339()), "2015-06-17T18:25:45Z");
        // store in Timespec and restore in Tm
        let ts = tm.to_timespec();
        let tm1 = at_utc(ts);
        // somehow they don't have the same identical structure :(
        // assert_eq!(tm, tm1);
        // test equally formatted
        let format_fn = |tm: &Tm| { format!("{}", tm.rfc3339()) };
        assert_eq!(format_fn(&tm), format_fn(&tm1));
    }
}
<commit_msg>Moved member functions not using self<commit_after>use regex::Regex;
use time::Timespec;

use time_utils::parse_time_str;

pub struct FileNameInfo<'a> {
    pub file_name: &'a str,
    pub info: Info
}

#[derive(Eq, PartialEq, Debug)]
pub struct Info {
    pub tp: Type,
    pub compressed: bool,
    pub encrypted: bool
}

#[derive(Eq, PartialEq, Debug)]
pub enum Type {
    Full{
        time: Timespec,
        volume_number: i32
    },
    FullManifest{
        time: Timespec,
        partial: bool
    },
    Inc{
        start_time: Timespec,
        end_time: Timespec,
        volume_number: i32
    },
    IncManifest{
        start_time: Timespec,
        end_time: Timespec,
        partial: bool
    },
    FullSig{
        time: Timespec,
        partial: bool
    },
    NewSig{
        start_time: Timespec,
        end_time: Timespec,
        partial: bool
    }
}

pub struct FileNameParser {
    full_vol_re: Regex,
    full_manifest_re: Regex,
    inc_vol_re: Regex,
    inc_manifest_re: Regex,
    full_sig_re: Regex,
    new_sig_re: Regex
}

impl<'a> FileNameInfo<'a> {
    pub fn new(name: &'a str, info: Info) -> Self {
        FileNameInfo {
            file_name: &name,
            info: info
        }
    }
}

impl Type {
    pub fn time_range(&self) -> (Timespec, Timespec) {
        match *self {
            Type::Full{ time, .. } |
                Type::FullSig{ time, .. } |
                Type::FullManifest{ time, .. } => (time, time),
            Type::Inc{ start_time, end_time, .. } |
                Type::IncManifest{ start_time, end_time, .. } |
                Type::NewSig{ start_time, end_time, .. } => (start_time, end_time)
        }
    }
}

impl FileNameParser {
    pub fn new() -> Self {
        FileNameParser {
            full_vol_re: Regex::new(r"^duplicity-full\.(?P<time>.*?)\.vol(?P<num>[0-9]+)\.difftar(?P<partial>(\.part))?($|\.)").unwrap(),
            full_manifest_re: Regex::new(r"^duplicity-full\.(?P<time>.*?)\.manifest(?P<partial>(\.part))?($|\.)").unwrap(),
            inc_vol_re: Regex::new(r"^duplicity-inc\.(?P<start_time>.*?)\.to\.(?P<end_time>.*?)\.vol(?P<num>[0-9]+)\.difftar($|\.)").unwrap(),
            inc_manifest_re: Regex::new(r"^duplicity-inc\.(?P<start_time>.*?)\.to\.(?P<end_time>.*?)\.manifest(?P<partial>(\.part))?(\.|$)").unwrap(),
            full_sig_re: Regex::new(r"^duplicity-full-signatures\.(?P<time>.*?)\.sigtar(?P<partial>(\.part))?(\.|$)").unwrap(),
            new_sig_re: Regex::new(r"^duplicity-new-signatures\.(?P<start_time>.*?)\.to\.(?P<end_time>.*?)\.sigtar(?P<partial>(\.part))?(\.|$)").unwrap(),
        }
    }

    pub fn parse(&self, filename: &str) -> Option<Info> {
        use std::ascii::AsciiExt;

        let lower_fname = filename.to_ascii_lowercase();
        let opt_type = self.check_full(&lower_fname)
                           .or(self.check_inc(&lower_fname))
                           .or(self.check_sig(&lower_fname));
        opt_type.map(|t| Info{ tp: t,
            compressed: is_compressed(lower_fname.as_ref()),
            encrypted: is_encrypted(lower_fname.as_ref())
        })
    }

    fn check_full(&self, filename: &str) -> Option<Type> {
        if let Some(captures) = self.full_vol_re.captures(filename) {
            let time = try_opt!(parse_time_str(captures.name("time").unwrap()));
            let vol_num = try_opt!(get_vol_num(captures.name("num").unwrap()));
            return Some(Type::Full{
                time: time,
                volume_number: vol_num
            });
        }
        if let Some(captures) = self.full_manifest_re.captures(filename) {
            let time = try_opt!(parse_time_str(captures.name("time").unwrap()));
            return Some(Type::FullManifest{
                time: time,
                partial: captures.name("partial").is_some()
            });
        }
        None
    }

    fn check_inc(&self, filename: &str) -> Option<Type> {
        if let Some(captures) = self.inc_vol_re.captures(filename) {
            let start_time = try_opt!(parse_time_str(captures.name("start_time").unwrap()));
            let end_time = try_opt!(parse_time_str(captures.name("end_time").unwrap()));
            let vol_num = try_opt!(get_vol_num(captures.name("num").unwrap()));
            Some(Type::Inc{
                start_time: start_time,
                end_time: end_time,
                volume_number: vol_num
            })
        }
        else if let Some(captures) = self.inc_manifest_re.captures(filename) {
            let start_time = try_opt!(parse_time_str(captures.name("start_time").unwrap()));
            let end_time = try_opt!(parse_time_str(captures.name("end_time").unwrap()));
            Some(Type::IncManifest{
                start_time: start_time,
                end_time: end_time,
                partial: captures.name("partial").is_some()
            })
        }
        else {
            None
        }
    }

    fn check_sig(&self, filename: &str) -> Option<Type> {
        if let Some(captures) = self.full_sig_re.captures(filename) {
            let time = try_opt!(parse_time_str(captures.name("time").unwrap()));
            Some(Type::FullSig{
                time: time,
                partial: captures.name("partial").is_some()
            })
        }
        else if let Some(captures) = self.new_sig_re.captures(filename) {
            let start_time = try_opt!(parse_time_str(captures.name("start_time").unwrap()));
            let end_time = try_opt!(parse_time_str(captures.name("end_time").unwrap()));
            Some(Type::NewSig{
                start_time: start_time,
                end_time: end_time,
                partial: captures.name("partial").is_some()
            })
        }
        else {
            None
        }
    }
}

fn get_vol_num(s: &str) -> Option<i32> {
    s.parse::<i32>().ok()
}

fn is_encrypted(s: &str) -> bool {
    s.ends_with(".gpg") || s.ends_with(".g")
}

fn is_compressed(s: &str) -> bool {
    s.ends_with(".gz") || s.ends_with(".z")
}

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

    #[test]
    fn parser_test() {
        let parser = FileNameParser::new();
        // invalid
        assert_eq!(parser.parse("invalid"), None);
        // full
        assert_eq!(parser.parse("duplicity-full.20150617T182545Z.vol1.difftar.gz"),
                   Some(Info{ tp: Type::Full{ time: parse_time_str("20150617t182545z").unwrap(),
                                              volume_number: 1 },
                              compressed: true,
                              encrypted: false }));
        // full manifest
        assert_eq!(parser.parse("duplicity-full.20150617T182545Z.manifest"),
                   Some(Info{ tp: Type::FullManifest{ time: parse_time_str("20150617t182545z").unwrap(),
                                                      partial: false },
                              compressed: false,
                              encrypted: false }));
        // inc
        assert_eq!(parser.parse("duplicity-inc.20150617T182629Z.to.20150617T182650Z.vol1.difftar.gz"),
                   Some(Info{ tp: Type::Inc{ start_time: parse_time_str("20150617t182629z").unwrap(),
                                             end_time: parse_time_str("20150617t182650z").unwrap(),
                                             volume_number: 1 },
                              compressed: true,
                              encrypted: false }));
        // inc manifest
        assert_eq!(parser.parse("duplicity-inc.20150617T182545Z.to.20150617T182629Z.manifest"),
                   Some(Info{ tp: Type::IncManifest{ start_time: parse_time_str("20150617t182545z").unwrap(),
                                                     end_time: parse_time_str("20150617t182629z").unwrap(),
                                                     partial: false },
                              compressed: false,
                              encrypted: false }));
        // new sig
        assert_eq!(parser.parse("duplicity-new-signatures.20150617T182545Z.to.20150617T182629Z.sigtar.gz"),
                   Some(Info{ tp: Type::NewSig{ start_time: parse_time_str("20150617t182545z").unwrap(),
                                                end_time: parse_time_str("20150617t182629z").unwrap(),
                                                partial: false },
                              compressed: true,
                              encrypted: false }));
        // full sig
        assert_eq!(parser.parse("duplicity-full-signatures.20150617T182545Z.sigtar.gz"),
                   Some(Info{ tp: Type::FullSig{ time: parse_time_str("20150617t182545z").unwrap(),
                                                 partial: false },
                              compressed: true,
                              encrypted: false }));
    }

    #[test]
    fn time_test() {
        use time::{strptime, strftime, at_utc, Tm};

        // parse
        let tm = strptime("20150617t182545Z", "%Y%m%dt%H%M%S%Z").unwrap();
        // format
        assert_eq!(strftime("%a %d/%m/%Y %H:%M:%S", &tm).unwrap(), "Sun 17/06/2015 18:25:45");
        assert_eq!(format!("{}", tm.rfc3339()), "2015-06-17T18:25:45Z");
        // store in Timespec and restore in Tm
        let ts = tm.to_timespec();
        let tm1 = at_utc(ts);
        // somehow they don't have the same identical structure :(
        // assert_eq!(tm, tm1);
        // test equally formatted
        let format_fn = |tm: &Tm| { format!("{}", tm.rfc3339()) };
        assert_eq!(format_fn(&tm), format_fn(&tm1));
    }
}
<|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/. */

#![feature(globs, macro_rules, phase, thread_local, link_args)]

#![allow(experimental, non_camel_case_types)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;

extern crate rustuv;

extern crate "plugins" as servo_plugins;
extern crate servo;

extern crate azure;
extern crate geom;
extern crate gfx;
extern crate glfw;
extern crate glfw_app;
extern crate js;
extern crate layers;
extern crate opengles;
extern crate png;
extern crate script;

extern crate "net" as servo_net;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;
extern crate style;
extern crate stb_image;

extern crate green;
extern crate native;
extern crate libc;
extern crate "url" as std_url;

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

pub mod browser;
pub mod command_line;
pub mod core;
pub mod eutil;
#[cfg(target_os="linux")] #[cfg(target_os="macos")]
pub mod mem;
pub mod request;
pub mod string;
pub mod task;
pub mod types;
pub mod urlrequest;

<commit_msg>use rust-encoding to correctly(?) set utf16 strings for cmdline args as expected<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/. */

#![feature(globs, macro_rules, phase, thread_local, link_args)]

#![allow(experimental, non_camel_case_types)]

#![feature(phase)]
#[phase(plugin, link)]
extern crate log;

extern crate rustuv;

extern crate "plugins" as servo_plugins;
extern crate servo;

extern crate azure;
extern crate geom;
extern crate gfx;
extern crate glfw;
extern crate glfw_app;
extern crate js;
extern crate layers;
extern crate opengles;
extern crate png;
extern crate script;

extern crate "net" as servo_net;
extern crate "msg" as servo_msg;
extern crate "util" as servo_util;
extern crate style;
extern crate stb_image;

extern crate green;
extern crate native;
extern crate libc;
extern crate "url" as std_url;

extern crate encoding;

#[cfg(target_os="macos")]
extern crate core_graphics;
#[cfg(target_os="macos")]
extern crate core_text;

pub mod browser;
pub mod command_line;
pub mod core;
pub mod eutil;
#[cfg(target_os="linux")] #[cfg(target_os="macos")]
pub mod mem;
pub mod request;
pub mod string;
pub mod task;
pub mod types;
pub mod urlrequest;

<|endoftext|>


<commit_before>use std::{fmt, mem, ptr, isize};
use std::num::Int;
use std::ops::{Index, IndexMut};
use alloc::heap;
use os::token::Token;

/// A preallocated chunk of memory for storing objects of the same type.
pub struct Slab<T> {
    // Chunk of memory
    mem: *mut Entry<T>,
    // Number of elements currently in the slab
    len: isize,
    // The total number of elements that the slab can hold
    cap: isize,
    // THe token offset
    off: usize,
    // Offset of the next available slot in the slab. Set to the slab's
    // capacity when the slab is full.
    nxt: isize,
    // The total number of slots that were initialized
    init: isize,
}

const MAX: usize = isize::MAX as usize;

// When Entry.nxt is set to this, the entry is in use
const IN_USE: isize = -1;

unsafe impl<T> Send for Slab<T> where T: Send {}

impl<T> Slab<T> {
    pub fn new(cap: usize) -> Slab<T> {
        Slab::new_starting_at(Token(0), cap)
    }

    pub fn new_starting_at(offset: Token, cap: usize) -> Slab<T> {
        assert!(cap <= MAX, "capacity too large");
        // TODO:
        // - Rename to with_capacity
        // - Use a power of 2 capacity
        // - Ensure that mem size is less than usize::MAX

        let size = cap.checked_mul(mem::size_of::<Entry<T>>())
            .expect("capacity overflow");

        let ptr = unsafe { heap::allocate(size, mem::min_align_of::<Entry<T>>()) };

        Slab {
            mem: ptr as *mut Entry<T>,
            cap: cap as isize,
            len: 0,
            off: offset.as_usize(),
            nxt: 0,
            init: 0,
        }
    }

    #[inline]
    pub fn count(&self) -> usize {
        self.len as usize
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        (self.cap - self.len) as usize
    }

    #[inline]
    pub fn has_remaining(&self) -> bool {
        self.remaining() > 0
    }

    #[inline]
    pub fn contains(&self, idx: Token) -> bool {
        if idx.as_usize() < self.off {
            return false;
        }

        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            let idx = idx as isize;

            if idx < self.init {
                return self.entry(idx).in_use();
            }
        }

        false
    }

    pub fn get(&self, idx: Token) -> Option<&T> {
        assert!(self.contains(idx), "slab does not contain token `{:?}`", idx);

        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            let idx = idx as isize;

            if idx < self.init {
                let entry = self.entry(idx);

                if entry.in_use() {
                    return Some(&entry.val);
                }
            }
        }

        None
    }

    pub fn get_mut(&mut self, idx: Token) -> Option<&mut T> {
        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            let idx = idx as isize;

            if idx < self.init {
                let mut entry = self.mut_entry(idx);

                if entry.in_use() {
                    return Some(&mut entry.val);
                }
            }
        }

        None
    }

    pub fn insert(&mut self, val: T) -> Result<Token, T> {
        let idx = self.nxt;

        if idx == self.init {
            // Using an uninitialized entry
            if idx == self.cap {
                // No more capacity
                debug!("slab out of capacity; cap={}", self.cap);
                return Err(val);
            }

            self.mut_entry(idx).put(val, true);

            self.init += 1;
            self.len = self.init;
            self.nxt = self.init;

            debug!("inserting into new slot; idx={}", idx);
        }
        else {
            self.len += 1;
            self.nxt = self.mut_entry(idx).put(val, false);

            debug!("inserting into reused slot; idx={}", idx);
        }

        Ok(self.idx_to_token(idx))
    }

    /// Releases the given slot
    pub fn remove(&mut self, idx: Token) -> Option<T> {
        debug!("removing value; idx={:?}", idx);

        // Cast to usize
        let idx = self.token_to_idx(idx);

        if idx > MAX {
            return None;
        }

        let idx = idx as isize;

        // Ensure index is within capacity of slab
        if idx >= self.init {
            return None;
        }

        let nxt = self.nxt;

        match self.mut_entry(idx).remove(nxt) {
            Some(v) => {
                self.nxt = idx;
                self.len -= 1;
                Some(v)
            }
            None => None
        }
    }

    #[inline]
    fn entry(&self, idx: isize) -> &Entry<T> {
        unsafe { &*self.mem.offset(idx) }
    }

    #[inline]
    fn mut_entry(&mut self, idx: isize) -> &mut Entry<T> {
        unsafe { &mut *self.mem.offset(idx) }
    }

    #[inline]
    fn validate_idx(&self, idx: usize) -> isize {
        if idx <= MAX {
            let idx = idx as isize;

            if idx < self.init {
                return idx;
            }
        }

        panic!("invalid index {} -- greater than capacity {}", idx, self.cap);
    }

    fn token_to_idx(&self, token: Token) -> usize {
        token.as_usize() - self.off
    }

    fn idx_to_token(&self, idx: isize) -> Token {
        Token(idx as usize + self.off)
    }
}

impl<T> Index<Token> for Slab<T> {
    type Output = T;

    fn index<'a>(&'a self, idx: &Token) -> &'a T {
        let idx = self.token_to_idx(*idx);
        let idx = self.validate_idx(idx);

        let e = self.entry(idx);

        if !e.in_use() {
            panic!("invalid index; idx={}", idx);
        }

        &e.val
    }
}

impl<T> IndexMut<Token> for Slab<T> {
    fn index_mut<'a>(&'a mut self, idx: &Token) -> &'a mut T {
        let idx = self.token_to_idx(*idx);
        let idx = self.validate_idx(idx);

        let e = self.mut_entry(idx);

        if !e.in_use() {
            panic!("invalid index; idx={}", idx);
        }

        &mut e.val
    }
}

impl<T> fmt::Debug for Slab<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Slab {{ len: {}, cap: {} }}", self.len, self.cap)
    }
}

#[unsafe_destructor]
impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        // TODO: check whether or not this is needed with intrinsics::needs_drop
        let mut i = 0;

        while i < self.init {
            self.mut_entry(i).release();
            i += 1;
        }

        let cap = self.cap as usize;
        let size = cap.checked_mul(mem::size_of::<Entry<T>>()).unwrap();
        unsafe { heap::deallocate(self.mem as *mut u8, size, mem::min_align_of::<Entry<T>>()) };
    }
}

// Holds the values in the slab.
struct Entry<T> {
    nxt: isize,
    val: T
}

impl<T> Entry<T> {
    #[inline]
    fn put(&mut self, val: T, init: bool) -> isize {
        assert!(init || self.nxt != IN_USE);

        let ret = self.nxt;

        unsafe { ptr::write(&mut self.val as *mut T, val); }
        self.nxt = IN_USE;

        // Could be uninitialized memory, but the caller (Slab) should guard
        // not use the return value in those cases.
        ret
    }

    fn remove(&mut self, nxt: isize) -> Option<T> {
        if self.in_use() {
            self.nxt = nxt;
            Some(unsafe { ptr::read(&self.val as *const T) })
        } else {
            None
        }
    }

    fn release(&mut self) {
        if self.in_use() {
            let _ = Some(unsafe { ptr::read(&self.val as *const T) });
        }
    }

    #[inline]
    fn in_use(&self) -> bool {
        self.nxt == IN_USE
    }
}

#[cfg(test)]
mod tests {
    use super::Slab;
    use {Token};

    #[test]
    fn test_insertion() {
        let mut slab = Slab::new(1);
        let token = slab.insert(10).ok().expect("Failed to insert");
        assert_eq!(slab[token], 10);
    }

    #[test]
    fn test_repeated_insertion() {
        let mut slab = Slab::new(10);

        for i in range(0, 10) {
            let token = slab.insert(i + 10).ok().expect("Failed to insert");
            assert_eq!(slab[token], i + 10);
        }

        slab.insert(20).err().expect("Inserted when full");
    }

    #[test]
    fn test_repeated_insertion_and_removal() {
        let mut slab = Slab::new(10);
        let mut tokens = vec![];

        for i in range(0, 10) {
            let token = slab.insert(i + 10).ok().expect("Failed to insert");
            tokens.push(token);
            assert_eq!(slab[token], i + 10);
        }

        for &i in tokens.iter() {
            slab.remove(i);
        }

        slab.insert(20).ok().expect("Failed to insert in newly empty slab");
    }

    #[test]
    fn test_insertion_when_full() {
        let mut slab = Slab::new(1);
        slab.insert(10).ok().expect("Failed to insert");
        slab.insert(10).err().expect("Inserted into a full slab");
    }

    #[test]
    fn test_removal_is_successful() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert(10).ok().expect("Failed to insert");
        slab.remove(t1);
        let t2 = slab.insert(20).ok().expect("Failed to insert");
        assert_eq!(slab[t2], 20);
    }

    #[test]
    fn test_mut_retrieval() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert("foo".to_string()).ok().expect("Failed to insert");

        slab[t1].push_str("bar");

        assert_eq!(slab[t1].as_slice(), "foobar");
    }

    #[test]
    #[should_fail]
    fn test_reusing_slots_1() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123).unwrap();
        let t1 = slab.insert(456).unwrap();

        assert!(slab.count() == 2);
        assert!(slab.remaining() == 14);

        slab.remove(t0);

        assert!(slab.count() == 1, "actual={}", slab.count());
        assert!(slab.remaining() == 15);

        slab.remove(t1);

        assert!(slab.count() == 0);
        assert!(slab.remaining() == 16);

        let _ = slab[t1];
    }

    #[test]
    fn test_reusing_slots_2() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123).unwrap();

        assert!(slab[t0] == 123);
        assert!(slab.remove(t0) == Some(123));

        let t0 = slab.insert(456).unwrap();

        assert!(slab[t0] == 456);

        let t1 = slab.insert(789).unwrap();

        assert!(slab[t0] == 456);
        assert!(slab[t1] == 789);

        assert!(slab.remove(t0).unwrap() == 456);
        assert!(slab.remove(t1).unwrap() == 789);

        assert!(slab.count() == 0);
    }

    #[test]
    #[should_fail]
    fn test_accessing_out_of_bounds() {
        let slab = Slab::<usize>::new(16);
        slab[Token(0)];
    }

    #[test]
    fn test_contains() {
        let mut slab = Slab::new_starting_at(Token(5),16);
        assert!(!slab.contains(Token(0)));

        let tok = slab.insert(111).unwrap();
        assert!(slab.contains(tok));
    }
}
<commit_msg>Add iterators for Slab<commit_after>use std::{fmt, mem, ptr, isize};
use std::num::Int;
use std::ops::{Index, IndexMut};
use alloc::heap;
use os::token::Token;

/// A preallocated chunk of memory for storing objects of the same type.
pub struct Slab<T> {
    // Chunk of memory
    mem: *mut Entry<T>,
    // Number of elements currently in the slab
    len: isize,
    // The total number of elements that the slab can hold
    cap: isize,
    // The token offset
    off: usize,
    // Offset of the next available slot in the slab. Set to the slab's
    // capacity when the slab is full.
    nxt: isize,
    // The total number of slots that were initialized
    init: isize,
}

const MAX: usize = isize::MAX as usize;

// When Entry.nxt is set to this, the entry is in use
const IN_USE: isize = -1;

unsafe impl<T> Send for Slab<T> where T: Send {}

impl<T> Slab<T> {
    pub fn new(cap: usize) -> Slab<T> {
        Slab::new_starting_at(Token(0), cap)
    }

    pub fn new_starting_at(offset: Token, cap: usize) -> Slab<T> {
        assert!(cap <= MAX, "capacity too large");
        // TODO:
        // - Rename to with_capacity
        // - Use a power of 2 capacity
        // - Ensure that mem size is less than usize::MAX

        let size = cap.checked_mul(mem::size_of::<Entry<T>>())
            .expect("capacity overflow");

        let ptr = unsafe { heap::allocate(size, mem::min_align_of::<Entry<T>>()) };

        Slab {
            mem: ptr as *mut Entry<T>,
            cap: cap as isize,
            len: 0,
            off: offset.as_usize(),
            nxt: 0,
            init: 0,
        }
    }

    #[inline]
    pub fn count(&self) -> usize {
        self.len as usize
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    #[inline]
    pub fn remaining(&self) -> usize {
        (self.cap - self.len) as usize
    }

    #[inline]
    pub fn has_remaining(&self) -> bool {
        self.remaining() > 0
    }

    #[inline]
    pub fn contains(&self, idx: Token) -> bool {
        if idx.as_usize() < self.off {
            return false;
        }

        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            let idx = idx as isize;

            if idx < self.init {
                return self.entry(idx).in_use();
            }
        }

        false
    }

    pub fn get(&self, idx: Token) -> Option<&T> {
        assert!(self.contains(idx), "slab does not contain token `{:?}`", idx);

        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            let idx = idx as isize;

            if idx < self.init {
                let entry = self.entry(idx);

                if entry.in_use() {
                    return Some(&entry.val);
                }
            }
        }

        None
    }

    pub fn get_mut(&mut self, idx: Token) -> Option<&mut T> {
        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            let idx = idx as isize;

            if idx < self.init {
                let mut entry = self.mut_entry(idx);

                if entry.in_use() {
                    return Some(&mut entry.val);
                }
            }
        }

        None
    }

    pub fn insert(&mut self, val: T) -> Result<Token, T> {
        let idx = self.nxt;

        if idx == self.init {
            // Using an uninitialized entry
            if idx == self.cap {
                // No more capacity
                debug!("slab out of capacity; cap={}", self.cap);
                return Err(val);
            }

            self.mut_entry(idx).put(val, true);

            self.init += 1;
            self.len = self.init;
            self.nxt = self.init;

            debug!("inserting into new slot; idx={}", idx);
        }
        else {
            self.len += 1;
            self.nxt = self.mut_entry(idx).put(val, false);

            debug!("inserting into reused slot; idx={}", idx);
        }

        Ok(self.idx_to_token(idx))
    }

    /// Releases the given slot
    pub fn remove(&mut self, idx: Token) -> Option<T> {
        debug!("removing value; idx={:?}", idx);

        // Cast to usize
        let idx = self.token_to_idx(idx);

        if idx > MAX {
            return None;
        }

        let idx = idx as isize;

        // Ensure index is within capacity of slab
        if idx >= self.init {
            return None;
        }

        let nxt = self.nxt;

        match self.mut_entry(idx).remove(nxt) {
            Some(v) => {
                self.nxt = idx;
                self.len -= 1;
                Some(v)
            }
            None => None
        }
    }

    pub fn iter(&self) -> SlabIter<T> {
        SlabIter {
            slab: self,
            cur_idx: 0,
            yielded: 0
        }
    }

    pub fn iter_mut(&mut self) -> SlabMutIter<T> {
        SlabMutIter {
            slab: self,
            cur_idx: 0,
            yielded: 0
        }
    }

    #[inline]
    fn entry(&self, idx: isize) -> &Entry<T> {
        unsafe { &*self.mem.offset(idx) }
    }

    #[inline]
    fn mut_entry(&mut self, idx: isize) -> &mut Entry<T> {
        unsafe { &mut *self.mem.offset(idx) }
    }

    #[inline]
    fn validate_idx(&self, idx: usize) -> isize {
        if idx <= MAX {
            let idx = idx as isize;

            if idx < self.init {
                return idx;
            }
        }

        panic!("invalid index {} -- greater than capacity {}", idx, self.cap);
    }

    fn token_to_idx(&self, token: Token) -> usize {
        token.as_usize() - self.off
    }

    fn idx_to_token(&self, idx: isize) -> Token {
        Token(idx as usize + self.off)
    }
}

impl<T> Index<Token> for Slab<T> {
    type Output = T;

    fn index<'a>(&'a self, idx: &Token) -> &'a T {
        let idx = self.token_to_idx(*idx);
        let idx = self.validate_idx(idx);

        let e = self.entry(idx);

        if !e.in_use() {
            panic!("invalid index; idx={}", idx);
        }

        &e.val
    }
}

impl<T> IndexMut<Token> for Slab<T> {
    fn index_mut<'a>(&'a mut self, idx: &Token) -> &'a mut T {
        let idx = self.token_to_idx(*idx);
        let idx = self.validate_idx(idx);

        let e = self.mut_entry(idx);

        if !e.in_use() {
            panic!("invalid index; idx={}", idx);
        }

        &mut e.val
    }
}

impl<T> fmt::Debug for Slab<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Slab {{ len: {}, cap: {} }}", self.len, self.cap)
    }
}

#[unsafe_destructor]
impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        // TODO: check whether or not this is needed with intrinsics::needs_drop
        let mut i = 0;

        while i < self.init {
            self.mut_entry(i).release();
            i += 1;
        }

        let cap = self.cap as usize;
        let size = cap.checked_mul(mem::size_of::<Entry<T>>()).unwrap();
        unsafe { heap::deallocate(self.mem as *mut u8, size, mem::min_align_of::<Entry<T>>()) };
    }
}

// Holds the values in the slab.
struct Entry<T> {
    nxt: isize,
    val: T
}

impl<T> Entry<T> {
    #[inline]
    fn put(&mut self, val: T, init: bool) -> isize {
        assert!(init || self.nxt != IN_USE);

        let ret = self.nxt;

        unsafe { ptr::write(&mut self.val as *mut T, val); }
        self.nxt = IN_USE;

        // Could be uninitialized memory, but the caller (Slab) should guard
        // not use the return value in those cases.
        ret
    }

    fn remove(&mut self, nxt: isize) -> Option<T> {
        if self.in_use() {
            self.nxt = nxt;
            Some(unsafe { ptr::read(&self.val as *const T) })
        } else {
            None
        }
    }

    fn release(&mut self) {
        if self.in_use() {
            let _ = Some(unsafe { ptr::read(&self.val as *const T) });
        }
    }

    #[inline]
    fn in_use(&self) -> bool {
        self.nxt == IN_USE
    }
}

pub struct SlabIter<'a, T: 'a> {
    slab: &'a Slab<T>,
    cur_idx: isize,
    yielded: isize
}

impl <'a, T> Iterator for SlabIter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        while self.yielded < self.slab.len {
            let entry = self.slab.entry(self.cur_idx);
            self.cur_idx += 1;
            if entry.in_use() {
                self.yielded += 1;
                return Some(&entry.val);
            }
        }
        None
    }
}

pub struct SlabMutIter<'a, T: 'a> {
    slab: &'a mut Slab<T>,
    cur_idx: isize,
    yielded: isize
}

impl <'a, T> Iterator for SlabMutIter<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<&'a mut T> {
        while self.yielded < self.slab.len {
            let entry = unsafe { &mut *self.slab.mem.offset(self.cur_idx) };
            self.cur_idx += 1;
            if entry.in_use() {
                self.yielded += 1;
                return Some(&mut entry.val);
            }
        }
        None
    }
}

#[cfg(test)]
mod tests {
    use super::Slab;
    use {Token};

    #[test]
    fn test_insertion() {
        let mut slab = Slab::new(1);
        let token = slab.insert(10).ok().expect("Failed to insert");
        assert_eq!(slab[token], 10);
    }

    #[test]
    fn test_repeated_insertion() {
        let mut slab = Slab::new(10);

        for i in range(0, 10) {
            let token = slab.insert(i + 10).ok().expect("Failed to insert");
            assert_eq!(slab[token], i + 10);
        }

        slab.insert(20).err().expect("Inserted when full");
    }

    #[test]
    fn test_repeated_insertion_and_removal() {
        let mut slab = Slab::new(10);
        let mut tokens = vec![];

        for i in range(0, 10) {
            let token = slab.insert(i + 10).ok().expect("Failed to insert");
            tokens.push(token);
            assert_eq!(slab[token], i + 10);
        }

        for &i in tokens.iter() {
            slab.remove(i);
        }

        slab.insert(20).ok().expect("Failed to insert in newly empty slab");
    }

    #[test]
    fn test_insertion_when_full() {
        let mut slab = Slab::new(1);
        slab.insert(10).ok().expect("Failed to insert");
        slab.insert(10).err().expect("Inserted into a full slab");
    }

    #[test]
    fn test_removal_is_successful() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert(10).ok().expect("Failed to insert");
        slab.remove(t1);
        let t2 = slab.insert(20).ok().expect("Failed to insert");
        assert_eq!(slab[t2], 20);
    }

    #[test]
    fn test_mut_retrieval() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert("foo".to_string()).ok().expect("Failed to insert");

        slab[t1].push_str("bar");

        assert_eq!(slab[t1].as_slice(), "foobar");
    }

    #[test]
    #[should_fail]
    fn test_reusing_slots_1() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123).unwrap();
        let t1 = slab.insert(456).unwrap();

        assert!(slab.count() == 2);
        assert!(slab.remaining() == 14);

        slab.remove(t0);

        assert!(slab.count() == 1, "actual={}", slab.count());
        assert!(slab.remaining() == 15);

        slab.remove(t1);

        assert!(slab.count() == 0);
        assert!(slab.remaining() == 16);

        let _ = slab[t1];
    }

    #[test]
    fn test_reusing_slots_2() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123).unwrap();

        assert!(slab[t0] == 123);
        assert!(slab.remove(t0) == Some(123));

        let t0 = slab.insert(456).unwrap();

        assert!(slab[t0] == 456);

        let t1 = slab.insert(789).unwrap();

        assert!(slab[t0] == 456);
        assert!(slab[t1] == 789);

        assert!(slab.remove(t0).unwrap() == 456);
        assert!(slab.remove(t1).unwrap() == 789);

        assert!(slab.count() == 0);
    }

    #[test]
    #[should_fail]
    fn test_accessing_out_of_bounds() {
        let slab = Slab::<usize>::new(16);
        slab[Token(0)];
    }

    #[test]
    fn test_contains() {
        let mut slab = Slab::new_starting_at(Token(5),16);
        assert!(!slab.contains(Token(0)));

        let tok = slab.insert(111).unwrap();
        assert!(slab.contains(tok));
    }

    #[test]
    fn test_iter() {
        let mut slab: Slab<u32> = Slab::new_starting_at(Token(0), 4);
        for i in range(0, 4) {
            slab.insert(i).unwrap();
        }
        assert_eq!(slab.iter().map(|r| *r).collect(), vec![0, 1, 2, 3]);
        slab.remove(Token(1));
        assert_eq!(slab.iter().map(|r| *r).collect(), vec![0, 2, 3]);
    }

    #[test]
    fn test_iter_mut() {
        let mut slab: Slab<u32> = Slab::new_starting_at(Token(0), 4);
        for i in range(0, 4) {
            slab.insert(i).unwrap();
        }
        for e in slab.iter_mut() {
            *e = *e + 1;
        }

        assert_eq!(slab.iter().map(|r| *r).collect(), vec![1, 2, 3, 4]);
        slab.remove(Token(2));
        for e in slab.iter_mut() {
            *e = *e + 1;
        }
        assert_eq!(slab.iter().map(|r| *r).collect(), vec![2, 3, 5]);
    }
}
<|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::ast::{SyntaxError, SourceLocation};

pub struct ErrorLoggerIterator<I>(pub I);

impl<T, I: Iterator<Result<T, SyntaxError>>> Iterator<T> for ErrorLoggerIterator<I> {
    fn next(&mut self) -> Option<T> {
        let ErrorLoggerIterator(ref mut this) = *self;
        loop {
            match this.next() {
                Some(Ok(v)) => return Some(v),
                Some(Err(error)) => log_css_error(error.location, format!("{:?}", error.reason)),
                None => return None,
            }
        }
   }
}

// FIXME: go back to `()` instead of `bool` after upgrading Rust
// past 898669c4e203ae91e2048fb6c0f8591c867bccc6
// Using bool is a work-around for https://github.com/mozilla/rust/issues/13322
local_data_key!(silence_errors: bool)

pub fn log_css_error(location: SourceLocation, message: &str) {
    // TODO eventually this will got into a "web console" or something.
    if silence_errors.get().is_none() {
        error!("{:u}:{:u} {:s}", location.line, location.column, message)
    }
}

pub fn with_errors_silenced<T>(f: || -> T) -> T {
    silence_errors.replace(Some(true));
    let result = f();
    silence_errors.replace(None);
    result
}
<commit_msg>Do not log CSS parse errors to stderr by default.<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::ast::{SyntaxError, SourceLocation};

pub struct ErrorLoggerIterator<I>(pub I);

impl<T, I: Iterator<Result<T, SyntaxError>>> Iterator<T> for ErrorLoggerIterator<I> {
    fn next(&mut self) -> Option<T> {
        let ErrorLoggerIterator(ref mut this) = *self;
        loop {
            match this.next() {
                Some(Ok(v)) => return Some(v),
                Some(Err(error)) => log_css_error(error.location, format!("{:?}", error.reason)),
                None => return None,
            }
        }
   }
}

// FIXME: go back to `()` instead of `bool` after upgrading Rust
// past 898669c4e203ae91e2048fb6c0f8591c867bccc6
// Using bool is a work-around for https://github.com/mozilla/rust/issues/13322
local_data_key!(silence_errors: bool)

/// Defaults to a no-op.
/// Set a `RUST_LOG=style::errors` environment variable
/// to log CSS parse errors to stderr.
pub fn log_css_error(location: SourceLocation, message: &str) {
    // TODO eventually this will got into a "web console" or something.
    if silence_errors.get().is_none() {
        info!("{:u}:{:u} {:s}", location.line, location.column, message)
    }
}

pub fn with_errors_silenced<T>(f: || -> T) -> T {
    silence_errors.replace(Some(true));
    let result = f();
    silence_errors.replace(None);
    result
}
<|endoftext|>


<commit_before>use vec_shift::Shift;
use std::str::FromStr;
use std::error::Error as StdError;
use utils::parse_quotes;

/// Defines how an operation on an `Args` method failed.
#[derive(Debug)]
pub enum Error {
    /// "END-OF-STRING", more precisely, there isn't anything to parse anymore.
    Eos,
    /// A parsing operation failed; the error in it can be of any returned from the `FromStr`
    /// trait.
    Parse(Box<StdError>),
}

type Result<T> = ::std::result::Result<T, Error>;

#[derive(Debug, Clone)]
pub struct Args {
    delimiter: String,
    delimiter_split: Vec<String>,
}

impl Args {
    pub fn new(message: &str, delimiter: &str) -> Self {
        Args {
            delimiter: delimiter.to_string(),
            delimiter_split: message.split(delimiter).map(|s| s.to_string()).collect(),
        }
    }

    /// Removes the first element, parses it to a specific type if necessary, returns.
    pub fn single<T: FromStr>(&mut self) -> Result<T>
        where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        self.delimiter_split
            .shift()
            .ok_or(Error::Eos)?
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`single`], but doesn't remove the element.
    ///
    /// [`single`]: #method.single
    pub fn single_n<T: FromStr>(&mut self) -> Result<T>
        where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        self.delimiter_split
            .get(0)
            .ok_or(Error::Eos)?
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Skips if there's a first element, but also returns it.
    pub fn skip(&mut self) -> Option<String> { self.delimiter_split.shift() }

    /// Like [`skip`], but allows for multiple at once.
    ///
    /// [`skip`]: #method.skip
    pub fn skip_for(&mut self, i: u32) -> Option<Vec<String>> {
        let mut vec = Vec::with_capacity(i as usize);

        for _ in 0..i {
            vec.push(match self.delimiter_split.shift() {
                Some(x) => x,
                None => return None,
            });
        }

        Some(vec)
    }

    /// Like [`single`], but takes quotes into account.
    ///
    /// [`single`]: #method.single
    pub fn single_quoted<T: FromStr>(&mut self) -> Result<T>
        where T::Err: StdError + 'static {
        parse_quotes(&self.delimiter_split.shift().ok_or(Error::Eos)?)
            .remove(0)
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`single_quoted`], but doesn't remove the element.
    ///
    /// [`single_quoted`]: #method.single_quoted
    pub fn single_quoted_n<T: FromStr>(&mut self) -> Result<T>
        where T::Err: StdError + 'static {
        parse_quotes(&self.delimiter_split.get(0).ok_or(Error::Eos)?)
            .remove(0)
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`list`], but takes quotes into account.
    ///
    /// [`list`]: #method.list
    pub fn multiple_quoted<T: FromStr>(self) -> Result<Vec<T>>
        where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        parse_quotes(&self.delimiter_split.join(&self.delimiter))
            .into_iter()
            .map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e))))
            .collect()
    }

    /// Empty outs the internal vector while parsing (if necessary) and returning them
    pub fn list<T: FromStr>(self) -> Result<Vec<T>>
        where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        self.delimiter_split
            .into_iter()
            .map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e))))
            .collect()
    }

    /// This method is just `internal_vector.join(delimiter)`
    pub fn full(&self) -> String { self.delimiter_split.join(&self.delimiter) }
}

impl ::std::ops::Deref for Args {
    type Target = [String];

    fn deref(&self) -> &Self::Target { &self.delimiter_split }
}
<commit_msg>Make args empty when no arguments are passed. (#143)<commit_after>use vec_shift::Shift;
use std::str::FromStr;
use std::error::Error as StdError;
use utils::parse_quotes;

/// Defines how an operation on an `Args` method failed.
#[derive(Debug)]
pub enum Error {
    /// "END-OF-STRING", more precisely, there isn't anything to parse anymore.
    Eos,
    /// A parsing operation failed; the error in it can be of any returned from the `FromStr`
    /// trait.
    Parse(Box<StdError>),
}

type Result<T> = ::std::result::Result<T, Error>;

#[derive(Debug, Clone)]
pub struct Args {
    delimiter: String,
    delimiter_split: Vec<String>,
}

impl Args {
    pub fn new(message: &str, delimiter: &str) -> Self {
        let split = if message.trim().is_empty() {
            Vec::new()
        } else {
            message.split(delimiter).map(|s| s.to_string()).collect()
        };

        Args {
            delimiter: delimiter.to_string(),
            delimiter_split: split,
        }
    }

    /// Removes the first element, parses it to a specific type if necessary, returns.
    pub fn single<T: FromStr>(&mut self) -> Result<T>
        where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        self.delimiter_split
            .shift()
            .ok_or(Error::Eos)?
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`single`], but doesn't remove the element.
    ///
    /// [`single`]: #method.single
    pub fn single_n<T: FromStr>(&mut self) -> Result<T>
        where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        self.delimiter_split
            .get(0)
            .ok_or(Error::Eos)?
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Skips if there's a first element, but also returns it.
    pub fn skip(&mut self) -> Option<String> { self.delimiter_split.shift() }

    /// Like [`skip`], but allows for multiple at once.
    ///
    /// [`skip`]: #method.skip
    pub fn skip_for(&mut self, i: u32) -> Option<Vec<String>> {
        let mut vec = Vec::with_capacity(i as usize);

        for _ in 0..i {
            vec.push(match self.delimiter_split.shift() {
                Some(x) => x,
                None => return None,
            });
        }

        Some(vec)
    }

    /// Like [`single`], but takes quotes into account.
    ///
    /// [`single`]: #method.single
    pub fn single_quoted<T: FromStr>(&mut self) -> Result<T>
        where T::Err: StdError + 'static {
        parse_quotes(&self.delimiter_split.shift().ok_or(Error::Eos)?)
            .remove(0)
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`single_quoted`], but doesn't remove the element.
    ///
    /// [`single_quoted`]: #method.single_quoted
    pub fn single_quoted_n<T: FromStr>(&mut self) -> Result<T>
        where T::Err: StdError + 'static {
        parse_quotes(&self.delimiter_split.get(0).ok_or(Error::Eos)?)
            .remove(0)
            .parse::<T>()
            .map_err(|e| Error::Parse(Box::new(e)))
    }

    /// Like [`list`], but takes quotes into account.
    ///
    /// [`list`]: #method.list
    pub fn multiple_quoted<T: FromStr>(self) -> Result<Vec<T>>
        where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        parse_quotes(&self.delimiter_split.join(&self.delimiter))
            .into_iter()
            .map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e))))
            .collect()
    }

    /// Empty outs the internal vector while parsing (if necessary) and returning them
    pub fn list<T: FromStr>(self) -> Result<Vec<T>>
        where T::Err: StdError + 'static {
        if self.delimiter_split.is_empty() {
            return Err(Error::Eos);
        }

        self.delimiter_split
            .into_iter()
            .map(|s| s.parse::<T>().map_err(|e| Error::Parse(Box::new(e))))
            .collect()
    }

    /// This method is just `internal_vector.join(delimiter)`
    pub fn full(&self) -> String { self.delimiter_split.join(&self.delimiter) }
}

impl ::std::ops::Deref for Args {
    type Target = [String];

    fn deref(&self) -> &Self::Target { &self.delimiter_split }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use rustc_serialize::Decodable;
use rustc_serialize::base64::{
    FromBase64,
    ToBase64,
};
use rustc_serialize::json::{
    self,
    Decoder,
    Json,
};
use error::Error;
use BASE_CONFIG;

#[derive(Debug, Default, PartialEq)]
pub struct Claims {
    pub reg: Registered,
    private: BTreeMap<String, Json>,
}

#[derive(Debug, Default, PartialEq, RustcDecodable, RustcEncodable)]
pub struct Registered {
    pub iss: Option<String>,
    pub sub: Option<String>,
    pub aud: Option<String>,
    pub exp: Option<u64>,
    pub nbf: Option<u64>,
    pub iat: Option<u64>,
    pub jti: Option<String>,
}

impl Claims {
    pub fn new(reg: Registered) -> Claims {
        Claims {
            reg: reg,
            private: BTreeMap::new(),
        }
    }

    pub fn parse(raw: &str) -> Result<Claims, Error> {
        let data = try!(raw.from_base64());
        let s = try!(String::from_utf8(data));
        let tree = match try!(Json::from_str(&*s)) {
            Json::Object(x) => x,
            _ => return Err(Error::Format),
        };

        const FIELDS: [&'static str; 7] = [
            "iss", "sub", "aud",
            "exp", "nbf", "iat",
            "jti",
        ];

        let (reg, pri): (BTreeMap<_, _>, BTreeMap<_, _>) = tree.into_iter()
            .partition(|&(ref key, _)| {
                FIELDS.iter().any(|f| f == key)
            });

        let mut decoder = Decoder::new(Json::Object(reg));
        let reg_claims: Registered = try!(Decodable::decode(&mut decoder));

        Ok(Claims{
            reg: reg_claims,
            private: pri,
        })
    }

    pub fn encode(&self) -> Result<String, Error> {
        // Extremely inefficient
        let s = try!(json::encode(&self.reg));
        let mut tree = match try!(Json::from_str(&*s)) {
            Json::Object(x) => x,
            _ => return Err(Error::Format),
        };

        tree.extend(self.private.clone());

        let s = try!(json::encode(&tree));
        let enc = (&*s).as_bytes().to_base64(BASE_CONFIG);
        Ok(enc)
    }
}

#[cfg(test)]
mod tests {
    use std::default::Default;
    use claims::Claims;

    #[test]
    fn parse() {
        let enc = "ew0KICAiaXNzIjogIm1pa2t5YW5nLmNvbSIsDQogICJleHAiOiAxMzAyMzE5MTAwLA0KICAibmFtZSI6ICJNaWNoYWVsIFlhbmciLA0KICAiYWRtaW4iOiB0cnVlDQp9";
        let claims = Claims::parse(enc).unwrap();

        assert_eq!(claims.reg.iss.unwrap(), "mikkyang.com");
        assert_eq!(claims.reg.exp.unwrap(), 1302319100);
    }

    #[test]
    fn roundtrip() {
        let mut claims: Claims = Default::default();
        claims.reg.iss = Some("mikkyang.com".into());
        claims.reg.exp = Some(1302319100);
        let enc = claims.encode().unwrap();
        assert_eq!(claims, Claims::parse(&*enc).unwrap());
    }
}
<commit_msg>Make private claims pub<commit_after>use std::collections::BTreeMap;
use rustc_serialize::Decodable;
use rustc_serialize::base64::{
    FromBase64,
    ToBase64,
};
use rustc_serialize::json::{
    self,
    Decoder,
    Json,
};
use error::Error;
use BASE_CONFIG;

#[derive(Debug, Default, PartialEq)]
pub struct Claims {
    pub reg: Registered,
    pub private: BTreeMap<String, Json>,
}

#[derive(Debug, Default, PartialEq, RustcDecodable, RustcEncodable)]
pub struct Registered {
    pub iss: Option<String>,
    pub sub: Option<String>,
    pub aud: Option<String>,
    pub exp: Option<u64>,
    pub nbf: Option<u64>,
    pub iat: Option<u64>,
    pub jti: Option<String>,
}

impl Claims {
    pub fn new(reg: Registered) -> Claims {
        Claims {
            reg: reg,
            private: BTreeMap::new(),
        }
    }

    pub fn parse(raw: &str) -> Result<Claims, Error> {
        let data = try!(raw.from_base64());
        let s = try!(String::from_utf8(data));
        let tree = match try!(Json::from_str(&*s)) {
            Json::Object(x) => x,
            _ => return Err(Error::Format),
        };

        const FIELDS: [&'static str; 7] = [
            "iss", "sub", "aud",
            "exp", "nbf", "iat",
            "jti",
        ];

        let (reg, pri): (BTreeMap<_, _>, BTreeMap<_, _>) = tree.into_iter()
            .partition(|&(ref key, _)| {
                FIELDS.iter().any(|f| f == key)
            });

        let mut decoder = Decoder::new(Json::Object(reg));
        let reg_claims: Registered = try!(Decodable::decode(&mut decoder));

        Ok(Claims{
            reg: reg_claims,
            private: pri,
        })
    }

    pub fn encode(&self) -> Result<String, Error> {
        // Extremely inefficient
        let s = try!(json::encode(&self.reg));
        let mut tree = match try!(Json::from_str(&*s)) {
            Json::Object(x) => x,
            _ => return Err(Error::Format),
        };

        tree.extend(self.private.clone());

        let s = try!(json::encode(&tree));
        let enc = (&*s).as_bytes().to_base64(BASE_CONFIG);
        Ok(enc)
    }
}

#[cfg(test)]
mod tests {
    use std::default::Default;
    use claims::Claims;

    #[test]
    fn parse() {
        let enc = "ew0KICAiaXNzIjogIm1pa2t5YW5nLmNvbSIsDQogICJleHAiOiAxMzAyMzE5MTAwLA0KICAibmFtZSI6ICJNaWNoYWVsIFlhbmciLA0KICAiYWRtaW4iOiB0cnVlDQp9";
        let claims = Claims::parse(enc).unwrap();

        assert_eq!(claims.reg.iss.unwrap(), "mikkyang.com");
        assert_eq!(claims.reg.exp.unwrap(), 1302319100);
    }

    #[test]
    fn roundtrip() {
        let mut claims: Claims = Default::default();
        claims.reg.iss = Some("mikkyang.com".into());
        claims.reg.exp = Some(1302319100);
        let enc = claims.encode().unwrap();
        assert_eq!(claims, Claims::parse(&*enc).unwrap());
    }
}
<|endoftext|>