<commit_before>// Copyright 2014 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.

//! Implementations of serialization for structures found in libcollections

use std::uint;
use std::default::Default;
use std::hash::{Hash, Hasher};

use {Decodable, Encodable, Decoder, Encoder};
use std::collections::{DList, RingBuf, TreeMap, TreeSet, HashMap, HashSet,
                       TrieMap, TrieSet};
use std::collections::enum_set::{EnumSet, CLike};

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E>
> Encodable<S, E> for DList<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
            for (i, e) in self.iter().enumerate() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
            }
            Ok(())
        })
    }
}

impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for DList<T> {
    fn decode(d: &mut D) -> Result<DList<T>, E> {
        d.read_seq(|d, len| {
            let mut list = DList::new();
            for i in range(0u, len) {
                list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(list)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E>
> Encodable<S, E> for RingBuf<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
            for (i, e) in self.iter().enumerate() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
            }
            Ok(())
        })
    }
}

impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for RingBuf<T> {
    fn decode(d: &mut D) -> Result<RingBuf<T>, E> {
        d.read_seq(|d, len| {
            let mut deque: RingBuf<T> = RingBuf::new();
            for i in range(0u, len) {
                deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(deque)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    K: Encodable<S, E> + PartialEq + Ord,
    V: Encodable<S, E> + PartialEq
> Encodable<S, E> for TreeMap<K, V> {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    E,
    D: Decoder<E>,
    K: Decodable<D, E> + PartialEq + Ord,
    V: Decodable<D, E> + PartialEq
> Decodable<D, E> for TreeMap<K, V> {
    fn decode(d: &mut D) -> Result<TreeMap<K, V>, E> {
        d.read_map(|d, len| {
            let mut map = TreeMap::new();
            for i in range(0u, len) {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E> + PartialEq + Ord
> Encodable<S, E> for TreeSet<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    E,
    D: Decoder<E>,
    T: Decodable<D, E> + PartialEq + Ord
> Decodable<D, E> for TreeSet<T> {
    fn decode(d: &mut D) -> Result<TreeSet<T>, E> {
        d.read_seq(|d, len| {
            let mut set = TreeSet::new();
            for i in range(0u, len) {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E> + CLike
> Encodable<S, E> for EnumSet<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        let mut bits = 0;
        for item in self.iter() {
            bits |= item.to_uint();
        }
        s.emit_uint(bits)
    }
}

impl<
    E,
    D: Decoder<E>,
    T: Decodable<D, E> + CLike
> Decodable<D, E> for EnumSet<T> {
    fn decode(d: &mut D) -> Result<EnumSet<T>, E> {
        let bits = try!(d.read_uint());
        let mut set = EnumSet::new();
        for bit in range(0, uint::BITS) {
            if bits & (1 << bit) != 0 {
                set.insert(CLike::from_uint(1 << bit));
            }
        }
        Ok(set)
    }
}

impl<
    E,
    S: Encoder<E>,
    K: Encodable<S, E> + Hash<X> + Eq,
    V: Encodable<S, E>,
    X,
    H: Hasher<X>
> Encodable<S, E> for HashMap<K, V, H> {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    E,
    D: Decoder<E>,
    K: Decodable<D, E> + Hash<S> + Eq,
    V: Decodable<D, E>,
    S,
    H: Hasher<S> + Default
> Decodable<D, E> for HashMap<K, V, H> {
    fn decode(d: &mut D) -> Result<HashMap<K, V, H>, E> {
        d.read_map(|d, len| {
            let hasher = Default::default();
            let mut map = HashMap::with_capacity_and_hasher(len, hasher);
            for i in range(0u, len) {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E> + Hash<X> + Eq,
    X,
    H: Hasher<X>
> Encodable<S, E> for HashSet<T, H> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    E,
    D: Decoder<E>,
    T: Decodable<D, E> + Hash<S> + Eq,
    S,
    H: Hasher<S> + Default
> Decodable<D, E> for HashSet<T, H> {
    fn decode(d: &mut D) -> Result<HashSet<T, H>, E> {
        d.read_seq(|d, len| {
            let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
            for i in range(0u, len) {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    V: Encodable<S, E>
> Encodable<S, E> for TrieMap<V> {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        e.emit_map(self.len(), |e| {
                for (i, (key, val)) in self.iter().enumerate() {
                    try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                    try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                }
                Ok(())
            })
    }
}

impl<
    E,
    D: Decoder<E>,
    V: Decodable<D, E>
> Decodable<D, E> for TrieMap<V> {
    fn decode(d: &mut D) -> Result<TrieMap<V>, E> {
        d.read_map(|d, len| {
            let mut map = TrieMap::new();
            for i in range(0u, len) {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<E, S: Encoder<E>> Encodable<S, E> for TrieSet {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
                for (i, e) in self.iter().enumerate() {
                    try!(s.emit_seq_elt(i, |s| e.encode(s)));
                }
                Ok(())
            })
    }
}

impl<E, D: Decoder<E>> Decodable<D, E> for TrieSet {
    fn decode(d: &mut D) -> Result<TrieSet, E> {
        d.read_seq(|d, len| {
            let mut set = TrieSet::new();
            for i in range(0u, len) {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}
<commit_msg>auto merge of #18813 : csherratt/rust/add-encode-decode-vecmap, r=alexcrichton<commit_after>// Copyright 2014 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.

//! Implementations of serialization for structures found in libcollections

use std::uint;
use std::default::Default;
use std::hash::{Hash, Hasher};

use {Decodable, Encodable, Decoder, Encoder};
use std::collections::{DList, RingBuf, TreeMap, TreeSet, HashMap, HashSet,
                       TrieMap, TrieSet, VecMap};
use std::collections::enum_set::{EnumSet, CLike};

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E>
> Encodable<S, E> for DList<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
            for (i, e) in self.iter().enumerate() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
            }
            Ok(())
        })
    }
}

impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for DList<T> {
    fn decode(d: &mut D) -> Result<DList<T>, E> {
        d.read_seq(|d, len| {
            let mut list = DList::new();
            for i in range(0u, len) {
                list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(list)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E>
> Encodable<S, E> for RingBuf<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
            for (i, e) in self.iter().enumerate() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
            }
            Ok(())
        })
    }
}

impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for RingBuf<T> {
    fn decode(d: &mut D) -> Result<RingBuf<T>, E> {
        d.read_seq(|d, len| {
            let mut deque: RingBuf<T> = RingBuf::new();
            for i in range(0u, len) {
                deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(deque)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    K: Encodable<S, E> + PartialEq + Ord,
    V: Encodable<S, E> + PartialEq
> Encodable<S, E> for TreeMap<K, V> {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    E,
    D: Decoder<E>,
    K: Decodable<D, E> + PartialEq + Ord,
    V: Decodable<D, E> + PartialEq
> Decodable<D, E> for TreeMap<K, V> {
    fn decode(d: &mut D) -> Result<TreeMap<K, V>, E> {
        d.read_map(|d, len| {
            let mut map = TreeMap::new();
            for i in range(0u, len) {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E> + PartialEq + Ord
> Encodable<S, E> for TreeSet<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    E,
    D: Decoder<E>,
    T: Decodable<D, E> + PartialEq + Ord
> Decodable<D, E> for TreeSet<T> {
    fn decode(d: &mut D) -> Result<TreeSet<T>, E> {
        d.read_seq(|d, len| {
            let mut set = TreeSet::new();
            for i in range(0u, len) {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E> + CLike
> Encodable<S, E> for EnumSet<T> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        let mut bits = 0;
        for item in self.iter() {
            bits |= item.to_uint();
        }
        s.emit_uint(bits)
    }
}

impl<
    E,
    D: Decoder<E>,
    T: Decodable<D, E> + CLike
> Decodable<D, E> for EnumSet<T> {
    fn decode(d: &mut D) -> Result<EnumSet<T>, E> {
        let bits = try!(d.read_uint());
        let mut set = EnumSet::new();
        for bit in range(0, uint::BITS) {
            if bits & (1 << bit) != 0 {
                set.insert(CLike::from_uint(1 << bit));
            }
        }
        Ok(set)
    }
}

impl<
    E,
    S: Encoder<E>,
    K: Encodable<S, E> + Hash<X> + Eq,
    V: Encodable<S, E>,
    X,
    H: Hasher<X>
> Encodable<S, E> for HashMap<K, V, H> {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        e.emit_map(self.len(), |e| {
            let mut i = 0;
            for (key, val) in self.iter() {
                try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    E,
    D: Decoder<E>,
    K: Decodable<D, E> + Hash<S> + Eq,
    V: Decodable<D, E>,
    S,
    H: Hasher<S> + Default
> Decodable<D, E> for HashMap<K, V, H> {
    fn decode(d: &mut D) -> Result<HashMap<K, V, H>, E> {
        d.read_map(|d, len| {
            let hasher = Default::default();
            let mut map = HashMap::with_capacity_and_hasher(len, hasher);
            for i in range(0u, len) {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    T: Encodable<S, E> + Hash<X> + Eq,
    X,
    H: Hasher<X>
> Encodable<S, E> for HashSet<T, H> {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
            let mut i = 0;
            for e in self.iter() {
                try!(s.emit_seq_elt(i, |s| e.encode(s)));
                i += 1;
            }
            Ok(())
        })
    }
}

impl<
    E,
    D: Decoder<E>,
    T: Decodable<D, E> + Hash<S> + Eq,
    S,
    H: Hasher<S> + Default
> Decodable<D, E> for HashSet<T, H> {
    fn decode(d: &mut D) -> Result<HashSet<T, H>, E> {
        d.read_seq(|d, len| {
            let mut set = HashSet::with_capacity_and_hasher(len, Default::default());
            for i in range(0u, len) {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    V: Encodable<S, E>
> Encodable<S, E> for TrieMap<V> {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        e.emit_map(self.len(), |e| {
                for (i, (key, val)) in self.iter().enumerate() {
                    try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                    try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                }
                Ok(())
            })
    }
}

impl<
    E,
    D: Decoder<E>,
    V: Decodable<D, E>
> Decodable<D, E> for TrieMap<V> {
    fn decode(d: &mut D) -> Result<TrieMap<V>, E> {
        d.read_map(|d, len| {
            let mut map = TrieMap::new();
            for i in range(0u, len) {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}

impl<E, S: Encoder<E>> Encodable<S, E> for TrieSet {
    fn encode(&self, s: &mut S) -> Result<(), E> {
        s.emit_seq(self.len(), |s| {
                for (i, e) in self.iter().enumerate() {
                    try!(s.emit_seq_elt(i, |s| e.encode(s)));
                }
                Ok(())
            })
    }
}

impl<E, D: Decoder<E>> Decodable<D, E> for TrieSet {
    fn decode(d: &mut D) -> Result<TrieSet, E> {
        d.read_seq(|d, len| {
            let mut set = TrieSet::new();
            for i in range(0u, len) {
                set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
            }
            Ok(set)
        })
    }
}

impl<
    E,
    S: Encoder<E>,
    V: Encodable<S, E>
> Encodable<S, E> for VecMap<V> {
    fn encode(&self, e: &mut S) -> Result<(), E> {
        e.emit_map(self.len(), |e| {
                for (i, (key, val)) in self.iter().enumerate() {
                    try!(e.emit_map_elt_key(i, |e| key.encode(e)));
                    try!(e.emit_map_elt_val(i, |e| val.encode(e)));
                }
                Ok(())
            })
    }
}

impl<
    E,
    D: Decoder<E>,
    V: Decodable<D, E>
> Decodable<D, E> for VecMap<V> {
    fn decode(d: &mut D) -> Result<VecMap<V>, E> {
        d.read_map(|d, len| {
            let mut map = VecMap::new();
            for i in range(0u, len) {
                let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
                map.insert(key, val);
            }
            Ok(map)
        })
    }
}
<|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::attr::{Attr, AttrHelpers};
use dom::bindings::codegen::Bindings::DOMTokenListBinding;
use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods;
use dom::bindings::error::{Fallible, InvalidCharacter, Syntax};
use dom::bindings::global::Window;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable};
use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::window_from_node;

use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS};
use string_cache::Atom;

#[dom_struct]
pub struct DOMTokenList {
    reflector_: Reflector,
    element: JS<Element>,
    local_name: Atom,
}

impl DOMTokenList {
    pub fn new_inherited(element: JSRef<Element>, local_name: Atom) -> DOMTokenList {
        DOMTokenList {
            reflector_: Reflector::new(),
            element: JS::from_rooted(element),
            local_name: local_name,
        }
    }

    pub fn new(element: JSRef<Element>, local_name: &Atom) -> Temporary<DOMTokenList> {
        let window = window_from_node(element).root();
        reflect_dom_object(box DOMTokenList::new_inherited(element, local_name.clone()),
                           &Window(*window),
                           DOMTokenListBinding::Wrap)
    }
}

impl Reflectable for DOMTokenList {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }
}

trait PrivateDOMTokenListHelpers {
    fn attribute(self) -> Option<Temporary<Attr>>;
    fn check_token_exceptions<'a>(self, token: &'a str) -> Fallible<&'a str>;
}

impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> {
    fn attribute(self) -> Option<Temporary<Attr>> {
        let element = self.element.root();
        element.get_attribute(ns!(""), &self.local_name)
    }

    fn check_token_exceptions<'a>(self, token: &'a str) -> Fallible<&'a str> {
        match token {
            "" => Err(Syntax),
            token if token.find(HTML_SPACE_CHARACTERS).is_some() => Err(InvalidCharacter),
            token => Ok(token)
        }
    }
}

// http://dom.spec.whatwg.org/#domtokenlist
impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
    // http://dom.spec.whatwg.org/#dom-domtokenlist-length
    fn Length(self) -> u32 {
        self.attribute().root().map(|attr| {
            attr.value().tokens().map(|tokens| tokens.len()).unwrap_or(0)
        }).unwrap_or(0) as u32
    }

    // http://dom.spec.whatwg.org/#dom-domtokenlist-item
    fn Item(self, index: u32) -> Option<DOMString> {
        self.attribute().root().and_then(|attr| attr.value().tokens().and_then(|tokens| {
            tokens.get(index as uint).map(|token| token.as_slice().to_string())
        }))
    }

    fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<DOMString> {
        let item = self.Item(index);
        *found = item.is_some();
        item
    }

    // http://dom.spec.whatwg.org/#dom-domtokenlist-contains
    fn Contains(self, token: DOMString) -> Fallible<bool> {
        self.check_token_exceptions(token.as_slice()).map(|slice| {
            self.attribute().root().and_then(|attr| attr.value().tokens().map(|tokens| {
                let atom = Atom::from_slice(slice);
                tokens.iter().any(|token| *token == atom)
            })).unwrap_or(false)
        })
    }
}
<commit_msg>auto merge of #4084 : Ms2ger/servo/tokenlist-robust, r=jdm<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::attr::{Attr, AttrHelpers};
use dom::bindings::codegen::Bindings::DOMTokenListBinding;
use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods;
use dom::bindings::error::{Fallible, InvalidCharacter, Syntax};
use dom::bindings::global::Window;
use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable};
use dom::bindings::utils::{Reflector, Reflectable, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::window_from_node;

use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS};
use string_cache::Atom;

#[dom_struct]
pub struct DOMTokenList {
    reflector_: Reflector,
    element: JS<Element>,
    local_name: Atom,
}

impl DOMTokenList {
    pub fn new_inherited(element: JSRef<Element>, local_name: Atom) -> DOMTokenList {
        DOMTokenList {
            reflector_: Reflector::new(),
            element: JS::from_rooted(element),
            local_name: local_name,
        }
    }

    pub fn new(element: JSRef<Element>, local_name: &Atom) -> Temporary<DOMTokenList> {
        let window = window_from_node(element).root();
        reflect_dom_object(box DOMTokenList::new_inherited(element, local_name.clone()),
                           &Window(*window),
                           DOMTokenListBinding::Wrap)
    }
}

impl Reflectable for DOMTokenList {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }
}

trait PrivateDOMTokenListHelpers {
    fn attribute(self) -> Option<Temporary<Attr>>;
    fn check_token_exceptions<'a>(self, token: &'a str) -> Fallible<&'a str>;
}

impl<'a> PrivateDOMTokenListHelpers for JSRef<'a, DOMTokenList> {
    fn attribute(self) -> Option<Temporary<Attr>> {
        let element = self.element.root();
        element.get_attribute(ns!(""), &self.local_name)
    }

    fn check_token_exceptions<'a>(self, token: &'a str) -> Fallible<&'a str> {
        match token {
            "" => Err(Syntax),
            token if token.find(HTML_SPACE_CHARACTERS).is_some() => Err(InvalidCharacter),
            token => Ok(token)
        }
    }
}

// http://dom.spec.whatwg.org/#domtokenlist
impl<'a> DOMTokenListMethods for JSRef<'a, DOMTokenList> {
    // http://dom.spec.whatwg.org/#dom-domtokenlist-length
    fn Length(self) -> u32 {
        self.attribute().root().map(|attr| {
            attr.value().tokens().map(|tokens| tokens.len()).unwrap_or(0)
        }).unwrap_or(0) as u32
    }

    // http://dom.spec.whatwg.org/#dom-domtokenlist-item
    fn Item(self, index: u32) -> Option<DOMString> {
        self.attribute().root().and_then(|attr| attr.value().tokens().and_then(|tokens| {
            tokens.get(index as uint).map(|token| token.as_slice().to_string())
        }))
    }

    fn IndexedGetter(self, index: u32, found: &mut bool) -> Option<DOMString> {
        let item = self.Item(index);
        *found = item.is_some();
        item
    }

    // http://dom.spec.whatwg.org/#dom-domtokenlist-contains
    fn Contains(self, token: DOMString) -> Fallible<bool> {
        self.check_token_exceptions(token.as_slice()).map(|slice| {
            self.attribute().root().map(|attr| {
                let value = attr.value();
                let tokens = value.tokens()
                                  .expect("Should have parsed this attribute");
                let atom = Atom::from_slice(slice);
                tokens.iter().any(|token| *token == atom)
            }).unwrap_or(false)
        })
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::error::Error;
use std::io::Cursor;

pub use self::route::Route;
pub use self::router::Router;

use conduit::{Handler, Request, Response};

pub mod regexp;
pub mod route;
pub mod router;

pub enum Outcome {
    Proceed(),
    Halt(u16, String),
    Complete(Response),
}

pub trait Wrapper {
    fn around(self, handler: Box<Segment>) -> Box<Segment>;
}

pub struct Chain {
    handler: Option<Box<Segment>>,
}

impl Chain {
    pub fn new<H: Segment>(handler: H) -> Self {
        Chain {
            handler: Some(Box::new(handler)),
        }
    }

    pub fn with<W: Wrapper>(&mut self, handler: W) -> &mut Self {
        let mut inner = self.handler.take().unwrap();
        inner = handler.around(inner);
        self.handler = Some(inner);
        self
    }
}

impl Handler for Chain {
    // TODO: don't panic at unexepcted end of chain ...
    fn call(&self, req: &mut Request) -> Result<Response, Box<Error + Send>> {
        match self.handler.as_ref().unwrap().invoke(req) {
            Outcome::Complete(resp)   => Ok(resp),
            Outcome::Halt(status,msg) => Ok(halt_stack(status, msg)),
            _ => panic!("middleware stack did not terminate... dats bad.")
        }
    }
}

/// A segment represents a visitor which will receive a request
/// along with a partial response and transform them in some way.
///
/// Segments cooperate with each other by way of specifying some
/// `Outcome` which tells the stack how it should proceed.
///
pub trait Segment: Send + Sync + 'static {
    fn invoke(&self, req: &mut Request) -> Outcome;
}

impl<F> Segment for F
where F: Send + Sync + 'static + Fn(&mut Request) -> Outcome {
    fn invoke(&self, req: &mut Request) -> Outcome { (*self)(req) }
}

/// Immediately generates a simple response, this should only be
/// used if processing cannot continue in an ordinary fashion ...
fn halt_stack(status: u16, reason: String) -> Response {
    Response {
        // TODO: status code => canonical reason per RFC
        status: (status as u32, "no reason given"),
        headers: HashMap::new(),
        body: Box::new(Cursor::new(reason.into_bytes())),
    }
}
<commit_msg>remove the old segment/stack dingus<commit_after>pub use self::router::Router;

pub mod regexp;
pub mod route;
pub mod router;
<|endoftext|>


<commit_before>#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;
#[macro_use]
extern crate torchrs;
#[macro_use]
extern crate clap;

use torchrs::autograd::{Variable, VariableArgs, VarAccess};
use torchrs::{optim, utils, nn, tensor};
use torchrs::nn::{InitModuleStruct, GetFieldStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;
use torchrs::utils::torchvision::{datasets, transforms};

use clap::{Arg, App};
#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="false")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    let mut args = NetArgs::default();
    let matches = App::new("Torch.rs MNIST Example")
        .version("0.1")
        .author("Some Guy")
        .about("recognize handwritten digits")
        .arg(Arg::with_name("batch-size").takes_value(true))
        .arg(Arg::with_name("test-batch-size").takes_value(true))
        .arg(Arg::with_name("epochs").takes_value(true))
        .arg(Arg::with_name("lr").takes_value(true))
        .arg(Arg::with_name("momentum").takes_value(true))
        .arg(Arg::with_name("no-cuda").takes_value(false))
        .arg(Arg::with_name("seed").takes_value(true))
        .arg(Arg::with_name("log-interval").takes_value(true))
        .get_matches();
    let (b_size, tb_size, epochs, lr, momentum, seed, log_int) =
        (value_t!(matches.value_of("batch-size"), usize).ok(),
         value_t!(matches.value_of("test-batch-size"), usize).ok(),
         value_t!(matches.value_of("epochs"), u32).ok(),
         value_t!(matches.value_of("lr"), f32).ok(),
         value_t!(matches.value_of("momentum"), f32).ok(),
         value_t!(matches.value_of("seed"), usize).ok(),
         value_t!(matches.value_of("log-interval"), usize).ok());
    if let Some(b_size) = b_size {
        args.batch_size = b_size
    }
    if let Some(tb_size) = tb_size {
        args.test_batch_size = tb_size
    }
    if let Some(epochs) = epochs {
        args.epochs = epochs
    }
    if let Some(lr) = lr {
        args.lr = lr
    }
    if let Some(momentum) = momentum {
        args.momentum = momentum
    }
    if let Some(seed) = seed {
        args.seed = seed
    }
    if let Some(log_int) = log_int {
        args.log_interval = log_int
    }
    //XXX CUDA?
    args
}

#[derive(ModParse)]
struct Net<T: tensor::NumLimits> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: tensor::NumLimits> Net<T> {
    pub fn new() -> Net<T> {
        Net {
                delegate: nn::Module::new(),
                conv1: nn::Conv2d::build(1, 10, (5, 5)).done(),
                conv2: nn::Conv2d::build(10, 20, (5, 5)).done(),
                fc1: nn::Linear::build(320, 50).done(),
                fc2: nn::Linear::build(50, 10).done(),
            }
            .init_module()
    }
}
impl_mod_delegate!(Net);

impl<T: tensor::NumLimits> ModIntf<T> for Net<T> {
    fn forward(&mut self, args: &mut Variable<T>) -> Variable<T> {
        let pool_val = F::MaxPool2dArgs::default();
        let mut dropout_val = F::DropoutArgs::default();
        dropout_val.training = self.delegate.training;
        let mut x = F::relu(F::max_pool2d(self.conv1.f(args.clone()), (2, 2), &pool_val));
        x = F::relu(F::max_pool2d(F::dropout2d(self.conv2.f(x), &dropout_val),
                                  (2, 2),
                                  &pool_val));
        x = x.view([-1, 320]);
        x = F::relu(self.fc1.f(x));
        x = F::dropout(x, &dropout_val);
        x = self.fc2.f(x);
        F::log_softmax(x)
    }
}

fn train(model: &mut Net<f32>,
         args: &NetArgs,
         train_loader: &D::BatchLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf<f32>) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda(None).clone()), Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad(model);
        let output = model.f(data.clone());
        let mut loss = F::nll_loss(output, target, None, &F::NLLLossArgs::default());
        loss.backward();
        optimizer.step(model);
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
        model.free_graph();
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let varargs = VariableArgs {
            volatile: true,
            ..Default::default()
        };
        let (data, mut target) = if args.cuda {
            (Variable::new_args(data.cuda(None).clone(), &varargs),
             Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new_args(data.clone(), &varargs), Variable::new(target.clone()))
        };
        let mut output = model.f(data);
        test_loss += F::nll_loss(output.clone(),
                                 target.clone(),
                                 None,
                                 &F::NLLLossArgs::default());
        let pred = output.data().max_reduce(1, false).1;
        correct += pred.eq_tensor(&*target.data()).cpu().sum::<u32>();
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    let args = parse_args();
    let train_loader: D::BatchLoader<f32, i64> = D::DataLoader::build()
        .batch_size(args.batch_size)
        .done(datasets::MNIST::<f32>::build("../data")
                  .download(false)
                  .done(None));

    let test_loader: D::BatchLoader<f32, i64> = D::DataLoader::build()
        .batch_size(args.batch_size)
        .done(datasets::MNIST::<f32>::build("../data")
                  .train(false)
                  .done(None));
    let mut model = Net::new();
    let mut optimizer = optim::SGD::new(map_opt!{"lr" => args.lr, "momentum" => args.momentum});
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader);
    }
}
<commit_msg>compile fix after API change<commit_after>#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;
#[macro_use]
extern crate torchrs;
#[macro_use]
extern crate clap;

use torchrs::autograd::{Variable, VariableArgs, VarAccess};
use torchrs::{optim, utils, nn, tensor};
use torchrs::nn::{InitModuleStruct, GetFieldStruct, ModIntf, ModDelegate, Module};
use torchrs::nn::functional as F;
use torchrs::utils::data as D;
use torchrs::utils::torchvision::{datasets, transforms};

use clap::{Arg, App};
#[derive(Clone, Builder)]
struct NetArgs {
    #[builder(default="64")]
    batch_size: usize,
    #[builder(default="1000")]
    test_batch_size: usize,
    #[builder(default="10")]
    epochs: u32,
    #[builder(default="0.01")]
    lr: f32,
    #[builder(default="0.5")]
    momentum: f32,
    #[builder(default="false")]
    cuda: bool,
    #[builder(default="1")]
    seed: usize,
    #[builder(default="10")]
    log_interval: usize,
}

impl Default for NetArgs {
    fn default() -> Self {
        NetArgsBuilder::default().build().unwrap()
    }
}

fn parse_args() -> NetArgs {
    let mut args = NetArgs::default();
    let matches = App::new("Torch.rs MNIST Example")
        .version("0.1")
        .author("Some Guy")
        .about("recognize handwritten digits")
        .arg(Arg::with_name("batch-size").takes_value(true))
        .arg(Arg::with_name("test-batch-size").takes_value(true))
        .arg(Arg::with_name("epochs").takes_value(true))
        .arg(Arg::with_name("lr").takes_value(true))
        .arg(Arg::with_name("momentum").takes_value(true))
        .arg(Arg::with_name("no-cuda").takes_value(false))
        .arg(Arg::with_name("seed").takes_value(true))
        .arg(Arg::with_name("log-interval").takes_value(true))
        .get_matches();
    let (b_size, tb_size, epochs, lr, momentum, seed, log_int) =
        (value_t!(matches.value_of("batch-size"), usize).ok(),
         value_t!(matches.value_of("test-batch-size"), usize).ok(),
         value_t!(matches.value_of("epochs"), u32).ok(),
         value_t!(matches.value_of("lr"), f32).ok(),
         value_t!(matches.value_of("momentum"), f32).ok(),
         value_t!(matches.value_of("seed"), usize).ok(),
         value_t!(matches.value_of("log-interval"), usize).ok());
    if let Some(b_size) = b_size {
        args.batch_size = b_size
    }
    if let Some(tb_size) = tb_size {
        args.test_batch_size = tb_size
    }
    if let Some(epochs) = epochs {
        args.epochs = epochs
    }
    if let Some(lr) = lr {
        args.lr = lr
    }
    if let Some(momentum) = momentum {
        args.momentum = momentum
    }
    if let Some(seed) = seed {
        args.seed = seed
    }
    if let Some(log_int) = log_int {
        args.log_interval = log_int
    }
    //XXX CUDA?
    args
}

#[derive(ModParse)]
struct Net<T: tensor::NumLimits> {
    delegate: nn::Module<T>,
    conv1: nn::Conv2d<T>,
    conv2: nn::Conv2d<T>,
    fc1: nn::Linear<T>,
    fc2: nn::Linear<T>,
}

impl<T: tensor::NumLimits> Net<T> {
    pub fn new() -> Net<T> {
        Net {
                delegate: nn::Module::new(),
                conv1: nn::Conv2d::build(1, 10, (5, 5)).done(),
                conv2: nn::Conv2d::build(10, 20, (5, 5)).done(),
                fc1: nn::Linear::build(320, 50).done(),
                fc2: nn::Linear::build(50, 10).done(),
            }
            .init_module()
    }
}
impl_mod_delegate!(Net);

impl<T: tensor::NumLimits> ModIntf<T> for Net<T> {
    fn forward(&mut self, args: &mut Variable<T>) -> Variable<T> {
        let pool_val = F::MaxPool2dArgs::default();
        let mut dropout_val = F::DropoutArgs::default();
        dropout_val.training = self.delegate.training;
        let mut x = F::relu(F::max_pool2d(self.conv1.f(args.clone()), (2, 2), &pool_val));
        x = F::relu(F::max_pool2d(F::dropout2d(self.conv2.f(x), &dropout_val),
                                  (2, 2),
                                  &pool_val));
        x = x.view([-1, 320]);
        x = F::relu(self.fc1.f(x));
        x = F::dropout(x, &dropout_val);
        x = self.fc2.f(x);
        F::log_softmax(x)
    }
}

fn train(model: &mut Net<f32>,
         args: &NetArgs,
         train_loader: &D::BatchLoader<f32, i64>,
         epoch: u32,
         optimizer: &mut optim::OptIntf<f32>) {
    model.train();
    for (batch_idx, (ref data, ref target)) in train_loader.iter().enumerate() {
        let (mut data, target) = if args.cuda {
            (Variable::new(data.cuda(None).clone()), Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new(data.clone()), Variable::new(target.clone()))
        };
        optimizer.zero_grad(model);
        let output = model.f(data.clone());
        let mut loss = F::nll_loss(output, target, None, &F::NLLLossArgs::default());
        loss.backward();
        optimizer.step(model);
        if batch_idx % args.log_interval == 0 {
            println!("Train Epoch: {} [{}/{} ({:.0}%)]\tLoss: {:.6}",
                     epoch,
                     batch_idx * data.data().len(),
                     train_loader.dataset.len(),
                     100. * (batch_idx as f32) / train_loader.len() as f32,
                     loss.data()[0]);
        }
        model.free_graph();
    }
}

fn test(model: &mut Net<f32>, args: &NetArgs, test_loader: &D::BatchLoader<f32, i64>) {
    model.eval();
    let mut test_loss = 0.;
    let mut correct = 0;
    for (ref data, ref target) in test_loader.iter() {
        let varargs = VariableArgs {
            volatile: true,
            ..Default::default()
        };
        let (data, mut target) = if args.cuda {
            (Variable::new_args(data.cuda(None).clone(), &varargs),
             Variable::new(target.cuda(None).clone()))
        } else {
            (Variable::new_args(data.clone(), &varargs), Variable::new(target.clone()))
        };
        let mut output = model.f(data);
        test_loss += F::nll_loss(output.clone(),
                                 target.clone(),
                                 None,
                                 &F::NLLLossArgs::default());
        let pred = output.data().max_reduce(1, true).1;
        correct += pred.eq_tensor(&*target.data()).cpu().sum::<u32>();
    }
    test_loss /= test_loader.len() as f32;
    println!("\nTest set: Average loss: {:.4}, Accuracy: {}/{} ({:.0}%)\n",
             test_loss,
             correct,
             test_loader.dataset.len(),
             100. * (correct as f32) / (test_loader.dataset.len() as f32))

}

fn main() {
    let args = parse_args();
    let train_loader: D::BatchLoader<f32, i64> = D::DataLoader::build()
        .batch_size(args.batch_size)
        .done(datasets::MNIST::<f32>::build("../data")
                  .download(false)
                  .done(None));

    let test_loader: D::BatchLoader<f32, i64> = D::DataLoader::build()
        .batch_size(args.batch_size)
        .done(datasets::MNIST::<f32>::build("../data")
                  .train(false)
                  .done(None));
    let mut model = Net::new();
    let mut optimizer = optim::SGD::new(map_opt!{"lr" => args.lr, "momentum" => args.momentum});
    for epoch in 1..args.epochs + 1 {
        train(&mut model, &args, &train_loader, epoch, &mut optimizer);
        test(&mut model, &args, &test_loader);
    }
}
<|endoftext|>


<commit_before>//! SOCKSv5 protocol support

use std::comm::channel;
use std::io::{IoError, IoResult, Reader, TcpStream};
use std::io::net::ip::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::io::net::addrinfo;
use std::str;

#[allow(dead_code)]
mod consts {
    pub static VERSION_NUMBER: u8 = 0x05;

    pub mod auth {
        pub static NONE: u8 = 0x00;
    }

    pub mod atype {
        pub static IPV4:   u8 = 0x1;
        pub static IPV6:   u8 = 0x4;
        pub static DOMAIN: u8 = 0x3;
    }

    pub mod command {
        pub static CONNECT:       u8 = 0x01;
        pub static BIND:          u8 = 0x02;
        pub static UDP_ASSOCIATE: u8 = 0x04;
    }

    pub mod reply {
        pub static SUCCESS:          u8 = 0x00;
        pub static GENERAL_FAILURE:  u8 = 0x01;
        pub static CONN_DENIED:      u8 = 0x02;
        pub static NET_UNREACHABLE:  u8 = 0x03;
        pub static HOST_UNREACHABLE: u8 = 0x04;
        pub static CONN_REFUSED:     u8 = 0x05;
        pub static TTL_EXPIRED:      u8 = 0x06;
        pub static CMD_UNSUPPORTED:  u8 = 0x07;
        pub static ADDR_UNSUPPORTED: u8 = 0x08;
    }
}

struct SocksConnection<'a> {
    stream: &'a mut TcpStream
}

impl <'a> SocksConnection<'a> {
    /// Make sure that the client sends the right version number at
    /// the start of the message, or fail
    fn read_client_version(&mut self) -> IoResult<()> {
        match try!(self.stream.read_byte()) {
            consts::VERSION_NUMBER => Ok(()),
            _ => Err(IoError::last_error())
        }
    }

    /// Client -> Server:
    ///
    /// |VER | NMETHODS | METHODS  |
    /// |----+----------+----------|
    /// | 1  |    1     | 1 to 255 |
    ///
    /// Client <- Server:
    /// +----+--------+
    /// |VER | METHOD |
    /// +----+--------+
    /// | 1  |   1    |
    fn read_client_hello(&mut self) -> IoResult<()> {
        try!(self.read_client_version());

        // Number of authentication methods
        let nmethods = try!(self.stream.read_byte());

        // Authentication methods
        let methods = try!(self.stream.read_exact(nmethods as uint));

        // If the client doesn't respond to NULL-auth, we can't proceed.
        if !methods.contains(&consts::auth::NONE) {
            // Send the error back
            try!(self.stream.write(&[consts::VERSION_NUMBER, 0xFF]));

            return Err(IoError::last_error());
        }

        // Now respond that we're using NULL auth.
        try!(self.stream.write(&[consts::VERSION_NUMBER, consts::auth::NONE]));

        Ok(())
    }

    /// Client -> Server:
    /// +----+-----+-------+------+----------+----------+
    /// |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
    /// +----+-----+-------+------+----------+----------+
    /// | 1  |  1  | X'00' |  1   | Variable |    2     |
    ///
    /// o  VER    protocol version: X'05'
    /// o  CMD
    /// o  RSV    RESERVED
    /// o  ATYP   address type of following address
    /// o  DST.ADDR desired destination address
    /// o  DST.PORT desired destination port in network octet
    ///    order
    fn read_client_request(&mut self) -> IoResult<TcpStream> {
        try!(self.read_client_version());

        // Commands (for now only connect is supported)
        match try!(self.stream.read_byte()) {
            consts::command::CONNECT => (),
            _ => {
                // Tell client we don't support that command
                try!(self.send_error_reply(consts::reply::CMD_UNSUPPORTED));
                return Err(IoError::last_error());
            }
        };

        // Reserved byte
        match try!(self.stream.read_byte()) {
            0u8 => (),
            _ => { return Err(IoError::last_error()); }
        };

        // Address type
        let addr = match try!(self.stream.read_byte()) {
            // 4 bytes
            consts::atype::IPV4 => {
                let a = try!(self.stream.read_byte());
                let b = try!(self.stream.read_byte());
                let c = try!(self.stream.read_byte());
                let d = try!(self.stream.read_byte());

                Ipv4Addr(a, b, c, d)
            },

            // 16 bytes
            consts::atype::IPV6 => {
                let a = try!(self.stream.read_be_u16());
                let b = try!(self.stream.read_be_u16());
                let c = try!(self.stream.read_be_u16());
                let d = try!(self.stream.read_be_u16());
                let e = try!(self.stream.read_be_u16());
                let f = try!(self.stream.read_be_u16());
                let g = try!(self.stream.read_be_u16());
                let h = try!(self.stream.read_be_u16());

                Ipv6Addr(a, b, c, d, e, f, g, h)
            },

            // len | hostname
            consts::atype::DOMAIN => {
                let len = try!(self.stream.read_byte());
                let hostname = try!(self.stream.read_exact(len as uint));

                let mut hosts = match str::from_utf8(hostname.as_slice()) {
                    Some(host) => try!(addrinfo::get_host_addresses(host)),
                    None => { return Err(IoError::last_error()); }
                };

                match hosts.shift() {
                    Some(host) => host,
                    None => { return Err(IoError::last_error()); }
                }
            },

            // Unsupported address type
            _ => {
                try!(self.send_error_reply(consts::reply::ADDR_UNSUPPORTED));
                return Err(IoError::last_error());
            }
        };

        // Network port
        let port = try!(self.stream.read_be_u16());

        Ok(try!(TcpStream::connect_timeout(
            SocketAddr { ip: addr, port: port },
            1000)))
    }

    /// Client <- Server:
    /// +----+-----+-------+------+----------+----------+
    /// |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
    /// +----+-----+-------+------+----------+----------+
    /// | 1  |  1  | X'00' |  1   | Variable |    2     |
    ///
    ///   o  VER    protocol version: X'05'
    ///   o  REP    Reply field
    ///   o  RSV    RESERVED
    ///   o  ATYP   address type of following address
    ///   o  BND.ADDR       server bound address
    ///   o  BND.PORT       server bound port in network octet order
    fn send_reply(&mut self, rep: u8, atype: u8, addr: &[u8], port: u16) -> IoResult<()> {
        try!(self.stream.write(&[consts::VERSION_NUMBER, rep, 0x00, atype]));
        try!(self.stream.write(addr));
        try!(self.stream.write_be_u16(port));

        Ok(())
    }

    fn send_error_reply(&mut self, rep: u8) -> IoResult<()> {
        self.send_reply(rep, 0, &[0u8, 0, 0, 0], 0)
    }
}

pub fn handle_stream<'a>(client_stream: &'a mut TcpStream) -> () {
    let mut conn = SocksConnection { stream: client_stream };

    if conn.read_client_hello().is_err() {
        return;
    }

    // FIXME: A ton of probably redundant clone()s here.
    match conn.read_client_request() {
        Ok(server_stream) => {
            let (client_send, client_recv) = channel();
            let (server_send, server_recv) = channel();

            let client = conn.stream.clone();
            let server = server_stream.clone();

            // client -> server
            spawn(proc() {
                let mut client = client.clone();
                loop {
                    let mut buf = [0u8, ..4096];
                    match client.read(buf) {
                        Ok(_) => client_send.send(buf),
                        Err(_) => break
                    }
                }
            });

            // client <- server
            spawn(proc() {
                let mut server = server.clone();
                loop {
                    let mut buf = [0u8, ..4096];
                    match server.read(buf) {
                        Ok(_) => server_send.send(buf),
                        Err(_) => break
                    }
                }
            });

            loop {
                let mut client = conn.stream.clone();
                let mut server = server_stream.clone();

                let result = select! {
                    buf = client_recv.recv() => server.write(buf),
                    buf = server_recv.recv() => client.write(buf)
                };

                match result {
                    Err(e) => println!("Something broke: {}", e),
                    _ => ()
                }
            }
        },
        Err(_) => ()
    }
}
<commit_msg>shift() is deprecated, use remove(0)<commit_after>//! SOCKSv5 protocol support

use std::comm::channel;
use std::io::{IoError, IoResult, Reader, TcpStream};
use std::io::net::ip::{Ipv4Addr, Ipv6Addr, SocketAddr};
use std::io::net::addrinfo;
use std::str;

#[allow(dead_code)]
mod consts {
    pub static VERSION_NUMBER: u8 = 0x05;

    pub mod auth {
        pub static NONE: u8 = 0x00;
    }

    pub mod atype {
        pub static IPV4:   u8 = 0x1;
        pub static IPV6:   u8 = 0x4;
        pub static DOMAIN: u8 = 0x3;
    }

    pub mod command {
        pub static CONNECT:       u8 = 0x01;
        pub static BIND:          u8 = 0x02;
        pub static UDP_ASSOCIATE: u8 = 0x04;
    }

    pub mod reply {
        pub static SUCCESS:          u8 = 0x00;
        pub static GENERAL_FAILURE:  u8 = 0x01;
        pub static CONN_DENIED:      u8 = 0x02;
        pub static NET_UNREACHABLE:  u8 = 0x03;
        pub static HOST_UNREACHABLE: u8 = 0x04;
        pub static CONN_REFUSED:     u8 = 0x05;
        pub static TTL_EXPIRED:      u8 = 0x06;
        pub static CMD_UNSUPPORTED:  u8 = 0x07;
        pub static ADDR_UNSUPPORTED: u8 = 0x08;
    }
}

struct SocksConnection<'a> {
    stream: &'a mut TcpStream
}

impl <'a> SocksConnection<'a> {
    /// Make sure that the client sends the right version number at
    /// the start of the message, or fail
    fn read_client_version(&mut self) -> IoResult<()> {
        match try!(self.stream.read_byte()) {
            consts::VERSION_NUMBER => Ok(()),
            _ => Err(IoError::last_error())
        }
    }

    /// Client -> Server:
    ///
    /// |VER | NMETHODS | METHODS  |
    /// |----+----------+----------|
    /// | 1  |    1     | 1 to 255 |
    ///
    /// Client <- Server:
    /// +----+--------+
    /// |VER | METHOD |
    /// +----+--------+
    /// | 1  |   1    |
    fn read_client_hello(&mut self) -> IoResult<()> {
        try!(self.read_client_version());

        // Number of authentication methods
        let nmethods = try!(self.stream.read_byte());

        // Authentication methods
        let methods = try!(self.stream.read_exact(nmethods as uint));

        // If the client doesn't respond to NULL-auth, we can't proceed.
        if !methods.contains(&consts::auth::NONE) {
            // Send the error back
            try!(self.stream.write(&[consts::VERSION_NUMBER, 0xFF]));

            return Err(IoError::last_error());
        }

        // Now respond that we're using NULL auth.
        try!(self.stream.write(&[consts::VERSION_NUMBER, consts::auth::NONE]));

        Ok(())
    }

    /// Client -> Server:
    /// +----+-----+-------+------+----------+----------+
    /// |VER | CMD |  RSV  | ATYP | DST.ADDR | DST.PORT |
    /// +----+-----+-------+------+----------+----------+
    /// | 1  |  1  | X'00' |  1   | Variable |    2     |
    ///
    /// o  VER    protocol version: X'05'
    /// o  CMD
    /// o  RSV    RESERVED
    /// o  ATYP   address type of following address
    /// o  DST.ADDR desired destination address
    /// o  DST.PORT desired destination port in network octet
    ///    order
    fn read_client_request(&mut self) -> IoResult<TcpStream> {
        try!(self.read_client_version());

        // Commands (for now only connect is supported)
        match try!(self.stream.read_byte()) {
            consts::command::CONNECT => (),
            _ => {
                // Tell client we don't support that command
                try!(self.send_error_reply(consts::reply::CMD_UNSUPPORTED));
                return Err(IoError::last_error());
            }
        };

        // Reserved byte
        match try!(self.stream.read_byte()) {
            0u8 => (),
            _ => { return Err(IoError::last_error()); }
        };

        // Address type
        let addr = match try!(self.stream.read_byte()) {
            // 4 bytes
            consts::atype::IPV4 => {
                let a = try!(self.stream.read_byte());
                let b = try!(self.stream.read_byte());
                let c = try!(self.stream.read_byte());
                let d = try!(self.stream.read_byte());

                Ipv4Addr(a, b, c, d)
            },

            // 16 bytes
            consts::atype::IPV6 => {
                let a = try!(self.stream.read_be_u16());
                let b = try!(self.stream.read_be_u16());
                let c = try!(self.stream.read_be_u16());
                let d = try!(self.stream.read_be_u16());
                let e = try!(self.stream.read_be_u16());
                let f = try!(self.stream.read_be_u16());
                let g = try!(self.stream.read_be_u16());
                let h = try!(self.stream.read_be_u16());

                Ipv6Addr(a, b, c, d, e, f, g, h)
            },

            // len | hostname
            consts::atype::DOMAIN => {
                let len = try!(self.stream.read_byte());
                let hostname = try!(self.stream.read_exact(len as uint));

                let mut hosts = match str::from_utf8(hostname.as_slice()) {
                    Some(host) => try!(addrinfo::get_host_addresses(host)),
                    None => { return Err(IoError::last_error()); }
                };

                match hosts.remove(0) {
                    Some(host) => host,
                    None => { return Err(IoError::last_error()); }
                }
            },

            // Unsupported address type
            _ => {
                try!(self.send_error_reply(consts::reply::ADDR_UNSUPPORTED));
                return Err(IoError::last_error());
            }
        };

        // Network port
        let port = try!(self.stream.read_be_u16());

        Ok(try!(TcpStream::connect_timeout(
            SocketAddr { ip: addr, port: port },
            1000)))
    }

    /// Client <- Server:
    /// +----+-----+-------+------+----------+----------+
    /// |VER | REP |  RSV  | ATYP | BND.ADDR | BND.PORT |
    /// +----+-----+-------+------+----------+----------+
    /// | 1  |  1  | X'00' |  1   | Variable |    2     |
    ///
    ///   o  VER    protocol version: X'05'
    ///   o  REP    Reply field
    ///   o  RSV    RESERVED
    ///   o  ATYP   address type of following address
    ///   o  BND.ADDR       server bound address
    ///   o  BND.PORT       server bound port in network octet order
    fn send_reply(&mut self, rep: u8, atype: u8, addr: &[u8], port: u16) -> IoResult<()> {
        try!(self.stream.write(&[consts::VERSION_NUMBER, rep, 0x00, atype]));
        try!(self.stream.write(addr));
        try!(self.stream.write_be_u16(port));

        Ok(())
    }

    fn send_error_reply(&mut self, rep: u8) -> IoResult<()> {
        self.send_reply(rep, 0, &[0u8, 0, 0, 0], 0)
    }
}

pub fn handle_stream<'a>(client_stream: &'a mut TcpStream) -> () {
    let mut conn = SocksConnection { stream: client_stream };

    if conn.read_client_hello().is_err() {
        return;
    }

    // FIXME: A ton of probably redundant clone()s here.
    match conn.read_client_request() {
        Ok(server_stream) => {
            let (client_send, client_recv) = channel();
            let (server_send, server_recv) = channel();

            let client = conn.stream.clone();
            let server = server_stream.clone();

            // client -> server
            spawn(proc() {
                let mut client = client.clone();
                loop {
                    let mut buf = [0u8, ..4096];
                    match client.read(buf) {
                        Ok(_) => client_send.send(buf),
                        Err(_) => break
                    }
                }
            });

            // client <- server
            spawn(proc() {
                let mut server = server.clone();
                loop {
                    let mut buf = [0u8, ..4096];
                    match server.read(buf) {
                        Ok(_) => server_send.send(buf),
                        Err(_) => break
                    }
                }
            });

            loop {
                let mut client = conn.stream.clone();
                let mut server = server_stream.clone();

                let result = select! {
                    buf = client_recv.recv() => server.write(buf),
                    buf = server_recv.recv() => client.write(buf)
                };

                match result {
                    Err(e) => println!("Something broke: {}", e),
                    _ => ()
                }
            }
        },
        Err(_) => ()
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 The Evcxr Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use anyhow::{anyhow, bail, Context, Result};
use ra_ap_base_db::{FileId, SourceRoot};
use ra_ap_hir as ra_hir;
use ra_ap_ide as ra_ide;
use ra_ap_paths::AbsPathBuf;
use ra_ap_project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace};
use ra_ap_syntax::ast::{self, AstNode};
use ra_ap_vfs as ra_vfs;
use ra_ap_vfs_notify as vfs_notify;
use std::sync::mpsc;
use std::{collections::HashMap, convert::TryFrom, path::Path, sync::Arc};

pub(crate) struct RustAnalyzer {
    with_sysroot: bool,
    root_directory: AbsPathBuf,
    analysis_host: ra_ide::AnalysisHost,
    vfs: ra_vfs::Vfs,
    loader: vfs_notify::NotifyHandle,
    message_receiver: mpsc::Receiver<ra_vfs::loader::Message>,
    last_cargo_toml: Option<Vec<u8>>,
    source_file: AbsPathBuf,
    source_file_id: FileId,
    current_source: Arc<String>,
}

pub(crate) struct VariableInfo {
    /// The variable's type as Rust code.
    pub(crate) type_name: String,
    /// Whether the variable is declared as mutable.
    pub(crate) is_mutable: bool,
}

impl RustAnalyzer {
    pub(crate) fn new(root_directory: &Path) -> Result<RustAnalyzer> {
        use ra_vfs::loader::Handle;
        let (message_sender, message_receiver) = std::sync::mpsc::channel();
        let mut vfs = ra_vfs::Vfs::default();
        let root_directory = AbsPathBuf::try_from(root_directory.to_owned())
            .map_err(|path| anyhow!("Evcxr tmpdir is not absolute: '{:?}'", path))?;
        let source_file = root_directory.join("src/lib.rs");
        // We need to write the file to the filesystem even though we subsequently set the file
        // contents via the vfs and change.change_file. This is because the loader checks for the
        // files existence when determining the crate structure.
        let src_dir = root_directory.join("src");
        std::fs::create_dir_all(&src_dir)
            .with_context(|| format!("Failed to create directory `{:?}`", src_dir))?;
        std::fs::write(source_file.as_path(), "")
            .with_context(|| format!("Failed to write {:?}", source_file))?;
        // Pre-allocate an ID for our main source file.
        let vfs_source_file: ra_vfs::VfsPath = source_file.clone().into();
        vfs.set_file_contents(vfs_source_file.clone(), Some(vec![]));
        let source_file_id = vfs.file_id(&vfs_source_file.clone()).unwrap();
        Ok(RustAnalyzer {
            with_sysroot: true,
            root_directory,
            analysis_host: Default::default(),
            vfs,
            loader: vfs_notify::NotifyHandle::spawn(Box::new(move |message| {
                let _ = message_sender.send(message);
            })),
            message_receiver,
            last_cargo_toml: None,
            source_file,
            source_file_id,
            current_source: Arc::new(String::new()),
        })
    }

    pub(crate) fn set_source(&mut self, source: String) -> Result<()> {
        self.current_source = Arc::new(source.to_owned());
        let mut change = ra_ide::Change::new();

        self.vfs.set_file_contents(
            self.source_file.clone().into(),
            Some(source.bytes().collect()),
        );
        change.change_file(self.source_file_id, Some(Arc::clone(&self.current_source)));

        // Check to see if we haven't yet loaded Cargo.toml, or if it's changed since we read it.
        let cargo_toml = Some(std::fs::read(self.cargo_toml_filename()).with_context(|| {
            format!(
                "Failed to read Cargo.toml from `{:?}`",
                self.cargo_toml_filename()
            )
        })?);
        if cargo_toml != self.last_cargo_toml {
            self.load_cargo_toml(&mut change)?;
            self.last_cargo_toml = cargo_toml;
        }

        self.analysis_host.apply_change(change);
        Ok(())
    }

    /// Returns top-level variable names and their types in the specified function.
    pub(crate) fn top_level_variables(&self, function_name: &str) -> HashMap<String, VariableInfo> {
        use ra_ap_syntax::ast::{ModuleItemOwner, NameOwner};
        let mut result = HashMap::new();
        let sema = ra_ide::Semantics::new(self.analysis_host.raw_database());
        let source_file = sema.parse(self.source_file_id);
        for item in source_file.items() {
            if let ast::Item::Fn(function) = item {
                if function
                    .name()
                    .map(|n| n.text() == function_name)
                    .unwrap_or(false)
                {
                    let body = if let Some(b) = function.body() {
                        b
                    } else {
                        continue;
                    };
                    let module = sema.scope(&function.syntax()).module().unwrap();
                    for statement in body.statements() {
                        if let ast::Stmt::LetStmt(let_stmt) = statement {
                            if let Some(pat) = let_stmt.pat() {
                                if let ast::Pat::IdentPat(ident_pat) = pat.clone() {
                                    if let Some(name) = ident_pat.name() {
                                        use ra_hir::HirDisplay;
                                        if let Some(ty) = sema.type_of_pat(&pat) {
                                            if let Ok(type_name) =
                                                ty.display_source_code(sema.db, module.into())
                                            {
                                                result.insert(
                                                    name.text().to_string(),
                                                    VariableInfo {
                                                        type_name,
                                                        is_mutable: ident_pat.mut_token().is_some(),
                                                    },
                                                );
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        result
    }

    fn load_cargo_toml(&mut self, change: &mut ra_ide::Change) -> Result<()> {
        let manifest = ProjectManifest::from_manifest_file(self.cargo_toml_filename())?;
        let workspace =
            ProjectWorkspace::load(manifest, &CargoConfig::default(), self.with_sysroot).unwrap();
        let load = workspace
            .to_roots()
            .iter()
            .map(|root| {
                ra_vfs::loader::Entry::Directories(ra_vfs::loader::Directories {
                    extensions: vec!["rs".to_owned()],
                    include: root.include.clone(),
                    exclude: root.exclude.clone(),
                })
            })
            .collect();
        // Note, set_config is what triggers loading and calling the callback that we registered when we created self.loader.
        use ra_vfs::loader::Handle;
        self.loader.set_config(ra_vfs::loader::Config {
            load,
            watch: vec![],
        });

        for message in &self.message_receiver {
            match message {
                ra_vfs::loader::Message::Progress { n_total, n_done } => {
                    if n_total == n_done {
                        break;
                    }
                }
                ra_vfs::loader::Message::Loaded { files } => {
                    for (path, contents) in files {
                        let vfs_path: ra_vfs::VfsPath = path.to_path_buf().into();
                        self.vfs
                            .set_file_contents(vfs_path.clone(), contents.clone());
                    }
                }
            }
        }

        for changed_file in self.vfs.take_changes() {
            let new_contents = if changed_file.exists() {
                String::from_utf8(self.vfs.file_contents(changed_file.file_id).to_owned())
                    .ok()
                    .map(|contents| Arc::new(contents))
            } else {
                None
            };
            change.change_file(changed_file.file_id, new_contents);
        }
        change.set_roots(
            ra_vfs::file_set::FileSetConfig::default()
                .partition(&self.vfs)
                .into_iter()
                .map(|file_set| SourceRoot::new_local(file_set))
                .collect(),
        );
        change.set_crate_graph(workspace.to_crate_graph(
            None,
            &ProcMacroClient::dummy(),
            &mut |path| self.vfs.file_id(&path.to_path_buf().into()),
        ));
        Ok(())
    }

    fn cargo_toml_filename(&self) -> AbsPathBuf {
        self.root_directory.join("Cargo.toml")
    }

    pub(crate) fn completions(&self, position: usize) -> Result<Completions> {
        let mut completions = Vec::new();
        let mut range = None;
        let mut config = ra_ide::CompletionConfig {
            enable_postfix_completions: true,
            add_call_parenthesis: true,
            add_call_argument_snippets: true,
            snippet_cap: None,
        };
        config.allow_snippets(true);
        if let Ok(Some(completion_items)) = self.analysis_host.analysis().completions(
            &config,
            ra_ide::FilePosition {
                file_id: self.source_file_id,
                offset: (position as u32).into(),
            },
        ) {
            for item in completion_items {
                use regex::Regex;
                lazy_static! {
                    static ref ARG_PLACEHOLDER: Regex =
                        Regex::new("\\$\\{[0-9]+:([^}]+)\\}").unwrap();
                }
                let mut indels = item.text_edit().iter();
                if let Some(indel) = indels.next() {
                    let text_to_delete = &self.current_source[indel.delete];
                    // Rust analyzer returns all available methods/fields etc. It's up to us to
                    // decide how what we filter and what we keep.
                    if !item.lookup().starts_with(text_to_delete) {
                        continue;
                    }
                    completions.push(Completion {
                        code: ARG_PLACEHOLDER
                            .replace_all(&indel.insert, "$1")
                            .replace("$0", ""),
                    });
                    if let Some(previous_range) = range.as_ref() {
                        if *previous_range != indel.delete {
                            bail!("Different completions wanted to replace different parts of the text");
                        }
                    } else {
                        range = Some(indel.delete)
                    }
                }
                if indels.next().is_some() {
                    bail!("Completion unexpectedly provided more than one insertion/deletion");
                }
            }
        }
        Ok(Completions {
            completions,
            start_offset: range.map(|range| range.start().into()).unwrap_or(position),
            end_offset: range.map(|range| range.end().into()).unwrap_or(position),
        })
    }
}

/// Completions found in a particular context.
#[derive(Default)]
pub struct Completions {
    pub completions: Vec<Completion>,
    pub start_offset: usize,
    pub end_offset: usize,
}

/// A code completion. We use our own type rather than exposing rust-analyzer's CompletionItem,
/// since rust-analyzer is an internal implementation detail, so we don't want to expose it in a
/// public API.
#[derive(Debug, Eq, PartialEq)]
pub struct Completion {
    pub code: String,
}

/// Returns whether this appears to be a valid type. Rust analyzer, when asked to emit code for some
/// types, produces invalid code. In particular, fixed sized arrays come out without a size. e.g.
/// instead of `[i32, 5]`, we get `[i32, _]`.
pub(crate) fn is_type_valid(type_name: &str) -> bool {
    if let Ok(ty) = ast::Type::parse(&type_name) {
        for node in ty.syntax().descendants() {
            if node.kind() == ra_ap_syntax::SyntaxKind::ERROR {
                return false;
            }
        }
        return true;
    }
    false
}

#[cfg(test)]
mod test {
    use super::{is_type_valid, RustAnalyzer};
    use anyhow::Result;
    use tempfile;

    #[test]
    fn get_variable_types() -> Result<()> {
        let tmpdir = tempfile::tempdir()?;
        let mut ra = RustAnalyzer::new(tmpdir.path())?;
        ra.with_sysroot = false;
        std::fs::write(
            ra.cargo_toml_filename().to_path_buf(),
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [lib]
            "#,
        )?;

        ra.set_source(
            r#"
            fn foo() {
                let v1 = true;
                let mut v1 = 42i32;
                let v2 = &[false];
                {
                    let v2 = false;
                    let v100 = true;
                }
            }
            fn foo2() {
                let v9 = true;
            }"#
            .to_owned(),
        )?;
        let var_types = ra.top_level_variables("foo");
        assert_eq!(var_types["v1"].type_name, "i32");
        assert!(var_types["v1"].is_mutable);
        assert_eq!(var_types["v2"].type_name, "&[bool; _]");
        assert!(!var_types["v2"].is_mutable);
        assert!(var_types.get("v100").is_none());

        ra.set_source(
            r#"
            fn foo() {
                let v1 = 1u16;
            }"#
            .to_owned(),
        )?;
        let var_types = ra.top_level_variables("foo");
        assert_eq!(var_types["v1"].type_name, "u16");
        assert!(var_types.get("v2").is_none());

        Ok(())
    }

    #[test]
    fn test_is_type_valid() {
        assert!(is_type_valid("Vec<String>"));
        assert!(is_type_valid("&[i32]"));
        assert!(!is_type_valid("[i32, _]"));
    }
}
<commit_msg>Always write source file to filesystem, otherwise RA doesn't function for some reason<commit_after>// Copyright 2020 The Evcxr Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use anyhow::{anyhow, bail, Context, Result};
use ra_ap_base_db::{FileId, SourceRoot};
use ra_ap_hir as ra_hir;
use ra_ap_ide as ra_ide;
use ra_ap_paths::AbsPathBuf;
use ra_ap_project_model::{CargoConfig, ProcMacroClient, ProjectManifest, ProjectWorkspace};
use ra_ap_syntax::ast::{self, AstNode};
use ra_ap_vfs as ra_vfs;
use ra_ap_vfs_notify as vfs_notify;
use std::sync::mpsc;
use std::{collections::HashMap, convert::TryFrom, path::Path, sync::Arc};

pub(crate) struct RustAnalyzer {
    with_sysroot: bool,
    root_directory: AbsPathBuf,
    analysis_host: ra_ide::AnalysisHost,
    vfs: ra_vfs::Vfs,
    loader: vfs_notify::NotifyHandle,
    message_receiver: mpsc::Receiver<ra_vfs::loader::Message>,
    last_cargo_toml: Option<Vec<u8>>,
    source_file: AbsPathBuf,
    source_file_id: FileId,
    current_source: Arc<String>,
}

pub(crate) struct VariableInfo {
    /// The variable's type as Rust code.
    pub(crate) type_name: String,
    /// Whether the variable is declared as mutable.
    pub(crate) is_mutable: bool,
}

impl RustAnalyzer {
    pub(crate) fn new(root_directory: &Path) -> Result<RustAnalyzer> {
        use ra_vfs::loader::Handle;
        let (message_sender, message_receiver) = std::sync::mpsc::channel();
        let mut vfs = ra_vfs::Vfs::default();
        let root_directory = AbsPathBuf::try_from(root_directory.to_owned())
            .map_err(|path| anyhow!("Evcxr tmpdir is not absolute: '{:?}'", path))?;
        let source_file = root_directory.join("src/lib.rs");
        // We need to write the file to the filesystem even though we subsequently set the file
        // contents via the vfs and change.change_file. This is because the loader checks for the
        // files existence when determining the crate structure.
        let src_dir = root_directory.join("src");
        std::fs::create_dir_all(&src_dir)
            .with_context(|| format!("Failed to create directory `{:?}`", src_dir))?;
        // Pre-allocate an ID for our main source file.
        let vfs_source_file: ra_vfs::VfsPath = source_file.clone().into();
        vfs.set_file_contents(vfs_source_file.clone(), Some(vec![]));
        let source_file_id = vfs.file_id(&vfs_source_file.clone()).unwrap();
        Ok(RustAnalyzer {
            with_sysroot: true,
            root_directory,
            analysis_host: Default::default(),
            vfs,
            loader: vfs_notify::NotifyHandle::spawn(Box::new(move |message| {
                let _ = message_sender.send(message);
            })),
            message_receiver,
            last_cargo_toml: None,
            source_file,
            source_file_id,
            current_source: Arc::new(String::new()),
        })
    }

    pub(crate) fn set_source(&mut self, source: String) -> Result<()> {
        self.current_source = Arc::new(source.to_owned());
        let mut change = ra_ide::Change::new();

        std::fs::write(self.source_file.as_path(), &source)
            .with_context(|| format!("Failed to write {:?}", self.source_file))?;
        self.vfs.set_file_contents(
            self.source_file.clone().into(),
            Some(source.bytes().collect()),
        );
        change.change_file(self.source_file_id, Some(Arc::clone(&self.current_source)));

        // Check to see if we haven't yet loaded Cargo.toml, or if it's changed since we read it.
        let cargo_toml = Some(std::fs::read(self.cargo_toml_filename()).with_context(|| {
            format!(
                "Failed to read Cargo.toml from `{:?}`",
                self.cargo_toml_filename()
            )
        })?);
        if cargo_toml != self.last_cargo_toml {
            self.load_cargo_toml(&mut change)?;
            self.last_cargo_toml = cargo_toml;
        }

        self.analysis_host.apply_change(change);
        Ok(())
    }

    /// Returns top-level variable names and their types in the specified function.
    pub(crate) fn top_level_variables(&self, function_name: &str) -> HashMap<String, VariableInfo> {
        use ra_ap_syntax::ast::{ModuleItemOwner, NameOwner};
        let mut result = HashMap::new();
        let sema = ra_ide::Semantics::new(self.analysis_host.raw_database());
        let source_file = sema.parse(self.source_file_id);
        for item in source_file.items() {
            if let ast::Item::Fn(function) = item {
                if function
                    .name()
                    .map(|n| n.text() == function_name)
                    .unwrap_or(false)
                {
                    let body = if let Some(b) = function.body() {
                        b
                    } else {
                        continue;
                    };
                    let module = sema.scope(&function.syntax()).module().unwrap();
                    for statement in body.statements() {
                        if let ast::Stmt::LetStmt(let_stmt) = statement {
                            if let Some(pat) = let_stmt.pat() {
                                if let ast::Pat::IdentPat(ident_pat) = pat.clone() {
                                    if let Some(name) = ident_pat.name() {
                                        use ra_hir::HirDisplay;
                                        if let Some(ty) = sema.type_of_pat(&pat) {
                                            if let Ok(type_name) =
                                                ty.display_source_code(sema.db, module.into())
                                            {
                                                result.insert(
                                                    name.text().to_string(),
                                                    VariableInfo {
                                                        type_name,
                                                        is_mutable: ident_pat.mut_token().is_some(),
                                                    },
                                                );
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        result
    }

    fn load_cargo_toml(&mut self, change: &mut ra_ide::Change) -> Result<()> {
        let manifest = ProjectManifest::from_manifest_file(self.cargo_toml_filename())?;
        let workspace =
            ProjectWorkspace::load(manifest, &CargoConfig::default(), self.with_sysroot).unwrap();
        let load = workspace
            .to_roots()
            .iter()
            .map(|root| {
                ra_vfs::loader::Entry::Directories(ra_vfs::loader::Directories {
                    extensions: vec!["rs".to_owned()],
                    include: root.include.clone(),
                    exclude: root.exclude.clone(),
                })
            })
            .collect();
        // Note, set_config is what triggers loading and calling the callback that we registered when we created self.loader.
        use ra_vfs::loader::Handle;
        self.loader.set_config(ra_vfs::loader::Config {
            load,
            watch: vec![],
        });

        for message in &self.message_receiver {
            match message {
                ra_vfs::loader::Message::Progress { n_total, n_done } => {
                    if n_total == n_done {
                        break;
                    }
                }
                ra_vfs::loader::Message::Loaded { files } => {
                    for (path, contents) in files {
                        let vfs_path: ra_vfs::VfsPath = path.to_path_buf().into();
                        self.vfs
                            .set_file_contents(vfs_path.clone(), contents.clone());
                    }
                }
            }
        }

        for changed_file in self.vfs.take_changes() {
            let new_contents = if changed_file.exists() {
                String::from_utf8(self.vfs.file_contents(changed_file.file_id).to_owned())
                    .ok()
                    .map(|contents| Arc::new(contents))
            } else {
                None
            };
            change.change_file(changed_file.file_id, new_contents);
        }
        change.set_roots(
            ra_vfs::file_set::FileSetConfig::default()
                .partition(&self.vfs)
                .into_iter()
                .map(|file_set| SourceRoot::new_local(file_set))
                .collect(),
        );
        change.set_crate_graph(workspace.to_crate_graph(
            None,
            &ProcMacroClient::dummy(),
            &mut |path| self.vfs.file_id(&path.to_path_buf().into()),
        ));
        Ok(())
    }

    fn cargo_toml_filename(&self) -> AbsPathBuf {
        self.root_directory.join("Cargo.toml")
    }

    pub(crate) fn completions(&self, position: usize) -> Result<Completions> {
        let mut completions = Vec::new();
        let mut range = None;
        let mut config = ra_ide::CompletionConfig {
            enable_postfix_completions: true,
            add_call_parenthesis: true,
            add_call_argument_snippets: true,
            snippet_cap: None,
        };
        config.allow_snippets(true);
        if let Ok(Some(completion_items)) = self.analysis_host.analysis().completions(
            &config,
            ra_ide::FilePosition {
                file_id: self.source_file_id,
                offset: (position as u32).into(),
            },
        ) {
            for item in completion_items {
                use regex::Regex;
                lazy_static! {
                    static ref ARG_PLACEHOLDER: Regex =
                        Regex::new("\\$\\{[0-9]+:([^}]+)\\}").unwrap();
                }
                let mut indels = item.text_edit().iter();
                if let Some(indel) = indels.next() {
                    let text_to_delete = &self.current_source[indel.delete];
                    // Rust analyzer returns all available methods/fields etc. It's up to us to
                    // decide how what we filter and what we keep.
                    if !item.lookup().starts_with(text_to_delete) {
                        continue;
                    }
                    completions.push(Completion {
                        code: ARG_PLACEHOLDER
                            .replace_all(&indel.insert, "$1")
                            .replace("$0", ""),
                    });
                    if let Some(previous_range) = range.as_ref() {
                        if *previous_range != indel.delete {
                            bail!("Different completions wanted to replace different parts of the text");
                        }
                    } else {
                        range = Some(indel.delete)
                    }
                }
                if indels.next().is_some() {
                    bail!("Completion unexpectedly provided more than one insertion/deletion");
                }
            }
        }
        Ok(Completions {
            completions,
            start_offset: range.map(|range| range.start().into()).unwrap_or(position),
            end_offset: range.map(|range| range.end().into()).unwrap_or(position),
        })
    }
}

/// Completions found in a particular context.
#[derive(Default)]
pub struct Completions {
    pub completions: Vec<Completion>,
    pub start_offset: usize,
    pub end_offset: usize,
}

/// A code completion. We use our own type rather than exposing rust-analyzer's CompletionItem,
/// since rust-analyzer is an internal implementation detail, so we don't want to expose it in a
/// public API.
#[derive(Debug, Eq, PartialEq)]
pub struct Completion {
    pub code: String,
}

/// Returns whether this appears to be a valid type. Rust analyzer, when asked to emit code for some
/// types, produces invalid code. In particular, fixed sized arrays come out without a size. e.g.
/// instead of `[i32, 5]`, we get `[i32, _]`.
pub(crate) fn is_type_valid(type_name: &str) -> bool {
    if let Ok(ty) = ast::Type::parse(&type_name) {
        for node in ty.syntax().descendants() {
            if node.kind() == ra_ap_syntax::SyntaxKind::ERROR {
                return false;
            }
        }
        return true;
    }
    false
}

#[cfg(test)]
mod test {
    use super::{is_type_valid, RustAnalyzer};
    use anyhow::Result;
    use tempfile;

    #[test]
    fn get_variable_types() -> Result<()> {
        let tmpdir = tempfile::tempdir()?;
        let mut ra = RustAnalyzer::new(tmpdir.path())?;
        ra.with_sysroot = false;
        std::fs::write(
            ra.cargo_toml_filename().to_path_buf(),
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [lib]
            "#,
        )?;

        ra.set_source(
            r#"
            fn foo() {
                let v1 = true;
                let mut v1 = 42i32;
                let v2 = &[false];
                {
                    let v2 = false;
                    let v100 = true;
                }
            }
            fn foo2() {
                let v9 = true;
            }"#
            .to_owned(),
        )?;
        let var_types = ra.top_level_variables("foo");
        assert_eq!(var_types["v1"].type_name, "i32");
        assert!(var_types["v1"].is_mutable);
        assert_eq!(var_types["v2"].type_name, "&[bool; _]");
        assert!(!var_types["v2"].is_mutable);
        assert!(var_types.get("v100").is_none());

        ra.set_source(
            r#"
            fn foo() {
                let v1 = 1u16;
            }"#
            .to_owned(),
        )?;
        let var_types = ra.top_level_variables("foo");
        assert_eq!(var_types["v1"].type_name, "u16");
        assert!(var_types.get("v2").is_none());

        Ok(())
    }

    #[test]
    fn test_is_type_valid() {
        assert!(is_type_valid("Vec<String>"));
        assert!(is_type_valid("&[i32]"));
        assert!(!is_type_valid("[i32, _]"));
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Exonum blockchain framework.
//!
//! For more information see the project readme.

#![deny(missing_debug_implementations)]
#![deny(missing_docs)]

#![cfg_attr(feature="cargo-clippy", allow(zero_prefixed_literal))]

#![cfg_attr(feature="flame_profile", feature(plugin, custom_attribute))]
#![cfg_attr(feature="flame_profile", plugin(exonum_flamer))]

#[macro_use]
extern crate exonum_profiler;
#[macro_use]
extern crate log;
extern crate byteorder;
extern crate exonum_sodiumoxide as sodiumoxide;
extern crate exonum_rocksdb as rocksdb;

extern crate rand;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;
extern crate hex;
extern crate bit_vec;
extern crate vec_map;
#[cfg(test)]
extern crate tempdir;
extern crate env_logger;
extern crate colored;
extern crate term;
#[macro_use(crate_version, crate_authors)]
extern crate clap;
extern crate hyper;
extern crate iron;
extern crate iron_cors;
extern crate router;
extern crate params;
extern crate cookie;
extern crate mount;
extern crate atty;
extern crate bytes;
extern crate futures;
#[cfg(any(test, feature = "long_benchmarks"))]
extern crate tokio_timer;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_retry;

#[macro_use]
pub mod encoding;
#[macro_use]
pub mod messages;
#[macro_use]
pub mod helpers;
pub mod crypto;
#[doc(hidden)]
pub mod events;
pub mod node;
pub mod storage;
pub mod blockchain;
pub mod explorer;
pub mod api;
<commit_msg>Remove 'allow(zero_prefixed_literal)' attribute<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Exonum blockchain framework.
//!
//! For more information see the project readme.

#![deny(missing_debug_implementations, missing_docs)]

#![cfg_attr(feature="flame_profile", feature(plugin, custom_attribute))]
#![cfg_attr(feature="flame_profile", plugin(exonum_flamer))]

#[macro_use]
extern crate exonum_profiler;
#[macro_use]
extern crate log;
extern crate byteorder;
extern crate exonum_sodiumoxide as sodiumoxide;
extern crate exonum_rocksdb as rocksdb;

extern crate rand;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate toml;
extern crate hex;
extern crate bit_vec;
extern crate vec_map;
#[cfg(test)]
extern crate tempdir;
extern crate env_logger;
extern crate colored;
extern crate term;
#[macro_use(crate_version, crate_authors)]
extern crate clap;
extern crate hyper;
extern crate iron;
extern crate iron_cors;
extern crate router;
extern crate params;
extern crate cookie;
extern crate mount;
extern crate atty;
extern crate bytes;
extern crate futures;
#[cfg(any(test, feature = "long_benchmarks"))]
extern crate tokio_timer;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_retry;

#[macro_use]
pub mod encoding;
#[macro_use]
pub mod messages;
#[macro_use]
pub mod helpers;
pub mod crypto;
#[doc(hidden)]
pub mod events;
pub mod node;
pub mod storage;
pub mod blockchain;
pub mod explorer;
pub mod api;
<|endoftext|>


<commit_before>use std::collections::HashMap;

// https://leetcode.com/problems/number-of-pairs-of-interchangeable-rectangles/
pub fn interchangeable_rectangles(rectangles: Vec<Vec<i32>>) -> i64 {
    fn gcd(a: i32, b: i32) -> i32 {
        if a == b {
            return a;
        }
        if a > b {
            return gcd(a - b, b);
        }
        gcd(a, b - a)
    }

    fn series(n: i32, a: i32, b: i32) -> i64 {
        ((n as f64 / 2.0) * (a + b) as f64) as i64
    }

    let mut answer: i64 = 0;
    let mut map: HashMap<String, i32> = HashMap::new();
    for rectangle in rectangles.into_iter() {
        let gcd = gcd(rectangle[0], rectangle[1]);
        let s = format!("{}/{}", rectangle[0] / gcd, rectangle[1] / gcd);
        let count = map.get(&s).unwrap_or(&0) + 1;
        map.insert(s, count);
    }
    answer += map
        .into_iter()
        .map(|a| series(a.1 - 1, 1, a.1 - 1))
        .sum::<i64>();
    answer
}

fn main() {
    println!(
        "{}",
        interchangeable_rectangles(vec![vec![4, 8], vec![3, 6], vec![10, 20], vec![15, 30]])
    ); // 6
    println!(
        "{}",
        interchangeable_rectangles(vec![vec![4, 5], vec![7, 8]])
    ); // 0
    println!(
        "{}",
        interchangeable_rectangles(vec![vec![3, 4], vec![6, 8], vec![9, 12]])
    ); // 3
    println!(
        "{}",
        interchangeable_rectangles(vec![
            vec![4, 8],
            vec![3, 6],
            vec![10, 20],
            vec![15, 30],
            vec![3, 4],
            vec![6, 8],
            vec![9, 12]
        ])
    ); // 9
}
<commit_msg>Update problem 2001<commit_after>use std::collections::HashMap;

// https://leetcode.com/problems/number-of-pairs-of-interchangeable-rectangles/
pub fn interchangeable_rectangles(rectangles: Vec<Vec<i32>>) -> i64 {
    fn gcd(a: i32, b: i32) -> i32 {
        if a == b {
            return a;
        }
        if a > b {
            return gcd(a - b, b);
        }
        gcd(a, b - a)
    }

    fn series(n: i32, a: i32, b: i32) -> i64 {
        ((n as f64 / 2.0) * (a + b) as f64) as i64
    }

    let mut answer: i64 = 0;
    let mut map: HashMap<(i32, i32), i32> = HashMap::new();
    for rectangle in rectangles.into_iter() {
        let gcd = gcd(rectangle[0], rectangle[1]);
        let key = (rectangle[0] / gcd, rectangle[1] / gcd);
        let count = map.get(&key).unwrap_or(&0) + 1;
        map.insert(key, count);
    }
    answer += map
        .into_iter()
        .map(|a| series(a.1 - 1, 1, a.1 - 1))
        .sum::<i64>();
    answer
}

fn main() {
    println!(
        "{}",
        interchangeable_rectangles(vec![vec![4, 8], vec![3, 6], vec![10, 20], vec![15, 30]])
    ); // 6
    println!(
        "{}",
        interchangeable_rectangles(vec![vec![4, 5], vec![7, 8]])
    ); // 0
    println!(
        "{}",
        interchangeable_rectangles(vec![vec![3, 4], vec![6, 8], vec![9, 12]])
    ); // 3
    println!(
        "{}",
        interchangeable_rectangles(vec![
            vec![4, 8],
            vec![3, 6],
            vec![10, 20],
            vec![15, 30],
            vec![3, 4],
            vec![6, 8],
            vec![9, 12]
        ])
    ); // 9
}
<|endoftext|>


<commit_before>use ra_db::FileId;
use ra_syntax::ast;

use crate::db::RootDatabase;

pub fn goto_defenition(db: &RootDatabase, position: FilePosition,
) -> Cancelable<Option<Vec<NavigationTarget>>> {
    let file = db.source_file(position.file_id);
    let syntax = file.syntax();
    if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
        return Ok(Some(reference_defenition(db, position.file_id, name_ref)));
    }
    if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset)  {
        return Ok(Some(name_defenition(db, position.file_idname)));
    }
    Ok(None)
}

fn reference_defenition(db: &RootDatabase, file_id: FileId, name_ref: ast::NameRef) -> Cancelable<Vec<Nav>> {
    if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) {
        let mut rr = ReferenceResolution::new(name_ref.syntax().range());
        if let Some(fn_descr) =
            source_binder::function_from_child_node(self, position.file_id, name_ref.syntax())?
        {
            let scope = fn_descr.scopes(self);
            // First try to resolve the symbol locally
            if let Some(entry) = scope.resolve_local_name(name_ref) {
                rr.resolves_to.push(NavigationTarget {
                    file_id: position.file_id,
                    name: entry.name().to_string().into(),
                    range: entry.ptr().range(),
                    kind: NAME,
                    ptr: None,
                });
                return Ok(Some(rr));
            };
        }
        // If that fails try the index based approach.
        rr.resolves_to.extend(
            self.index_resolve(name_ref)?
                .into_iter()
                .map(NavigationTarget::from_symbol),
        );
        return Ok(Some(rr));
    }
        if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) {
            let mut rr = ReferenceResolution::new(name.syntax().range());
            if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
                if module.has_semi() {
                    if let Some(child_module) =
                        source_binder::module_from_declaration(self, position.file_id, module)?
                    {
                        let file_id = child_module.file_id();
                        let name = match child_module.name() {
                            Some(name) => name.to_string().into(),
                            None => "".into(),
                        };
                        let symbol = NavigationTarget {
                            file_id,
                            name,
                            range: TextRange::offset_len(0.into(), 0.into()),
                            kind: MODULE,
                            ptr: None,
                        };
                        rr.resolves_to.push(symbol);
                        return Ok(Some(rr));
                    }
                }
            }
        }
        Ok(None)

}
<commit_msg>kill accidentally added file<commit_after><|endoftext|>