<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! An "interner" is a data structure that associates values with usize tags and
//! allows bidirectional lookup; i.e. given a value, one can easily find the
//! type, and vice versa.

use hygiene::SyntaxContext;

use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Ident {
    pub name: Symbol,
    pub ctxt: SyntaxContext,
}

impl Ident {
    pub const fn with_empty_ctxt(name: Symbol) -> Ident {
        Ident { name: name, ctxt: SyntaxContext::empty() }
    }

    /// Maps a string to an identifier with an empty syntax context.
    pub fn from_str(string: &str) -> Ident {
        Ident::with_empty_ctxt(Symbol::intern(string))
    }

    pub fn modern(self) -> Ident {
        Ident { name: self.name, ctxt: self.ctxt.modern() }
    }
}

impl fmt::Debug for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{:?}", self.name, self.ctxt)
    }
}

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

impl Encodable for Ident {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if self.ctxt.modern() == SyntaxContext::empty() {
            s.emit_str(&self.name.as_str())
        } else { // FIXME(jseyfried) intercrate hygiene
            let mut string = "#".to_owned();
            string.push_str(&self.name.as_str());
            s.emit_str(&string)
        }
    }
}

impl Decodable for Ident {
    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
        let string = d.read_str()?;
        Ok(if !string.starts_with('#') {
            Ident::from_str(&string)
        } else { // FIXME(jseyfried) intercrate hygiene
            Ident::with_empty_ctxt(Symbol::gensym(&string[1..]))
        })
    }
}

/// A symbol is an interned or gensymed string.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Symbol(u32);

// The interner in thread-local, so `Symbol` shouldn't move between threads.
impl !Send for Symbol { }

impl Symbol {
    /// Maps a string to its interned representation.
    pub fn intern(string: &str) -> Self {
        with_interner(|interner| interner.intern(string))
    }

    pub fn interned(self) -> Self {
        with_interner(|interner| interner.interned(self))
    }

    /// gensym's a new usize, using the current interner.
    pub fn gensym(string: &str) -> Self {
        with_interner(|interner| interner.gensym(string))
    }

    pub fn gensymed(self) -> Self {
        with_interner(|interner| interner.gensymed(self))
    }

    pub fn as_str(self) -> InternedString {
        with_interner(|interner| unsafe {
            InternedString {
                string: ::std::mem::transmute::<&str, &str>(interner.get(self))
            }
        })
    }

    pub fn as_u32(self) -> u32 {
        self.0
    }
}

impl fmt::Debug for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}({})", self, self.0)
    }
}

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

impl Encodable for Symbol {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(&self.as_str())
    }
}

impl Decodable for Symbol {
    fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
        Ok(Symbol::intern(&d.read_str()?))
    }
}

impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
    fn eq(&self, other: &T) -> bool {
        self.as_str() == other.deref()
    }
}

#[derive(Default)]
pub struct Interner {
    names: HashMap<Box<str>, Symbol>,
    strings: Vec<Box<str>>,
    gensyms: Vec<Symbol>,
}

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

    fn prefill(init: &[&str]) -> Self {
        let mut this = Interner::new();
        for &string in init {
            this.intern(string);
        }
        this
    }

    pub fn intern(&mut self, string: &str) -> Symbol {
        if let Some(&name) = self.names.get(string) {
            return name;
        }

        let name = Symbol(self.strings.len() as u32);
        let string = string.to_string().into_boxed_str();
        self.strings.push(string.clone());
        self.names.insert(string, name);
        name
    }

    pub fn interned(&self, symbol: Symbol) -> Symbol {
        if (symbol.0 as usize) < self.strings.len() {
            symbol
        } else {
            self.interned(self.gensyms[(!0 - symbol.0) as usize])
        }
    }

    fn gensym(&mut self, string: &str) -> Symbol {
        let symbol = self.intern(string);
        self.gensymed(symbol)
    }

    fn gensymed(&mut self, symbol: Symbol) -> Symbol {
        self.gensyms.push(symbol);
        Symbol(!0 - self.gensyms.len() as u32 + 1)
    }

    pub fn get(&self, symbol: Symbol) -> &str {
        match self.strings.get(symbol.0 as usize) {
            Some(ref string) => string,
            None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
        }
    }
}

// In this macro, there is the requirement that the name (the number) must be monotonically
// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
// except starting from the next number instead of zero.
macro_rules! declare_keywords {(
    $( ($index: expr, $konst: ident, $string: expr) )*
) => {
    pub mod keywords {
        use super::{Symbol, Ident};
        #[derive(Clone, Copy, PartialEq, Eq)]
        pub struct Keyword {
            ident: Ident,
        }
        impl Keyword {
            #[inline] pub fn ident(self) -> Ident { self.ident }
            #[inline] pub fn name(self) -> Symbol { self.ident.name }
        }
        $(
            #[allow(non_upper_case_globals)]
            pub const $konst: Keyword = Keyword {
                ident: Ident::with_empty_ctxt(super::Symbol($index))
            };
        )*
    }

    impl Interner {
        fn fresh() -> Self {
            Interner::prefill(&[$($string,)*])
        }
    }
}}

// NB: leaving holes in the ident table is bad! a different ident will get
// interned with the id from the hole, but it will be between the min and max
// of the reserved words, and thus tagged as "reserved".
// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order.
declare_keywords! {
    // Invalid identifier
    (0,  Invalid,        "")

    // Strict keywords used in the language.
    (1,  As,             "as")
    (2,  Box,            "box")
    (3,  Break,          "break")
    (4,  Const,          "const")
    (5,  Continue,       "continue")
    (6,  Crate,          "crate")
    (7,  Else,           "else")
    (8,  Enum,           "enum")
    (9,  Extern,         "extern")
    (10, False,          "false")
    (11, Fn,             "fn")
    (12, For,            "for")
    (13, If,             "if")
    (14, Impl,           "impl")
    (15, In,             "in")
    (16, Let,            "let")
    (17, Loop,           "loop")
    (18, Match,          "match")
    (19, Mod,            "mod")
    (20, Move,           "move")
    (21, Mut,            "mut")
    (22, Pub,            "pub")
    (23, Ref,            "ref")
    (24, Return,         "return")
    (25, SelfValue,      "self")
    (26, SelfType,       "Self")
    (27, Static,         "static")
    (28, Struct,         "struct")
    (29, Super,          "super")
    (30, Trait,          "trait")
    (31, True,           "true")
    (32, Type,           "type")
    (33, Unsafe,         "unsafe")
    (34, Use,            "use")
    (35, Where,          "where")
    (36, While,          "while")

    // Keywords reserved for future use.
    (37, Abstract,       "abstract")
    (38, Alignof,        "alignof")
    (39, Become,         "become")
    (40, Do,             "do")
    (41, Final,          "final")
    (42, Macro,          "macro")
    (43, Offsetof,       "offsetof")
    (44, Override,       "override")
    (45, Priv,           "priv")
    (46, Proc,           "proc")
    (47, Pure,           "pure")
    (48, Sizeof,         "sizeof")
    (49, Typeof,         "typeof")
    (50, Unsized,        "unsized")
    (51, Virtual,        "virtual")
    (52, Yield,          "yield")

    // Weak keywords, have special meaning only in specific contexts.
    (53, Default,        "default")
    (54, StaticLifetime, "'static")
    (55, Union,          "union")
    (56, Catch,          "catch")

    // A virtual keyword that resolves to the crate root when used in a lexical scope.
    (57, CrateRoot, "{{root}}")
}

// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
    thread_local!(static INTERNER: RefCell<Interner> = {
        RefCell::new(Interner::fresh())
    });
    INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
}

/// Represents a string stored in the thread-local interner. Because the
/// interner lives for the life of the thread, this can be safely treated as an
/// immortal string, as long as it never crosses between threads.
///
/// FIXME(pcwalton): You must be careful about what you do in the destructors
/// of objects stored in TLS, because they may run after the interner is
/// destroyed. In particular, they must not access string contents. This can
/// be fixed in the future by just leaking all strings until thread death
/// somehow.
#[derive(Clone, Hash, PartialOrd, Eq, Ord)]
pub struct InternedString {
    string: &'static str,
}

impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
    fn as_ref(&self) -> &U {
        self.string.as_ref()
    }
}

impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
    fn eq(&self, other: &T) -> bool {
        self.string == other.deref()
    }
}

impl ::std::cmp::PartialEq<InternedString> for str {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl ::std::cmp::PartialEq<InternedString> for String {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl !Send for InternedString { }

impl ::std::ops::Deref for InternedString {
    type Target = str;
    fn deref(&self) -> &str { self.string }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.string, f)
    }
}

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

impl Decodable for InternedString {
    fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
        Ok(Symbol::intern(&d.read_str()?).as_str())
    }
}

impl Encodable for InternedString {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(self.string)
    }
}

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

    #[test]
    fn interner_tests() {
        let mut i: Interner = Interner::new();
        // first one is zero:
        assert_eq!(i.intern("dog"), Symbol(0));
        // re-use gets the same entry:
        assert_eq!(i.intern ("dog"), Symbol(0));
        // different string gets a different #:
        assert_eq!(i.intern("cat"), Symbol(1));
        assert_eq!(i.intern("cat"), Symbol(1));
        // dog is still at zero
        assert_eq!(i.intern("dog"), Symbol(0));
        assert_eq!(i.gensym("zebra"), Symbol(4294967295));
        // gensym of same string gets new number :
        assert_eq!(i.gensym("zebra"), Symbol(4294967294));
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym("dog"), Symbol(4294967293));
    }
}
<commit_msg>syntax_pos::Symbol should not implement Sync<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! An "interner" is a data structure that associates values with usize tags and
//! allows bidirectional lookup; i.e. given a value, one can easily find the
//! type, and vice versa.

use hygiene::SyntaxContext;

use serialize::{Decodable, Decoder, Encodable, Encoder};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;

#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Ident {
    pub name: Symbol,
    pub ctxt: SyntaxContext,
}

impl Ident {
    pub const fn with_empty_ctxt(name: Symbol) -> Ident {
        Ident { name: name, ctxt: SyntaxContext::empty() }
    }

    /// Maps a string to an identifier with an empty syntax context.
    pub fn from_str(string: &str) -> Ident {
        Ident::with_empty_ctxt(Symbol::intern(string))
    }

    pub fn modern(self) -> Ident {
        Ident { name: self.name, ctxt: self.ctxt.modern() }
    }
}

impl fmt::Debug for Ident {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{:?}", self.name, self.ctxt)
    }
}

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

impl Encodable for Ident {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        if self.ctxt.modern() == SyntaxContext::empty() {
            s.emit_str(&self.name.as_str())
        } else { // FIXME(jseyfried) intercrate hygiene
            let mut string = "#".to_owned();
            string.push_str(&self.name.as_str());
            s.emit_str(&string)
        }
    }
}

impl Decodable for Ident {
    fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
        let string = d.read_str()?;
        Ok(if !string.starts_with('#') {
            Ident::from_str(&string)
        } else { // FIXME(jseyfried) intercrate hygiene
            Ident::with_empty_ctxt(Symbol::gensym(&string[1..]))
        })
    }
}

/// A symbol is an interned or gensymed string.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Symbol(u32);

// The interner in thread-local, so `Symbol` shouldn't move between threads.
impl !Send for Symbol { }
impl !Sync for Symbol { }

impl Symbol {
    /// Maps a string to its interned representation.
    pub fn intern(string: &str) -> Self {
        with_interner(|interner| interner.intern(string))
    }

    pub fn interned(self) -> Self {
        with_interner(|interner| interner.interned(self))
    }

    /// gensym's a new usize, using the current interner.
    pub fn gensym(string: &str) -> Self {
        with_interner(|interner| interner.gensym(string))
    }

    pub fn gensymed(self) -> Self {
        with_interner(|interner| interner.gensymed(self))
    }

    pub fn as_str(self) -> InternedString {
        with_interner(|interner| unsafe {
            InternedString {
                string: ::std::mem::transmute::<&str, &str>(interner.get(self))
            }
        })
    }

    pub fn as_u32(self) -> u32 {
        self.0
    }
}

impl fmt::Debug for Symbol {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}({})", self, self.0)
    }
}

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

impl Encodable for Symbol {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(&self.as_str())
    }
}

impl Decodable for Symbol {
    fn decode<D: Decoder>(d: &mut D) -> Result<Symbol, D::Error> {
        Ok(Symbol::intern(&d.read_str()?))
    }
}

impl<T: ::std::ops::Deref<Target=str>> PartialEq<T> for Symbol {
    fn eq(&self, other: &T) -> bool {
        self.as_str() == other.deref()
    }
}

#[derive(Default)]
pub struct Interner {
    names: HashMap<Box<str>, Symbol>,
    strings: Vec<Box<str>>,
    gensyms: Vec<Symbol>,
}

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

    fn prefill(init: &[&str]) -> Self {
        let mut this = Interner::new();
        for &string in init {
            this.intern(string);
        }
        this
    }

    pub fn intern(&mut self, string: &str) -> Symbol {
        if let Some(&name) = self.names.get(string) {
            return name;
        }

        let name = Symbol(self.strings.len() as u32);
        let string = string.to_string().into_boxed_str();
        self.strings.push(string.clone());
        self.names.insert(string, name);
        name
    }

    pub fn interned(&self, symbol: Symbol) -> Symbol {
        if (symbol.0 as usize) < self.strings.len() {
            symbol
        } else {
            self.interned(self.gensyms[(!0 - symbol.0) as usize])
        }
    }

    fn gensym(&mut self, string: &str) -> Symbol {
        let symbol = self.intern(string);
        self.gensymed(symbol)
    }

    fn gensymed(&mut self, symbol: Symbol) -> Symbol {
        self.gensyms.push(symbol);
        Symbol(!0 - self.gensyms.len() as u32 + 1)
    }

    pub fn get(&self, symbol: Symbol) -> &str {
        match self.strings.get(symbol.0 as usize) {
            Some(ref string) => string,
            None => self.get(self.gensyms[(!0 - symbol.0) as usize]),
        }
    }
}

// In this macro, there is the requirement that the name (the number) must be monotonically
// increasing by one in the special identifiers, starting at 0; the same holds for the keywords,
// except starting from the next number instead of zero.
macro_rules! declare_keywords {(
    $( ($index: expr, $konst: ident, $string: expr) )*
) => {
    pub mod keywords {
        use super::{Symbol, Ident};
        #[derive(Clone, Copy, PartialEq, Eq)]
        pub struct Keyword {
            ident: Ident,
        }
        impl Keyword {
            #[inline] pub fn ident(self) -> Ident { self.ident }
            #[inline] pub fn name(self) -> Symbol { self.ident.name }
        }
        $(
            #[allow(non_upper_case_globals)]
            pub const $konst: Keyword = Keyword {
                ident: Ident::with_empty_ctxt(super::Symbol($index))
            };
        )*
    }

    impl Interner {
        fn fresh() -> Self {
            Interner::prefill(&[$($string,)*])
        }
    }
}}

// NB: leaving holes in the ident table is bad! a different ident will get
// interned with the id from the hole, but it will be between the min and max
// of the reserved words, and thus tagged as "reserved".
// After modifying this list adjust `is_strict_keyword`/`is_reserved_keyword`,
// this should be rarely necessary though if the keywords are kept in alphabetic order.
declare_keywords! {
    // Invalid identifier
    (0,  Invalid,        "")

    // Strict keywords used in the language.
    (1,  As,             "as")
    (2,  Box,            "box")
    (3,  Break,          "break")
    (4,  Const,          "const")
    (5,  Continue,       "continue")
    (6,  Crate,          "crate")
    (7,  Else,           "else")
    (8,  Enum,           "enum")
    (9,  Extern,         "extern")
    (10, False,          "false")
    (11, Fn,             "fn")
    (12, For,            "for")
    (13, If,             "if")
    (14, Impl,           "impl")
    (15, In,             "in")
    (16, Let,            "let")
    (17, Loop,           "loop")
    (18, Match,          "match")
    (19, Mod,            "mod")
    (20, Move,           "move")
    (21, Mut,            "mut")
    (22, Pub,            "pub")
    (23, Ref,            "ref")
    (24, Return,         "return")
    (25, SelfValue,      "self")
    (26, SelfType,       "Self")
    (27, Static,         "static")
    (28, Struct,         "struct")
    (29, Super,          "super")
    (30, Trait,          "trait")
    (31, True,           "true")
    (32, Type,           "type")
    (33, Unsafe,         "unsafe")
    (34, Use,            "use")
    (35, Where,          "where")
    (36, While,          "while")

    // Keywords reserved for future use.
    (37, Abstract,       "abstract")
    (38, Alignof,        "alignof")
    (39, Become,         "become")
    (40, Do,             "do")
    (41, Final,          "final")
    (42, Macro,          "macro")
    (43, Offsetof,       "offsetof")
    (44, Override,       "override")
    (45, Priv,           "priv")
    (46, Proc,           "proc")
    (47, Pure,           "pure")
    (48, Sizeof,         "sizeof")
    (49, Typeof,         "typeof")
    (50, Unsized,        "unsized")
    (51, Virtual,        "virtual")
    (52, Yield,          "yield")

    // Weak keywords, have special meaning only in specific contexts.
    (53, Default,        "default")
    (54, StaticLifetime, "'static")
    (55, Union,          "union")
    (56, Catch,          "catch")

    // A virtual keyword that resolves to the crate root when used in a lexical scope.
    (57, CrateRoot, "{{root}}")
}

// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
    thread_local!(static INTERNER: RefCell<Interner> = {
        RefCell::new(Interner::fresh())
    });
    INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
}

/// Represents a string stored in the thread-local interner. Because the
/// interner lives for the life of the thread, this can be safely treated as an
/// immortal string, as long as it never crosses between threads.
///
/// FIXME(pcwalton): You must be careful about what you do in the destructors
/// of objects stored in TLS, because they may run after the interner is
/// destroyed. In particular, they must not access string contents. This can
/// be fixed in the future by just leaking all strings until thread death
/// somehow.
#[derive(Clone, Hash, PartialOrd, Eq, Ord)]
pub struct InternedString {
    string: &'static str,
}

impl<U: ?Sized> ::std::convert::AsRef<U> for InternedString where str: ::std::convert::AsRef<U> {
    fn as_ref(&self) -> &U {
        self.string.as_ref()
    }
}

impl<T: ::std::ops::Deref<Target = str>> ::std::cmp::PartialEq<T> for InternedString {
    fn eq(&self, other: &T) -> bool {
        self.string == other.deref()
    }
}

impl ::std::cmp::PartialEq<InternedString> for str {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a str {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl ::std::cmp::PartialEq<InternedString> for String {
    fn eq(&self, other: &InternedString) -> bool {
        self == other.string
    }
}

impl<'a> ::std::cmp::PartialEq<InternedString> for &'a String {
    fn eq(&self, other: &InternedString) -> bool {
        *self == other.string
    }
}

impl !Send for InternedString { }

impl ::std::ops::Deref for InternedString {
    type Target = str;
    fn deref(&self) -> &str { self.string }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.string, f)
    }
}

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

impl Decodable for InternedString {
    fn decode<D: Decoder>(d: &mut D) -> Result<InternedString, D::Error> {
        Ok(Symbol::intern(&d.read_str()?).as_str())
    }
}

impl Encodable for InternedString {
    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        s.emit_str(self.string)
    }
}

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

    #[test]
    fn interner_tests() {
        let mut i: Interner = Interner::new();
        // first one is zero:
        assert_eq!(i.intern("dog"), Symbol(0));
        // re-use gets the same entry:
        assert_eq!(i.intern ("dog"), Symbol(0));
        // different string gets a different #:
        assert_eq!(i.intern("cat"), Symbol(1));
        assert_eq!(i.intern("cat"), Symbol(1));
        // dog is still at zero
        assert_eq!(i.intern("dog"), Symbol(0));
        assert_eq!(i.gensym("zebra"), Symbol(4294967295));
        // gensym of same string gets new number :
        assert_eq!(i.gensym("zebra"), Symbol(4294967294));
        // gensym of *existing* string gets new number:
        assert_eq!(i.gensym("dog"), Symbol(4294967293));
    }
}
<|endoftext|>


<commit_before><commit_msg>Finishing up chapter 17.<commit_after><|endoftext|>


<commit_before><commit_msg>Update comm::protocol to rethinkdb/rethinkdb@02d6796<commit_after><|endoftext|>


<commit_before>use lyon::path;
use lyon::path_builder::BaseBuilder;
use lyon::path_iterator::PathIterator;
use lyon::tessellation;
use lyon::tessellation::math;
use lyon::tessellation::path_stroke;
use lyon::tessellation::geometry_builder;

use super::{Point, Vertex};
use GameError;
use GameResult;

pub type Buffer = geometry_builder::VertexBuffers<Vertex>;

// Not used anywhere?  Not sure what vickenty was planning for this.
// pub struct ConstantUV {
//     uv: [f32; 2],
// }

// impl geometry_builder::VertexConstructor<math::Point, Vertex> for ConstantUV {
//     fn new_vertex(&mut self, input: math::Point) -> Vertex {
//         Vertex {
//             pos: [input.x, input.y],
//             uv: self.uv.clone(),
//         }
//     }
// }

pub struct ScreenUV;

impl geometry_builder::VertexConstructor<math::Point, Vertex> for ScreenUV {
    fn new_vertex(&mut self, input: math::Point) -> Vertex {
        Vertex {
            pos: [input.x, input.y],
            uv: [input.x, input.y],
        }
    }
}

fn build_path(points: &[Point], closed: bool) -> path::Path {
    let mut path_builder = path::Builder::with_capacity(points.len());
    path_builder.move_to(math::point(points[0].x, points[0].y));

    for p in &points[1..] {
        path_builder.line_to(math::point(p.x, p.y));
    }

    if closed {
        path_builder.close();
    }

    path_builder.build()
}

type BuffersBuilder<'a> = geometry_builder::BuffersBuilder<'a, Vertex, math::Point, ScreenUV>;

fn build_geometry<F>(f: F) -> GameResult<Buffer>
    where F: for<'a> FnOnce(&mut BuffersBuilder<'a>)
                            -> Result<tessellation::geometry_builder::Count, ()>
{
    let mut buffers = geometry_builder::VertexBuffers::new();
    {
        let mut builder = geometry_builder::BuffersBuilder::new(&mut buffers, ScreenUV);
        if let Err(()) = f(&mut builder) {
            return Err(GameError::RenderError(String::from("geometry tessellation failed")));
        }
    }
    Ok(buffers)
}

pub fn build_line(points: &[Point], line_width: f32) -> GameResult<Buffer> {
    let path = build_path(points, false);
    let opts = path_stroke::StrokeOptions::stroke_width(line_width);
    let mut tessellator = path_stroke::StrokeTessellator::new();
    build_geometry(|builder| {
                       tessellator.tessellate(path.path_iter().flattened(0.5), &opts, builder)
                   })
}

/// Build a closed polygon.  Identical to build_line but closes the path,
/// which makes sure the two endpoints actually line up.
pub fn build_polygon(points: &[Point], line_width: f32) -> GameResult<Buffer> {

    let path = build_path(points, true);
    let opts = path_stroke::StrokeOptions::stroke_width(line_width);
    let mut tessellator = path_stroke::StrokeTessellator::new();
    build_geometry(|builder| {
                       tessellator.tessellate(path.path_iter().flattened(0.5), &opts, builder)
                   })
}

// This would be ideal but really should be left until we can get around
// to updating lyon.
// pub fn build_polygon_fill(points: &[Point]) -> GameResult<Buffer> {

//     let path = build_path(points, true);
//     let opts = path_fill::FillOptions::default();
//     let mut tessellator = path_fill::FillTessellator::new();
//     build_geometry(|builder| {
//         tessellator.tessellate_events(path.path_iter()
//                                    .flattened(0.5),
//                                &opts,
//                                builder)
//     })
// }

pub fn build_ellipse_fill(point: Point, r1: f32, r2: f32, segments: u32) -> GameResult<Buffer> {
    build_geometry(|builder| {
                       Ok(tessellation::basic_shapes::tessellate_ellipsis(math::point(point.x,
                                                                                point.y),
                                                                          math::point(r1, r2),
                                                                          segments,
                                                                          builder))
                   })
}
<commit_msg>Remove old unused code.<commit_after>use lyon::path;
use lyon::path_builder::BaseBuilder;
use lyon::path_iterator::PathIterator;
use lyon::tessellation;
use lyon::tessellation::math;
use lyon::tessellation::path_stroke;
use lyon::tessellation::geometry_builder;

use super::{Point, Vertex};
use GameError;
use GameResult;

pub type Buffer = geometry_builder::VertexBuffers<Vertex>;

pub struct ScreenUV;

impl geometry_builder::VertexConstructor<math::Point, Vertex> for ScreenUV {
    fn new_vertex(&mut self, input: math::Point) -> Vertex {
        Vertex {
            pos: [input.x, input.y],
            uv: [input.x, input.y],
        }
    }
}

fn build_path(points: &[Point], closed: bool) -> path::Path {
    let mut path_builder = path::Builder::with_capacity(points.len());
    path_builder.move_to(math::point(points[0].x, points[0].y));

    for p in &points[1..] {
        path_builder.line_to(math::point(p.x, p.y));
    }

    if closed {
        path_builder.close();
    }

    path_builder.build()
}

type BuffersBuilder<'a> = geometry_builder::BuffersBuilder<'a, Vertex, math::Point, ScreenUV>;

fn build_geometry<F>(f: F) -> GameResult<Buffer>
    where F: for<'a> FnOnce(&mut BuffersBuilder<'a>)
                            -> Result<tessellation::geometry_builder::Count, ()>
{
    let mut buffers = geometry_builder::VertexBuffers::new();
    {
        let mut builder = geometry_builder::BuffersBuilder::new(&mut buffers, ScreenUV);
        if let Err(()) = f(&mut builder) {
            return Err(GameError::RenderError(String::from("geometry tessellation failed")));
        }
    }
    Ok(buffers)
}

pub fn build_line(points: &[Point], line_width: f32) -> GameResult<Buffer> {
    let path = build_path(points, false);
    let opts = path_stroke::StrokeOptions::stroke_width(line_width);
    let mut tessellator = path_stroke::StrokeTessellator::new();
    build_geometry(|builder| {
                       tessellator.tessellate(path.path_iter().flattened(0.5), &opts, builder)
                   })
}

/// Build a closed polygon.  Identical to build_line but closes the path,
/// which makes sure the two endpoints actually line up.
pub fn build_polygon(points: &[Point], line_width: f32) -> GameResult<Buffer> {

    let path = build_path(points, true);
    let opts = path_stroke::StrokeOptions::stroke_width(line_width);
    let mut tessellator = path_stroke::StrokeTessellator::new();
    build_geometry(|builder| {
                       tessellator.tessellate(path.path_iter().flattened(0.5), &opts, builder)
                   })
}

// This would be ideal but really should be left until we can get around
// to updating lyon.
// pub fn build_polygon_fill(points: &[Point]) -> GameResult<Buffer> {

//     let path = build_path(points, true);
//     let opts = path_fill::FillOptions::default();
//     let mut tessellator = path_fill::FillTessellator::new();
//     build_geometry(|builder| {
//         tessellator.tessellate_events(path.path_iter()
//                                    .flattened(0.5),
//                                &opts,
//                                builder)
//     })
// }

pub fn build_ellipse_fill(point: Point, r1: f32, r2: f32, segments: u32) -> GameResult<Buffer> {
    build_geometry(|builder| {
                       Ok(tessellation::basic_shapes::tessellate_ellipsis(math::point(point.x,
                                                                                point.y),
                                                                          math::point(r1, r2),
                                                                          segments,
                                                                          builder))
                   })
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};

pub fn target() -> Result<Target, String> {
    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Em,
                vec!["-s".to_string(),
                     "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
                     "-s".to_string(),
                     "ABORTING_MALLOC=0".to_string()]);

    let opts = TargetOptions {
        dynamic_linking: false,
        executables: true,
        exe_suffix: ".js".to_string(),
        linker_is_gnu: true,
        allow_asm: false,
        obj_is_bitcode: true,
        is_like_emscripten: true,
        max_atomic_width: Some(32),
        post_link_args: args,
        target_family: Some("unix".to_string()),
        codegen_backend: "emscripten".to_string(),
        .. Default::default()
    };
    Ok(Target {
        llvm_target: "asmjs-unknown-emscripten".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "emscripten".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
        arch: "asmjs".to_string(),
        linker_flavor: LinkerFlavor::Em,
        options: opts,
    })
}
<commit_msg>Rollup merge of #51875 - badboy:emscripten-no-wasm, r=nikomatsakis<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use super::{LinkArgs, LinkerFlavor, Target, TargetOptions};

pub fn target() -> Result<Target, String> {
    let mut args = LinkArgs::new();
    args.insert(LinkerFlavor::Em,
                vec!["-s".to_string(),
                     "ERROR_ON_UNDEFINED_SYMBOLS=1".to_string(),
                     "-s".to_string(),
                     "ABORTING_MALLOC=0".to_string(),
                     "-s".to_string(),
                     "WASM=0".to_string()]);

    let opts = TargetOptions {
        dynamic_linking: false,
        executables: true,
        exe_suffix: ".js".to_string(),
        linker_is_gnu: true,
        allow_asm: false,
        obj_is_bitcode: true,
        is_like_emscripten: true,
        max_atomic_width: Some(32),
        post_link_args: args,
        target_family: Some("unix".to_string()),
        codegen_backend: "emscripten".to_string(),
        .. Default::default()
    };
    Ok(Target {
        llvm_target: "asmjs-unknown-emscripten".to_string(),
        target_endian: "little".to_string(),
        target_pointer_width: "32".to_string(),
        target_c_int_width: "32".to_string(),
        target_os: "emscripten".to_string(),
        target_env: "".to_string(),
        target_vendor: "unknown".to_string(),
        data_layout: "e-p:32:32-i64:64-v128:32:128-n32-S128".to_string(),
        arch: "asmjs".to_string(),
        linker_flavor: LinkerFlavor::Em,
        options: opts,
    })
}
<|endoftext|>


<commit_before>//! A single-producer, single-consumer, futures-aware channel

use std::any::Any;
use std::error::Error;
use std::fmt;

mod bounded;
mod unbounded;
mod queue;

pub use self::bounded::{channel, Sender, Receiver};
pub use self::unbounded::{unbounded, UnboundedSender, UnboundedReceiver};

/// Error type for sending, used when the receiving end of the channel is
/// dropped
pub struct SendError<T>(T);

impl<T> fmt::Debug for SendError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_tuple("SendError")
            .field(&"...")
            .finish()
    }
}

impl<T> fmt::Display for SendError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "send failed because receiver is gone")
    }
}

impl<T> Error for SendError<T>
    where T: Any
{
    fn description(&self) -> &str {
        "send failed because receiver is gone"
    }
}

impl<T> SendError<T> {
    /// Returns the message that was attempted to be sent but failed.
    pub fn into_inner(self) -> T {
        self.0
    }
}

<commit_msg>Add more docs to spsc<commit_after>//! A single-producer, single-consumer, futures-aware channel
//!
//! A channel can be used as a communication primitive between tasks running on
//! `futures-rs` executors. Channel creation provides `Receiver` and `Sender`
//! handles. `Receiver` implements `Stream` and allows a task to read values
//! out of the channel. If there is no message to read from the channel, the
//! curernt task will be notified when a new value is sent. `Sender` implements
//! the `Sink` trait and allows a task to send messages into the channel. If
//! the channel is at capacity, then send will be rejected and the task will be
//! notified when additional capacity is available.
//!
//! # Disconnection
//!
//! When all `Sender` handles have been dropped, it is no longer possible to
//! send values into the channel. This is considered the termination event of
//! the stream. As such, `Sender::poll` will return `Ok(Ready(None))`.
//!
//! If the receiver handle is dropped, then messages can no longer be read out
//! of the channel. In this case, a `send` will result in an error.
//!
//! # Clean Shutdown
//!
//! If the `Receiver` is simply dropped, then it is possible for there to be
//! messages still in the channel that will not be processed. As such, it is
//! usually desirable to perform a "clean" shutdown. To do this, the receiver
//! will first call `close`, which will prevent any further messages to be sent
//! into the channel. Then, the receiver consumes the channel to completion, at
//! which point the receiver can be dropped.

use std::any::Any;
use std::error::Error;
use std::fmt;

mod bounded;
mod unbounded;
mod queue;

pub use self::bounded::{channel, Sender, Receiver};
pub use self::unbounded::{unbounded, UnboundedSender, UnboundedReceiver};

/// Error type for sending, used when the receiving end of the channel is
/// dropped
pub struct SendError<T>(T);

impl<T> fmt::Debug for SendError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_tuple("SendError")
            .field(&"...")
            .finish()
    }
}

impl<T> fmt::Display for SendError<T> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "send failed because receiver is gone")
    }
}

impl<T> Error for SendError<T>
    where T: Any
{
    fn description(&self) -> &str {
        "send failed because receiver is gone"
    }
}

impl<T> SendError<T> {
    /// Returns the message that was attempted to be sent but failed.
    pub fn into_inner(self) -> T {
        self.0
    }
}

<|endoftext|>


<commit_before><commit_msg>Add test<commit_after>macro_rules! e( //~ ERROR unknown macro variable `nonexistent`
    ($inp:ident) => (
        $nonexistent
    );
)

fn main() {
    e!(foo);
}
<|endoftext|>


<commit_before><commit_msg>FEAT(core)<commit_after><|endoftext|>


<commit_before>use std::io::UserRWX;
use std::io::fs;
use std::io::process::{Command,ProcessOutput};
use std::io::{File,Truncate,Write};
use std::os;

pub fn mkdir(path: &Path)  {
    match fs::mkdir_recursive(path, UserRWX) {
        Err(_) => {},
        Ok(_) => {},
    }
}

pub fn read(path: &Path) -> Result<String, String> {
    match File::open(path) {
        Err(_) => Err(format!("couldn't open {}", path.display())),
        Ok(mut file) => match file.read_to_str() {
            Err(_) => Err(format!("couldn't read {}", path.display())),
            Ok(string) => Ok(string),
        }
    }
}

pub fn run(prefix: &str, id: &str, src: &str) -> Result<String, String> {
    let cwd = os::getcwd();
    let out_dir = cwd.join(format!("bin/{}/{}", prefix, id));

    let mut cmd = Command::new("rustc");
    cmd.cwd(&Path::new(format!("examples/{}/{}", prefix, id)));
    cmd.arg(format!("{}.rs", src));
    cmd.arg("--out-dir");
    cmd.arg(out_dir);

    match cmd.output() {
        Err(_) => return Err(format!("couldn't find rustc")),
        Ok(p) => if !p.status.success() {
            return Ok(String::from_utf8(p.error).unwrap());
        },
    }

    let executable = Path::new(format!("./bin/{}/{}/{}", prefix, id, src));

    match Command::new(&executable).output() {
        Err(_) => Err(format!("couldn't find {}", executable.display())),
        Ok(ProcessOutput { error: error, output: output, status: status }) => {
            let mut s = String::from_utf8(output).unwrap();
            if !status.success() {
                s.push_str(String::from_utf8(error).unwrap().as_slice());
            }

            Ok(s)
        }
    }
}

pub fn write(path: &Path, string: &str) -> Result<(), String> {
    match File::open_mode(path, Truncate, Write) {
        Err(_) => Err(format!("couldn't open {}", path.display())),
        Ok(mut file) => match file.write_str(string) {
            Err(_) => Err(format!("couldn't write {}", path.display())),
            Ok(_) => Ok(()),
        }
    }
}
<commit_msg>fix method name: read_to_str should be read_to_string<commit_after>use std::io::UserRWX;
use std::io::fs;
use std::io::process::{Command,ProcessOutput};
use std::io::{File,Truncate,Write};
use std::os;

pub fn mkdir(path: &Path)  {
    match fs::mkdir_recursive(path, UserRWX) {
        Err(_) => {},
        Ok(_) => {},
    }
}

pub fn read(path: &Path) -> Result<String, String> {
    match File::open(path) {
        Err(_) => Err(format!("couldn't open {}", path.display())),
        Ok(mut file) => match file.read_to_string() {
            Err(_) => Err(format!("couldn't read {}", path.display())),
            Ok(string) => Ok(string),
        }
    }
}

pub fn run(prefix: &str, id: &str, src: &str) -> Result<String, String> {
    let cwd = os::getcwd();
    let out_dir = cwd.join(format!("bin/{}/{}", prefix, id));

    let mut cmd = Command::new("rustc");
    cmd.cwd(&Path::new(format!("examples/{}/{}", prefix, id)));
    cmd.arg(format!("{}.rs", src));
    cmd.arg("--out-dir");
    cmd.arg(out_dir);

    match cmd.output() {
        Err(_) => return Err(format!("couldn't find rustc")),
        Ok(p) => if !p.status.success() {
            return Ok(String::from_utf8(p.error).unwrap());
        },
    }

    let executable = Path::new(format!("./bin/{}/{}/{}", prefix, id, src));

    match Command::new(&executable).output() {
        Err(_) => Err(format!("couldn't find {}", executable.display())),
        Ok(ProcessOutput { error: error, output: output, status: status }) => {
            let mut s = String::from_utf8(output).unwrap();
            if !status.success() {
                s.push_str(String::from_utf8(error).unwrap().as_slice());
            }

            Ok(s)
        }
    }
}

pub fn write(path: &Path, string: &str) -> Result<(), String> {
    match File::open_mode(path, Truncate, Write) {
        Err(_) => Err(format!("couldn't open {}", path.display())),
        Ok(mut file) => match file.write_str(string) {
            Err(_) => Err(format!("couldn't write {}", path.display())),
            Ok(_) => Ok(()),
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Added corner-cases for polygons<commit_after><|endoftext|>


<commit_before><commit_msg>Add a HTTPResponse struct, with response codes enum<commit_after><|endoftext|>


<commit_before><commit_msg>Add debug output<commit_after><|endoftext|>


<commit_before><commit_msg>Allowing acquisition thread to initiate stop.<commit_after><|endoftext|>


<commit_before><commit_msg>Simplify first dirty impl.<commit_after><|endoftext|>


<commit_before><commit_msg>Enter key now toggles the OSD<commit_after><|endoftext|>


<commit_before><commit_msg>Fix a use-after-free in the readiness queue<commit_after><|endoftext|>


<commit_before><commit_msg>Add a run-pass test for recursive copyable stack closures.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Ensures that it's legal to create a recursive stack closure as long as
// its environment is copyable

struct R<'self> {
    // This struct is needed to create the
    // otherwise infinite type of a fn that
    // accepts itself as argument:
    c: &'self fn:Copy(&R, uint) -> uint
}

fn main() {
    // Stupid version of fibonacci.
    let fib: &fn:Copy(&R, uint) -> uint = |fib, x| {
        if x == 0 || x == 1 {
            x
        } else {
            (fib.c)(fib, x-1) + (fib.c)(fib, x-2)
        }
    };
    assert!(fib(&R { c: fib }, 7) == 13);
}
<|endoftext|>


<commit_before><commit_msg>Add more error handling functions<commit_after><|endoftext|>


<commit_before>#![cfg(feature = "s3")]

extern crate env_logger;
#[macro_use]
extern crate log;
extern crate time;

#[macro_use]
extern crate rusoto;

use std::io::Read;
use std::fs::File;
use std::env::var;
use rusoto::{DefaultCredentialsProvider, Region};
use rusoto::s3::{S3Helper, S3Client, ListObjectsRequest, HeadObjectRequest, CreateBucketRequest};

fn test_bucket() -> String {
    match var("S3_TEST_BUCKET") {
        Ok(val) => val.to_owned(),
        Err(_) => "rusototester".to_owned()
    }
}

fn test_bucket_region() -> Region {
    match var("S3_TEST_BUCKET_REGION") {
        Ok(val) => val.parse().unwrap(),
        Err(_) => "us-west-2".parse().unwrap()
    }
}

#[test]
fn list_buckets_tests() {
    let _ = env_logger::init();
    let s3 = S3Helper::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
    let response = s3.list_buckets().unwrap();
    info!("Got list of buckets: {:?}", response);
    for q in response.buckets {
        info!("Existing bucket: {:?}", q.name);
    }
}

#[test]
fn object_lifecycle_test() {
    // PUT an object
    let s3 = S3Helper::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());

    let mut f = File::open("tests/sample-data/no_credentials").unwrap();
    let mut contents : Vec<u8> = Vec::new();
    match f.read_to_end(&mut contents) {
        Err(why) => panic!("Error opening file to send to S3: {}", why),
        Ok(_) => {
            s3.put_object(&test_bucket(), "no_credentials", &contents).unwrap();
        }
    }

    let client = S3Client::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
    // HEAD the object that was PUT
    let size_req = HeadObjectRequest{
      bucket: test_bucket(),
      key: "no_credentials".to_string(),
      ..Default::default()
    };

    println!("{:?}", client.head_object(&size_req).unwrap());

    // GET the object
    s3.get_object(&test_bucket(), "no_credentials").unwrap();

    // DELETE the object
    s3.delete_object(&test_bucket(), "no_credentials").unwrap();
}

#[test]
fn create_bucket_in_useast1_and_use_immediately() {
    let s3 = S3Client::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
    let create_bucket_request = CreateBucketRequest{
        bucket: "rusoto_foo_bucket".to_string(),
        ..Default::default()
    };
    let bucket_creation_result = s3.create_bucket(&create_bucket_request).unwrap();
    println!("bucket created: {:?}", bucket_creation_result);

    let mut f = File::open("tests/sample-data/no_credentials").unwrap();
    let mut contents : Vec<u8> = Vec::new();
    match f.read_to_end(&mut contents) {
        Err(why) => panic!("Error opening file to send to S3: {}", why),
        Ok(_) => {
            let s3_helper = S3Helper::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
            let put_response = s3_helper.put_object("rusoto_foo_bucket", "no_credentials", &contents).unwrap();
            println!("put_response is {:?}", put_response);
        }
    }

}

#[test]
fn put_and_fetch_timestamp_named_object_test() {
    let s3 = S3Helper::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
    let mut f = File::open("tests/sample-data/no_credentials").unwrap();
    let mut contents : Vec<u8> = Vec::new();
    match f.read_to_end(&mut contents) {
        Err(why) => panic!("Error opening file to send to S3: {}", why),
        Ok(_) => {
            s3.put_object(&test_bucket(), "2016-10-07T23:30:38Z", &contents).unwrap();
        }
    }
    let get_response = s3.get_object(&test_bucket(), "2016-10-07T23:30:38Z").unwrap();
    println!("Got object back: {:?}", get_response);
}

#[test]
fn list_objects_test() {
    let _ = env_logger::init();
    let bare_s3 = S3Client::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
    let mut list_request = ListObjectsRequest::default(); // need to set bucket
    list_request.bucket = test_bucket();
    let result = bare_s3.list_objects(&list_request).unwrap();
    println!("result is {:?}", result);
}

<commit_msg>Reworks us-east-1 s3 bucket creation test.<commit_after>#![cfg(feature = "s3")]

extern crate env_logger;
#[macro_use]
extern crate log;
extern crate time;

#[macro_use]
extern crate rusoto;

use std::io::Read;
use std::fs::File;
use std::env::var;
use rusoto::{DefaultCredentialsProvider, Region};
use rusoto::s3::{S3Helper, S3Client, ListObjectsRequest, HeadObjectRequest, CreateBucketRequest};

fn test_bucket() -> String {
    match var("S3_TEST_BUCKET") {
        Ok(val) => val.to_owned(),
        Err(_) => "rusototester".to_owned()
    }
}

fn test_bucket_region() -> Region {
    match var("S3_TEST_BUCKET_REGION") {
        Ok(val) => val.parse().unwrap(),
        Err(_) => "us-west-2".parse().unwrap()
    }
}

#[test]
fn list_buckets_tests() {
    let _ = env_logger::init();
    let s3 = S3Helper::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
    let response = s3.list_buckets().unwrap();
    info!("Got list of buckets: {:?}", response);
    for q in response.buckets {
        info!("Existing bucket: {:?}", q.name);
    }
}

#[test]
fn object_lifecycle_test() {
    // PUT an object
    let s3 = S3Helper::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());

    let mut f = File::open("tests/sample-data/no_credentials").unwrap();
    let mut contents : Vec<u8> = Vec::new();
    match f.read_to_end(&mut contents) {
        Err(why) => panic!("Error opening file to send to S3: {}", why),
        Ok(_) => {
            s3.put_object(&test_bucket(), "no_credentials", &contents).unwrap();
        }
    }

    let client = S3Client::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
    // HEAD the object that was PUT
    let size_req = HeadObjectRequest{
      bucket: test_bucket(),
      key: "no_credentials".to_string(),
      ..Default::default()
    };

    println!("{:?}", client.head_object(&size_req).unwrap());

    // GET the object
    s3.get_object(&test_bucket(), "no_credentials").unwrap();

    // DELETE the object
    s3.delete_object(&test_bucket(), "no_credentials").unwrap();
}

#[test]
fn create_bucket_in_useast1_and_use_immediately() {
    let mut f = File::open("tests/sample-data/no_credentials").unwrap();
    let mut contents : Vec<u8> = Vec::new();
    match f.read_to_end(&mut contents) {
        Err(why) => panic!("Error opening file to send to S3: {}", why),
        Ok(_) => (),
    }

    let bucket_name = format!("rusototestbucket");
    let s3_helper = S3Helper::new(DefaultCredentialsProvider::new().unwrap(), Region::UsEast1);
    let s3 = S3Client::new(DefaultCredentialsProvider::new().unwrap(), Region::UsEast1);
    let create_bucket_request = CreateBucketRequest{
        bucket: bucket_name.clone(),
        ..Default::default()
    };
    let bucket_creation_result = s3.create_bucket(&create_bucket_request).unwrap();
    println!("bucket created: {:?}", bucket_creation_result);

    let put_response = s3_helper.put_object(&bucket_name, "no_credentials", &contents).unwrap();
    println!("put_response is {:?}", put_response);
}

#[test]
fn put_and_fetch_timestamp_named_object_test() {
    let s3 = S3Helper::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
    let mut f = File::open("tests/sample-data/no_credentials").unwrap();
    let mut contents : Vec<u8> = Vec::new();
    match f.read_to_end(&mut contents) {
        Err(why) => panic!("Error opening file to send to S3: {}", why),
        Ok(_) => {
            s3.put_object(&test_bucket(), "2016-10-07T23:30:38Z", &contents).unwrap();
        }
    }
    let get_response = s3.get_object(&test_bucket(), "2016-10-07T23:30:38Z").unwrap();
    println!("Got object back: {:?}", get_response);
}

#[test]
fn list_objects_test() {
    let _ = env_logger::init();
    let bare_s3 = S3Client::new(DefaultCredentialsProvider::new().unwrap(), test_bucket_region());
    let mut list_request = ListObjectsRequest::default(); // need to set bucket
    list_request.bucket = test_bucket();
    let result = bare_s3.list_objects(&list_request).unwrap();
    println!("result is {:?}", result);
}
<|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 dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::codegen::InheritTypes::EventCast;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::error::Error::{InvalidAccess, Syntax};
use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::js::{Temporary, JSRef, Rootable};
use dom::bindings::refcounted::Trusted;
use dom::bindings::str::USVString;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::reflect_dom_object;
use dom::closeevent::CloseEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use script_task::Runnable;
use script_task::ScriptMsg;
use std::cell::{Cell, RefCell};
use std::borrow::ToOwned;
use util::str::DOMString;

use websocket::Message;
use websocket::ws::sender::Sender as Sender_Object;
use websocket::client::sender::Sender;
use websocket::client::receiver::Receiver;
use websocket::stream::WebSocketStream;
use websocket::client::request::Url;
use websocket::Client;

#[derive(PartialEq, Copy, Clone)]
#[jstraceable]
enum WebSocketRequestState {
    Connecting = 0,
    Open = 1,
    Closing = 2,
    Closed = 3,
}

no_jsmanaged_fields!(Sender<WebSocketStream>);
no_jsmanaged_fields!(Receiver<WebSocketStream>);

#[dom_struct]
pub struct WebSocket {
    eventtarget: EventTarget,
    url: DOMString,
    global: GlobalField,
    ready_state: Cell<WebSocketRequestState>,
    sender: RefCell<Option<Sender<WebSocketStream>>>,
    receiver: RefCell<Option<Receiver<WebSocketStream>>>,
    failed: Cell<bool>, //Flag to tell if websocket was closed due to failure
    full: Cell<bool>, //Flag to tell if websocket queue is full
    clean_close: Cell<bool>, //Flag to tell if the websocket closed cleanly (not due to full or fail)
    code: Cell<u16>, //Closing code
    reason: DOMRefCell<DOMString>, //Closing reason
    data: DOMRefCell<DOMString>, //Data from send - TODO: Remove after buffer is added.
    sendCloseFrame: Cell<bool>
}

fn parse_web_socket_url(url_str: &str) -> Fallible<(Url, String, u16, String, bool)> {
    // https://html.spec.whatwg.org/multipage/#parse-a-websocket-url's-components
    // Steps 1 and 2
    let parsed_url = Url::parse(url_str);
    let parsed_url = match parsed_url {
        Ok(parsed_url) => parsed_url,
        Err(_) => return Err(Error::Syntax),
    };

    // Step 4
    if parsed_url.fragment != None {
        return Err(Error::Syntax);
    }

    // Steps 3 and 5
    let secure = match parsed_url.scheme.as_ref() {
        "ws" => false,
        "wss" => true,
        _ => return Err(Error::Syntax), // step 3
    };

    let host = parsed_url.host().unwrap().serialize(); // Step 6
    let port = parsed_url.port_or_default().unwrap(); // Steps 7 and 8
    let mut resource = parsed_url.path().unwrap().connect("/"); // Step 9
    if resource.is_empty() {
        resource = "/".to_owned(); // Step 10
    }

    // Step 11
    if let Some(ref query) = parsed_url.query {
        resource.push('?');
        resource.push_str(query);
    }

    // Step 12
    // FIXME remove parsed_url once it's no longer used in WebSocket::new
    Ok((parsed_url, host, port, resource, secure))
}

impl WebSocket {
    pub fn new_inherited(global: GlobalRef, url: DOMString) -> WebSocket {
        WebSocket {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::WebSocket),
            url: url,
            global: GlobalField::from_rooted(&global),
            ready_state: Cell::new(WebSocketRequestState::Connecting),
            failed: Cell::new(false),
            sender: RefCell::new(None),
            receiver: RefCell::new(None),
            full: Cell::new(false),
            clean_close: Cell::new(true),
            code: Cell::new(0),
            reason: DOMRefCell::new("".to_owned()),
            data: DOMRefCell::new("".to_owned()),
            sendCloseFrame: Cell::new(false)
        }

    }

    pub fn new(global: GlobalRef, url: DOMString) -> Fallible<Temporary<WebSocket>> {
        /*TODO: This constructor is only a prototype, it does not accomplish the specs
          defined here:
          http://html.spec.whatwg.org
          Item 1 is already satisfied.
          The remaining 8 items must be satisfied.
          TODO: This constructor should be responsible for spawning a thread for the
          receive loop after ws_root.r().Open() - See comment
        */
        let ws_root = reflect_dom_object(box WebSocket::new_inherited(global, url),
                                         global,
                                         WebSocketBinding::Wrap).root();
        let ws_root = ws_root.r();

        // FIXME extract the right variables once Client::connect implementation is
        // fixed to follow the RFC 6455 properly
        let (parsed_url, _, _, _, _) = try!(parse_web_socket_url(&ws_root.url));

        // TODO Client::connect does not conform to RFC 6455
        // see https://github.com/cyderize/rust-websocket/issues/38
        let request = Client::connect(parsed_url).unwrap();
        let response = request.send().unwrap();
        response.validate().unwrap();
        ws_root.ready_state.set(WebSocketRequestState::Open);
        //Check to see if ready_state is Closing or Closed and failed = true - means we failed the websocket
        //if so return without setting any states
        let ready_state = ws_root.ready_state.get();
        let failed = ws_root.failed.get();
        if failed && (ready_state == WebSocketRequestState::Closed || ready_state == WebSocketRequestState::Closing) {
            //Do nothing else. Let the close finish.
            return Ok(Temporary::from_rooted(ws_root));
        }

        let (temp_sender, temp_receiver) = response.begin().split();
        let mut other_sender = ws_root.sender.borrow_mut();
        let mut other_receiver = ws_root.receiver.borrow_mut();
        *other_sender = Some(temp_sender);
        *other_receiver = Some(temp_receiver);

        //Create everything necessary for starting the open asynchronous task, then begin the task.
        let global_root = ws_root.global.root();
        let addr: Trusted<WebSocket> = Trusted::new(global_root.r().get_cx(), ws_root, global_root.r().script_chan().clone());
        let open_task = box WebSocketTaskHandler::new(addr.clone(), WebSocketTask::Open);
        global_root.r().script_chan().send(ScriptMsg::RunnableMsg(open_task)).unwrap();
        //TODO: Spawn thread here for receive loop
        /*TODO: Add receive loop here and make new thread run this
          Receive is an infinite loop "similiar" the one shown here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop however does need to follow the spec. These are outlined here
          under "WebSocket message has been received" items 1-5:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop also needs to dispatch an asynchronous event as stated here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: When the receive loop receives a close message from the server,
          it confirms the websocket is now closed. This requires the close event
          to be fired (dispatch_close fires the close event - see implementation below)
        */
        Ok(Temporary::from_rooted(ws_root))
    }

    pub fn Constructor(global: GlobalRef, url: DOMString) -> Fallible<Temporary<WebSocket>> {
        WebSocket::new(global, url)
    }
}

impl<'a> WebSocketMethods for JSRef<'a, WebSocket> {
    event_handler!(open, GetOnopen, SetOnopen);
    event_handler!(close, GetOnclose, SetOnclose);
    event_handler!(error, GetOnerror, SetOnerror);

    fn Url(self) -> DOMString {
        self.url.clone()
    }

    fn ReadyState(self) -> u16 {
        self.ready_state.get() as u16
    }

    fn Send(self, data: Option<USVString>)-> Fallible<()>{
        /*TODO: This is not up to spec see http://html.spec.whatwg.org/multipage/comms.html search for "If argument is a string"
          TODO: Need to buffer data
          TODO: bufferedAmount attribute returns the size of the buffer in bytes -
                this is a required attribute defined in the websocket.webidl file
          TODO: The send function needs to flag when full by using the following
          self.full.set(true). This needs to be done when the buffer is full
        */
        let mut other_sender = self.sender.borrow_mut();
        let my_sender = other_sender.as_mut().unwrap();
        if self.sendCloseFrame.get() { //TODO: Also check if the buffer is full
            self.sendCloseFrame.set(false);
            let _ = my_sender.send_message(Message::Close(None));
            return Ok(());
        }
        let _ = my_sender.send_message(Message::Text(data.unwrap().0));
        return Ok(())
    }

    fn Close(self, code: Option<u16>, reason: Option<USVString>) -> Fallible<()>{
        if let Some(code) = code {
            //Check code is NOT 1000 NOR in the range of 3000-4999 (inclusive)
            if  code != 1000 && (code < 3000 || code > 4999) {
                return Err(Error::InvalidAccess);
            }
        }
        if let Some(ref reason) = reason {
            if reason.0.as_bytes().len() > 123 { //reason cannot be larger than 123 bytes
                return Err(Error::Syntax);
            }
        }

        match self.ready_state.get() {
            WebSocketRequestState::Closing | WebSocketRequestState::Closed  => {} //Do nothing
            WebSocketRequestState::Connecting => { //Connection is not yet established
                /*By setting the state to closing, the open function
                  will abort connecting the websocket*/
                self.ready_state.set(WebSocketRequestState::Closing);
                self.failed.set(true);
                self.sendCloseFrame.set(true);
                //Dispatch send task to send close frame
                //TODO: Sending here is just empty string, though no string is really needed. Another send, empty send, could be used.
                let _ = self.Send(None);
                //Note: After sending the close message, the receive loop confirms a close message from the server and must fire a close event
            }
            WebSocketRequestState::Open => {
                //Closing handshake not started - still in open
                //Start the closing by setting the code and reason if they exist
                if let Some(code) = code {
                    self.code.set(code);
                }
                if let Some(reason) = reason {
                    *self.reason.borrow_mut() = reason.0;
                }
                self.ready_state.set(WebSocketRequestState::Closing);
                self.sendCloseFrame.set(true);
                //Dispatch send task to send close frame
                let _ = self.Send(None);
                //Note: After sending the close message, the receive loop confirms a close message from the server and must fire a close event
            }
        }
        Ok(()) //Return Ok
    }
}

pub enum WebSocketTask {
    Open,
    Close,
}

pub struct WebSocketTaskHandler {
    addr: Trusted<WebSocket>,
    task: WebSocketTask,
}

impl WebSocketTaskHandler {
    pub fn new(addr: Trusted<WebSocket>, task: WebSocketTask) -> WebSocketTaskHandler {
        WebSocketTaskHandler {
            addr: addr,
            task: task,
        }
    }

    fn dispatch_open(&self) {
        /*TODO: Items 1, 3, 4, & 5 under "WebSocket connection is established" as specified here:
          https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol
        */
        let ws = self.addr.to_temporary().root(); //Get root
        let ws = ws.r(); //Get websocket reference
        let global = ws.global.root();
        let event = Event::new(global.r(),
            "open".to_owned(),
            EventBubbles::DoesNotBubble,
            EventCancelable::NotCancelable).root();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(ws);
        event.r().fire(target);
    }

    fn dispatch_close(&self) {
        let ws = self.addr.to_temporary().root();
        let ws = ws.r();
        let global = ws.global.root();
        ws.ready_state.set(WebSocketRequestState::Closed);
        //If failed or full, fire error event
        if ws.failed.get() || ws.full.get() {
            ws.failed.set(false);
            ws.full.set(false);
            //A Bad close
            ws.clean_close.set(false);
            let event = Event::new(global.r(),
                                   "error".to_owned(),
                                   EventBubbles::DoesNotBubble,
                                   EventCancelable::Cancelable).root();
            let target: JSRef<EventTarget> = EventTargetCast::from_ref(ws);
            event.r().fire(target);
        }
        let rsn = ws.reason.borrow();
        let rsn_clone = rsn.clone();
        /*In addition, we also have to fire a close even if error event fired
         https://html.spec.whatwg.org/multipage/#closeWebSocket
        */
        let close_event = CloseEvent::new(global.r(),
                                          "close".to_owned(),
                                          EventBubbles::DoesNotBubble,
                                          EventCancelable::Cancelable,
                                          ws.clean_close.get(),
                                          ws.code.get(),
                                          rsn_clone).root();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(ws);
        let event: JSRef<Event> = EventCast::from_ref(close_event.r());
        event.fire(target);
    }
}

impl Runnable for WebSocketTaskHandler {
    fn handler(self: Box<WebSocketTaskHandler>) {
        match self.task {
            WebSocketTask::Open => {
                self.dispatch_open();
            }
            WebSocketTask::Close => {
                self.dispatch_close();
            }
        }
    }
}

<commit_msg>fixes 6111: WebSocket close event shouldn't be Cancelable<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 dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::WebSocketBinding;
use dom::bindings::codegen::Bindings::WebSocketBinding::WebSocketMethods;
use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull;
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::codegen::InheritTypes::EventCast;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::error::Error::{InvalidAccess, Syntax};
use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::js::{Temporary, JSRef, Rootable};
use dom::bindings::refcounted::Trusted;
use dom::bindings::str::USVString;
use dom::bindings::trace::JSTraceable;
use dom::bindings::utils::reflect_dom_object;
use dom::closeevent::CloseEvent;
use dom::event::{Event, EventBubbles, EventCancelable, EventHelpers};
use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId};
use script_task::Runnable;
use script_task::ScriptMsg;
use std::cell::{Cell, RefCell};
use std::borrow::ToOwned;
use util::str::DOMString;

use websocket::Message;
use websocket::ws::sender::Sender as Sender_Object;
use websocket::client::sender::Sender;
use websocket::client::receiver::Receiver;
use websocket::stream::WebSocketStream;
use websocket::client::request::Url;
use websocket::Client;

#[derive(PartialEq, Copy, Clone)]
#[jstraceable]
enum WebSocketRequestState {
    Connecting = 0,
    Open = 1,
    Closing = 2,
    Closed = 3,
}

no_jsmanaged_fields!(Sender<WebSocketStream>);
no_jsmanaged_fields!(Receiver<WebSocketStream>);

#[dom_struct]
pub struct WebSocket {
    eventtarget: EventTarget,
    url: DOMString,
    global: GlobalField,
    ready_state: Cell<WebSocketRequestState>,
    sender: RefCell<Option<Sender<WebSocketStream>>>,
    receiver: RefCell<Option<Receiver<WebSocketStream>>>,
    failed: Cell<bool>, //Flag to tell if websocket was closed due to failure
    full: Cell<bool>, //Flag to tell if websocket queue is full
    clean_close: Cell<bool>, //Flag to tell if the websocket closed cleanly (not due to full or fail)
    code: Cell<u16>, //Closing code
    reason: DOMRefCell<DOMString>, //Closing reason
    data: DOMRefCell<DOMString>, //Data from send - TODO: Remove after buffer is added.
    sendCloseFrame: Cell<bool>
}

fn parse_web_socket_url(url_str: &str) -> Fallible<(Url, String, u16, String, bool)> {
    // https://html.spec.whatwg.org/multipage/#parse-a-websocket-url's-components
    // Steps 1 and 2
    let parsed_url = Url::parse(url_str);
    let parsed_url = match parsed_url {
        Ok(parsed_url) => parsed_url,
        Err(_) => return Err(Error::Syntax),
    };

    // Step 4
    if parsed_url.fragment != None {
        return Err(Error::Syntax);
    }

    // Steps 3 and 5
    let secure = match parsed_url.scheme.as_ref() {
        "ws" => false,
        "wss" => true,
        _ => return Err(Error::Syntax), // step 3
    };

    let host = parsed_url.host().unwrap().serialize(); // Step 6
    let port = parsed_url.port_or_default().unwrap(); // Steps 7 and 8
    let mut resource = parsed_url.path().unwrap().connect("/"); // Step 9
    if resource.is_empty() {
        resource = "/".to_owned(); // Step 10
    }

    // Step 11
    if let Some(ref query) = parsed_url.query {
        resource.push('?');
        resource.push_str(query);
    }

    // Step 12
    // FIXME remove parsed_url once it's no longer used in WebSocket::new
    Ok((parsed_url, host, port, resource, secure))
}

impl WebSocket {
    pub fn new_inherited(global: GlobalRef, url: DOMString) -> WebSocket {
        WebSocket {
            eventtarget: EventTarget::new_inherited(EventTargetTypeId::WebSocket),
            url: url,
            global: GlobalField::from_rooted(&global),
            ready_state: Cell::new(WebSocketRequestState::Connecting),
            failed: Cell::new(false),
            sender: RefCell::new(None),
            receiver: RefCell::new(None),
            full: Cell::new(false),
            clean_close: Cell::new(true),
            code: Cell::new(0),
            reason: DOMRefCell::new("".to_owned()),
            data: DOMRefCell::new("".to_owned()),
            sendCloseFrame: Cell::new(false)
        }

    }

    pub fn new(global: GlobalRef, url: DOMString) -> Fallible<Temporary<WebSocket>> {
        /*TODO: This constructor is only a prototype, it does not accomplish the specs
          defined here:
          http://html.spec.whatwg.org
          Item 1 is already satisfied.
          The remaining 8 items must be satisfied.
          TODO: This constructor should be responsible for spawning a thread for the
          receive loop after ws_root.r().Open() - See comment
        */
        let ws_root = reflect_dom_object(box WebSocket::new_inherited(global, url),
                                         global,
                                         WebSocketBinding::Wrap).root();
        let ws_root = ws_root.r();

        // FIXME extract the right variables once Client::connect implementation is
        // fixed to follow the RFC 6455 properly
        let (parsed_url, _, _, _, _) = try!(parse_web_socket_url(&ws_root.url));

        // TODO Client::connect does not conform to RFC 6455
        // see https://github.com/cyderize/rust-websocket/issues/38
        let request = Client::connect(parsed_url).unwrap();
        let response = request.send().unwrap();
        response.validate().unwrap();
        ws_root.ready_state.set(WebSocketRequestState::Open);
        //Check to see if ready_state is Closing or Closed and failed = true - means we failed the websocket
        //if so return without setting any states
        let ready_state = ws_root.ready_state.get();
        let failed = ws_root.failed.get();
        if failed && (ready_state == WebSocketRequestState::Closed || ready_state == WebSocketRequestState::Closing) {
            //Do nothing else. Let the close finish.
            return Ok(Temporary::from_rooted(ws_root));
        }

        let (temp_sender, temp_receiver) = response.begin().split();
        let mut other_sender = ws_root.sender.borrow_mut();
        let mut other_receiver = ws_root.receiver.borrow_mut();
        *other_sender = Some(temp_sender);
        *other_receiver = Some(temp_receiver);

        //Create everything necessary for starting the open asynchronous task, then begin the task.
        let global_root = ws_root.global.root();
        let addr: Trusted<WebSocket> = Trusted::new(global_root.r().get_cx(), ws_root, global_root.r().script_chan().clone());
        let open_task = box WebSocketTaskHandler::new(addr.clone(), WebSocketTask::Open);
        global_root.r().script_chan().send(ScriptMsg::RunnableMsg(open_task)).unwrap();
        //TODO: Spawn thread here for receive loop
        /*TODO: Add receive loop here and make new thread run this
          Receive is an infinite loop "similiar" the one shown here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop however does need to follow the spec. These are outlined here
          under "WebSocket message has been received" items 1-5:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: The receive loop also needs to dispatch an asynchronous event as stated here:
          https://github.com/cyderize/rust-websocket/blob/master/examples/client.rs#L64
          TODO: When the receive loop receives a close message from the server,
          it confirms the websocket is now closed. This requires the close event
          to be fired (dispatch_close fires the close event - see implementation below)
        */
        Ok(Temporary::from_rooted(ws_root))
    }

    pub fn Constructor(global: GlobalRef, url: DOMString) -> Fallible<Temporary<WebSocket>> {
        WebSocket::new(global, url)
    }
}

impl<'a> WebSocketMethods for JSRef<'a, WebSocket> {
    event_handler!(open, GetOnopen, SetOnopen);
    event_handler!(close, GetOnclose, SetOnclose);
    event_handler!(error, GetOnerror, SetOnerror);

    fn Url(self) -> DOMString {
        self.url.clone()
    }

    fn ReadyState(self) -> u16 {
        self.ready_state.get() as u16
    }

    fn Send(self, data: Option<USVString>)-> Fallible<()>{
        /*TODO: This is not up to spec see http://html.spec.whatwg.org/multipage/comms.html search for "If argument is a string"
          TODO: Need to buffer data
          TODO: bufferedAmount attribute returns the size of the buffer in bytes -
                this is a required attribute defined in the websocket.webidl file
          TODO: The send function needs to flag when full by using the following
          self.full.set(true). This needs to be done when the buffer is full
        */
        let mut other_sender = self.sender.borrow_mut();
        let my_sender = other_sender.as_mut().unwrap();
        if self.sendCloseFrame.get() { //TODO: Also check if the buffer is full
            self.sendCloseFrame.set(false);
            let _ = my_sender.send_message(Message::Close(None));
            return Ok(());
        }
        let _ = my_sender.send_message(Message::Text(data.unwrap().0));
        return Ok(())
    }

    fn Close(self, code: Option<u16>, reason: Option<USVString>) -> Fallible<()>{
        if let Some(code) = code {
            //Check code is NOT 1000 NOR in the range of 3000-4999 (inclusive)
            if  code != 1000 && (code < 3000 || code > 4999) {
                return Err(Error::InvalidAccess);
            }
        }
        if let Some(ref reason) = reason {
            if reason.0.as_bytes().len() > 123 { //reason cannot be larger than 123 bytes
                return Err(Error::Syntax);
            }
        }

        match self.ready_state.get() {
            WebSocketRequestState::Closing | WebSocketRequestState::Closed  => {} //Do nothing
            WebSocketRequestState::Connecting => { //Connection is not yet established
                /*By setting the state to closing, the open function
                  will abort connecting the websocket*/
                self.ready_state.set(WebSocketRequestState::Closing);
                self.failed.set(true);
                self.sendCloseFrame.set(true);
                //Dispatch send task to send close frame
                //TODO: Sending here is just empty string, though no string is really needed. Another send, empty send, could be used.
                let _ = self.Send(None);
                //Note: After sending the close message, the receive loop confirms a close message from the server and must fire a close event
            }
            WebSocketRequestState::Open => {
                //Closing handshake not started - still in open
                //Start the closing by setting the code and reason if they exist
                if let Some(code) = code {
                    self.code.set(code);
                }
                if let Some(reason) = reason {
                    *self.reason.borrow_mut() = reason.0;
                }
                self.ready_state.set(WebSocketRequestState::Closing);
                self.sendCloseFrame.set(true);
                //Dispatch send task to send close frame
                let _ = self.Send(None);
                //Note: After sending the close message, the receive loop confirms a close message from the server and must fire a close event
            }
        }
        Ok(()) //Return Ok
    }
}

pub enum WebSocketTask {
    Open,
    Close,
}

pub struct WebSocketTaskHandler {
    addr: Trusted<WebSocket>,
    task: WebSocketTask,
}

impl WebSocketTaskHandler {
    pub fn new(addr: Trusted<WebSocket>, task: WebSocketTask) -> WebSocketTaskHandler {
        WebSocketTaskHandler {
            addr: addr,
            task: task,
        }
    }

    fn dispatch_open(&self) {
        /*TODO: Items 1, 3, 4, & 5 under "WebSocket connection is established" as specified here:
          https://html.spec.whatwg.org/multipage/#feedback-from-the-protocol
        */
        let ws = self.addr.to_temporary().root(); //Get root
        let ws = ws.r(); //Get websocket reference
        let global = ws.global.root();
        let event = Event::new(global.r(),
            "open".to_owned(),
            EventBubbles::DoesNotBubble,
            EventCancelable::NotCancelable).root();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(ws);
        event.r().fire(target);
    }

    fn dispatch_close(&self) {
        let ws = self.addr.to_temporary().root();
        let ws = ws.r();
        let global = ws.global.root();
        ws.ready_state.set(WebSocketRequestState::Closed);
        //If failed or full, fire error event
        if ws.failed.get() || ws.full.get() {
            ws.failed.set(false);
            ws.full.set(false);
            //A Bad close
            ws.clean_close.set(false);
            let event = Event::new(global.r(),
                                   "error".to_owned(),
                                   EventBubbles::DoesNotBubble,
                                   EventCancelable::Cancelable).root();
            let target: JSRef<EventTarget> = EventTargetCast::from_ref(ws);
            event.r().fire(target);
        }
        let rsn = ws.reason.borrow();
        let rsn_clone = rsn.clone();
        /*In addition, we also have to fire a close even if error event fired
         https://html.spec.whatwg.org/multipage/#closeWebSocket
        */
        let close_event = CloseEvent::new(global.r(),
                                          "close".to_owned(),
                                          EventBubbles::DoesNotBubble,
                                          EventCancelable::NotCancelable,
                                          ws.clean_close.get(),
                                          ws.code.get(),
                                          rsn_clone).root();
        let target: JSRef<EventTarget> = EventTargetCast::from_ref(ws);
        let event: JSRef<Event> = EventCast::from_ref(close_event.r());
        event.fire(target);
    }
}

impl Runnable for WebSocketTaskHandler {
    fn handler(self: Box<WebSocketTaskHandler>) {
        match self.task {
            WebSocketTask::Open => {
                self.dispatch_open();
            }
            WebSocketTask::Close => {
                self.dispatch_close();
            }
        }
    }
}

<|endoftext|>


<commit_before><commit_msg>Add Day 18 solution<commit_after>// advent18.rs
// game of life

use std::io;
use std::cmp::min;

#[cfg(not(test))]
const GRID_SIZE: usize = 100;

#[cfg(test)]
const GRID_SIZE: usize = 6;

type LightGrid = [[bool; GRID_SIZE]; GRID_SIZE];

fn main() {
    let mut grid = [[false; GRID_SIZE]; GRID_SIZE];
    let mut row = 0;

    loop {
        let mut input = String::new();
        let result = io::stdin().read_line(&mut input);
        match result {
            Ok(byte_count) => if byte_count == 0 { break; },
            Err(_) => {
                println!("error reading from stdin");
                break;
            }
        }

        assert!(row < GRID_SIZE);
        for (i, c) in input.trim().char_indices() {
            grid[row][i] = match c {
                '.' => false,
                '#' => true,
                _ => panic!("Unexpected character!")
            };
        }

        row += 1;
    }

    assert!(row == GRID_SIZE);

    let mut grid2 = grid;

    for _ in 0..100 {
        grid = calc_new_grid(&grid);
        print_grid(&grid);
    }

    println!("Lights: {}", count_lights(&grid));

    set_corners(&mut grid2);
    for _ in 0..100 {
        grid2 = calc_new_grid2(&grid2);
        print_grid(&grid2);
    }

    println!("Lights part 2: {}", count_lights(&grid2));
}

// just for fun
fn print_grid(grid: &LightGrid) {
    for j in 0..GRID_SIZE {
        let mut row_string = String::new();
        for i in 0..GRID_SIZE {
            row_string.push(if grid[j][i] { '#' } else { '.' });
        }
        println!("{}", row_string);
    }
}

// count how many neighbor lights are on around point (x,y)
fn count_neighbors(grid: &LightGrid, x: usize, y: usize) -> usize {
    let x1 = if x == 0 { 0 } else { x - 1 };
    let x2 = min(x + 2, GRID_SIZE);
    let y1 = if y == 0 { 0 } else { y - 1 };
    let y2 = min(y + 2, GRID_SIZE);

    let mut total = 0;
    for i in x1..x2 {
        for j in y1..y2 {
            if (i != x || j != y) && grid[j][i] {
                total += 1;
            }
        }
    }
    total
}

// new state of the light at this location
fn new_light(grid: &LightGrid, x: usize, y: usize) -> bool {
    let neighbors = count_neighbors(grid, x, y);

    if grid[y][x] {
        neighbors == 2 || neighbors == 3
    } else {
        neighbors == 3
    }
}

fn calc_new_grid(grid: &LightGrid) -> LightGrid {
    let mut new_grid = [[false; GRID_SIZE]; GRID_SIZE];
    for i in 0..GRID_SIZE {
        for j in 0..GRID_SIZE {
            new_grid[j][i] = new_light(grid, i, j);
        }
    }
    new_grid
}

fn count_lights(grid: &LightGrid) -> u32 {
    let mut total = 0;

    for row in grid.iter() {
        for light in row.iter() {
            if *light {
                total += 1;
            }
        }
    }

    total
}

#[test]
fn test_count_neighbors() {
    let grid: LightGrid = [
        [false, true, false, true, false, true],
        [false, false, false, true, true, false],
        [true, false, false, false, false, true],
        [false, false, true, false, false, false],
        [true, false, true, false, false, true],
        [true, true, true, true, false, false]];

    assert_eq!(1, count_neighbors(&grid, 0, 0));
    assert_eq!(2, count_neighbors(&grid, 0, 5));
    assert_eq!(1, count_neighbors(&grid, 5, 0));
    assert_eq!(1, count_neighbors(&grid, 5, 5));
    assert_eq!(2, count_neighbors(&grid, 1, 1));
}

#[test]
fn test_calc_new_grid() {
    const GRID_TEMPLATE: LightGrid = [
        [false, true, false, true, false, true],
        [false, false, false, true, true, false],
        [true, false, false, false, false, true],
        [false, false, true, false, false, false],
        [true, false, true, false, false, true],
        [true, true, true, true, false, false]];

    const GRID_SOLUTION: LightGrid = [
        [false, false, false, false, false, false],
        [false, false, false, false, false, false],
        [false, false, true, true, false, false],
        [false, false, true, true, false, false],
        [false, false, false, false, false, false],
        [false, false, false, false, false, false]];

    let mut grid = GRID_TEMPLATE;
    for _ in 0..4 {
        grid = calc_new_grid(&grid);
    }

    assert_eq!(GRID_SOLUTION, grid);
    assert_eq!(4, count_lights(&grid));
}

// part 2

fn set_corners(grid: &mut LightGrid) {
   grid[0][0] = true;
   grid[0][GRID_SIZE - 1] = true;
   grid[GRID_SIZE - 1][0] = true;
   grid[GRID_SIZE - 1][GRID_SIZE - 1] = true;
}

fn calc_new_grid2(grid: &LightGrid) -> LightGrid {
    let mut new_grid = calc_new_grid(grid);
    set_corners(&mut new_grid);
    new_grid
}

#[test]
fn test_calc_new_grid2() {
    const GRID_TEMPLATE: LightGrid = [
        [false, true, false, true, false, true],
        [false, false, false, true, true, false],
        [true, false, false, false, false, true],
        [false, false, true, false, false, false],
        [true, false, true, false, false, true],
        [true, true, true, true, false, false]];

    const GRID_SOLUTION: LightGrid = [
        [true, true, false, true, true, true],
        [false, true, true, false, false, true],
        [false, true, true, false, false, false],
        [false, true, true, false, false, false],
        [true, false, true, false, false, false],
        [true, true, false, false, false, true]];

    let mut grid = GRID_TEMPLATE;
    set_corners(&mut grid);

    for _ in 0..5 {
        grid = calc_new_grid2(&grid);
    }

    assert_eq!(GRID_SOLUTION, grid);
    assert_eq!(17, count_lights(&grid));
}

<|endoftext|>


<commit_before><commit_msg>test binary<commit_after>extern crate chef_api;

#[macro_use]
extern crate log;
extern crate env_logger;

use chef_api::api_client::ApiClient;
use chef_api::config::Config;
use chef_api::requests::node::NodesRequest;

use std::io::Read;

pub fn main() {
    env_logger::init().unwrap();
    let cfg = Config::from_json("/Users/thom/.chef/knife.json");
    let client = ApiClient::new(cfg);
    let nodes = NodesRequest::new();

    let res = client.run(nodes);

    let mut output = String::new();
    res.unwrap().read_to_string(&mut output);
    info!("{:?}", output)
}
<|endoftext|>


<commit_before><commit_msg>critters fight back<commit_after><|endoftext|>