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

/*!

The `ToStr` trait for converting to strings

*/

use str;
use hashmap::HashMap;
use container::Map;
use hash::Hash;
use cmp::Eq;

pub trait ToStr {
    fn to_str(&self) -> ~str;
}

/// Trait for converting a type to a string, consuming it in the process.
pub trait ToStrConsume {
    // Cosume and convert to a string.
    fn to_str_consume(self) -> ~str;
}

impl ToStr for bool {
    #[inline(always)]
    fn to_str(&self) -> ~str { ::bool::to_str(*self) }
}
impl ToStr for () {
    #[inline(always)]
    fn to_str(&self) -> ~str { ~"()" }
}

impl<A:ToStr> ToStr for (A,) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        match *self {
            (ref a,) => {
                ~"(" + a.to_str() + ~", " + ~")"
            }
        }
    }
}

impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"{", first = true;
        for self.each |key, value| {
            if first {
                first = false;
            }
            else {
                str::push_str(&mut acc, ~", ");
            }
            str::push_str(&mut acc, key.to_str());
            str::push_str(&mut acc, ~" : ");
            str::push_str(&mut acc, value.to_str());
        }
        str::push_char(&mut acc, '}');
        acc
    }
}

impl<A:ToStr,B:ToStr> ToStr for (A, B) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        // FIXME(#4760): this causes an llvm assertion
        //let &(ref a, ref b) = self;
        match *self {
            (ref a, ref b) => {
                ~"(" + a.to_str() + ~", " + b.to_str() + ~")"
            }
        }
    }
}
impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        // FIXME(#4760): this causes an llvm assertion
        //let &(ref a, ref b, ref c) = self;
        match *self {
            (ref a, ref b, ref c) => {
                fmt!("(%s, %s, %s)",
                    (*a).to_str(),
                    (*b).to_str(),
                    (*c).to_str()
                )
            }
        }
    }
}

impl<'self,A:ToStr> ToStr for &'self [A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

impl<A:ToStr> ToStr for ~[A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

impl<A:ToStr> ToStr for @[A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

#[cfg(test)]
#[allow(non_implicitly_copyable_typarams)]
mod tests {
    use hashmap::HashMap;
    #[test]
    fn test_simple_types() {
        assert!(1i.to_str() == ~"1");
        assert!((-1i).to_str() == ~"-1");
        assert!(200u.to_str() == ~"200");
        assert!(2u8.to_str() == ~"2");
        assert!(true.to_str() == ~"true");
        assert!(false.to_str() == ~"false");
        assert!(().to_str() == ~"()");
        assert!((~"hi").to_str() == ~"hi");
        assert!((@"hi").to_str() == ~"hi");
    }

    #[test]
    fn test_tuple_types() {
        assert!((1, 2).to_str() == ~"(1, 2)");
        assert!((~"a", ~"b", false).to_str() == ~"(a, b, false)");
        assert!(((), ((), 100)).to_str() == ~"((), ((), 100))");
    }

    #[test]
    fn test_vectors() {
        let x: ~[int] = ~[];
        assert!(x.to_str() == ~"[]");
        assert!((~[1]).to_str() == ~"[1]");
        assert!((~[1, 2, 3]).to_str() == ~"[1, 2, 3]");
        assert!((~[~[], ~[1], ~[1, 1]]).to_str() ==
               ~"[[], [1], [1, 1]]");
    }

    #[test]
    fn test_hashmap() {
        let mut table: HashMap<int, int> = HashMap::new();
        let empty: HashMap<int, int> = HashMap::new();

        table.insert(3, 4);
        table.insert(1, 2);

        let table_str = table.to_str();

        assert!(table_str == ~"{1 : 2, 3 : 4}" || table_str == ~"{3 : 4, 1 : 2}");
        assert!(empty.to_str() == ~"{}");
    }
}<commit_msg>Remove extra space between key and value.<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The `ToStr` trait for converting to strings

*/

use str;
use str::OwnedStr;
use hashmap::HashMap;
use hashmap::HashSet;
use container::Map;
use hash::Hash;
use cmp::Eq;

pub trait ToStr {
    fn to_str(&self) -> ~str;
}

/// Trait for converting a type to a string, consuming it in the process.
pub trait ToStrConsume {
    // Cosume and convert to a string.
    fn to_str_consume(self) -> ~str;
}

impl ToStr for bool {
    #[inline(always)]
    fn to_str(&self) -> ~str { ::bool::to_str(*self) }
}
impl ToStr for () {
    #[inline(always)]
    fn to_str(&self) -> ~str { ~"()" }
}

impl<A:ToStr> ToStr for (A,) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        match *self {
            (ref a,) => {
                ~"(" + a.to_str() + ~", " + ~")"
            }
        }
    }
}

impl<A:ToStr+Hash+Eq, B:ToStr+Hash+Eq> ToStr for HashMap<A, B> {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"{", first = true;
        for self.each |key, value| {
            if first {
                first = false;
            }
            else {
                acc.push_str(", ");
            }
            acc.push_str(key.to_str());
            acc.push_str(": ");
            acc.push_str(value.to_str());
        }
        acc.push_char('}');
        acc
    }
}

impl<A:ToStr,B:ToStr> ToStr for (A, B) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        // FIXME(#4760): this causes an llvm assertion
        //let &(ref a, ref b) = self;
        match *self {
            (ref a, ref b) => {
                ~"(" + a.to_str() + ~", " + b.to_str() + ~")"
            }
        }
    }
}

impl<A:ToStr,B:ToStr,C:ToStr> ToStr for (A, B, C) {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        // FIXME(#4760): this causes an llvm assertion
        //let &(ref a, ref b, ref c) = self;
        match *self {
            (ref a, ref b, ref c) => {
                fmt!("(%s, %s, %s)",
                    (*a).to_str(),
                    (*b).to_str(),
                    (*c).to_str()
                )
            }
        }
    }
}

impl<'self,A:ToStr> ToStr for &'self [A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

impl<A:ToStr> ToStr for ~[A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

impl<A:ToStr> ToStr for @[A] {
    #[inline(always)]
    fn to_str(&self) -> ~str {
        let mut acc = ~"[", first = true;
        for self.each |elt| {
            if first { first = false; }
            else { str::push_str(&mut acc, ~", "); }
            str::push_str(&mut acc, elt.to_str());
        }
        str::push_char(&mut acc, ']');
        acc
    }
}

#[cfg(test)]
#[allow(non_implicitly_copyable_typarams)]
mod tests {
    use hashmap::HashMap;
    #[test]
    fn test_simple_types() {
        assert!(1i.to_str() == ~"1");
        assert!((-1i).to_str() == ~"-1");
        assert!(200u.to_str() == ~"200");
        assert!(2u8.to_str() == ~"2");
        assert!(true.to_str() == ~"true");
        assert!(false.to_str() == ~"false");
        assert!(().to_str() == ~"()");
        assert!((~"hi").to_str() == ~"hi");
        assert!((@"hi").to_str() == ~"hi");
    }

    #[test]
    fn test_tuple_types() {
        assert!((1, 2).to_str() == ~"(1, 2)");
        assert!((~"a", ~"b", false).to_str() == ~"(a, b, false)");
        assert!(((), ((), 100)).to_str() == ~"((), ((), 100))");
    }

    #[test]
    fn test_vectors() {
        let x: ~[int] = ~[];
        assert!(x.to_str() == ~"[]");
        assert!((~[1]).to_str() == ~"[1]");
        assert!((~[1, 2, 3]).to_str() == ~"[1, 2, 3]");
        assert!((~[~[], ~[1], ~[1, 1]]).to_str() ==
               ~"[[], [1], [1, 1]]");
    }

    #[test]
    fn test_hashmap() {
        let mut table: HashMap<int, int> = HashMap::new();
        let empty: HashMap<int, int> = HashMap::new();

        table.insert(3, 4);
        table.insert(1, 2);

        let table_str = table.to_str();

        assert!(table_str == ~"{1: 2, 3: 4}" || table_str == ~"{3: 4, 1: 2}");
        assert!(empty.to_str() == ~"{}");
    }
}<|endoftext|>


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

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
mod imp {
    use self::OsRngInner::*;

    use fs::File;
    use io;
    use libc;
    use mem;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use sys::os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(any(target_arch = "arm", target_arch = "powerpc"))]
        const NR_GETRANDOM: libc::c_long = 384;
        #[cfg(target_arch = "aarch64")]
        const NR_GETRANDOM: libc::c_long = 278;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, Ordering};
        use sync::Once;

        static CHECKER: Once = Once::new();
        static AVAILABLE: AtomicBool = AtomicBool::new(false);

        CHECKER.call_once(|| {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = io::Error::last_os_error().raw_os_error();
                err != Some(libc::ENOSYS)
            } else {
                true
            };
            AVAILABLE.store(available, Ordering::Relaxed);
        });

        AVAILABLE.load(Ordering::Relaxed)
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open("/dev/urandom"));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use io;
    use mem;
    use libc::c_long;
    use sys::os::errno;
    use rand::Rng;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    extern "C" {
        fn syscall(number: c_long, ...) -> c_long;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let mut ret: c_long;

            // getentropy(2) permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                unsafe { ret = syscall(7, s.as_mut_ptr(), s.len()); }
                if ret == -1 {
                    panic!("unexpected getentropy error: {}", errno());
                }
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    #[cfg(stage0)] use prelude::v1::*;

    use io;
    use mem;
    use ptr;
    use rand::Rng;
    use libc::{c_int, size_t};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t,
                                   v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    use io;
    use mem;
    use rand::Rng;
    use sys::c;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: c::HCRYPTPROV
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
                                        c::PROV_RSA_FULL,
                                        c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
            };

            if ret == 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                c::CryptGenRandom(self.hcryptprov, v.len() as c::DWORD,
                                  v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                c::CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

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

    use sync::mpsc::channel;
    use rand::Rng;
    use super::OsRng;
    use thread;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0; 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in 0..20 {
            let (tx, rx) = channel();
            txs.push(tx);

            thread::spawn(move|| {
                // wait until all the threads are ready to go.
                rx.recv().unwrap();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                thread::yield_now();
                let mut v = [0; 1000];

                for _ in 0..100 {
                    r.next_u32();
                    thread::yield_now();
                    r.next_u64();
                    thread::yield_now();
                    r.fill_bytes(&mut v);
                    thread::yield_now();
                }
            });
        }

        // start all the threads
        for tx in &txs {
            tx.send(()).unwrap();
        }
    }
}
<commit_msg>Use a const for getentropy(2)'s syscall number<commit_after>// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Interfaces to the operating system provided random number
//! generators.

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios"), not(target_os = "openbsd")))]
mod imp {
    use self::OsRngInner::*;

    use fs::File;
    use io;
    use libc;
    use mem;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use sys::os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc")))]
    fn getrandom(buf: &mut [u8]) -> libc::c_long {
        extern "C" {
            fn syscall(number: libc::c_long, ...) -> libc::c_long;
        }

        #[cfg(target_arch = "x86_64")]
        const NR_GETRANDOM: libc::c_long = 318;
        #[cfg(target_arch = "x86")]
        const NR_GETRANDOM: libc::c_long = 355;
        #[cfg(any(target_arch = "arm", target_arch = "powerpc"))]
        const NR_GETRANDOM: libc::c_long = 384;
        #[cfg(target_arch = "aarch64")]
        const NR_GETRANDOM: libc::c_long = 278;

        unsafe {
            syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc"))))]
    fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        while read < v.len() {
            let result = getrandom(&mut v[read..]);
            if result == -1 {
                let err = errno() as libc::c_int;
                if err == libc::EINTR {
                    continue;
                } else {
                    panic!("unexpected getrandom error: {}", err);
                }
            } else {
                read += result as usize;
            }
        }
    }

    fn getrandom_next_u32() -> u32 {
        let mut buf: [u8; 4] = [0; 4];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 4], u32>(buf) }
    }

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8; 8] = [0; 8];
        getrandom_fill_bytes(&mut buf);
        unsafe { mem::transmute::<[u8; 8], u64>(buf) }
    }

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64",
                  target_arch = "x86",
                  target_arch = "arm",
                  target_arch = "aarch64",
                  target_arch = "powerpc")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, Ordering};
        use sync::Once;

        static CHECKER: Once = Once::new();
        static AVAILABLE: AtomicBool = AtomicBool::new(false);

        CHECKER.call_once(|| {
            let mut buf: [u8; 0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = io::Error::last_os_error().raw_os_error();
                err != Some(libc::ENOSYS)
            } else {
                true
            };
            AVAILABLE.store(available, Ordering::Relaxed);
        });

        AVAILABLE.load(Ordering::Relaxed)
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64",
                      target_arch = "x86",
                      target_arch = "arm",
                      target_arch = "aarch64",
                      target_arch = "powerpc"))))]
    fn is_getrandom_available() -> bool { false }

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

    enum OsRngInner {
        OsGetrandomRng,
        OsReaderRng(ReaderRng<File>),
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            if is_getrandom_available() {
                return Ok(OsRng { inner: OsGetrandomRng });
            }

            let reader = try!(File::open("/dev/urandom"));
            let reader_rng = ReaderRng::new(reader);

            Ok(OsRng { inner: OsReaderRng(reader_rng) })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u32(),
                OsReaderRng(ref mut rng) => rng.next_u32(),
            }
        }
        fn next_u64(&mut self) -> u64 {
            match self.inner {
                OsGetrandomRng => getrandom_next_u64(),
                OsReaderRng(ref mut rng) => rng.next_u64(),
            }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            match self.inner {
                OsGetrandomRng => getrandom_fill_bytes(v),
                OsReaderRng(ref mut rng) => rng.fill_bytes(v)
            }
        }
    }
}

#[cfg(target_os = "openbsd")]
mod imp {
    use io;
    use mem;
    use libc::c_long;
    use sys::os::errno;
    use rand::Rng;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    extern "C" {
        fn syscall(number: c_long, ...) -> c_long;
    }

    const NR_GETENTROPY: libc::c_long = 7;

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let mut ret: c_long;

            // getentropy(2) permits a maximum buffer size of 256 bytes
            for s in v.chunks_mut(256) {
                unsafe {
                    ret = syscall(NR_GETENTROPY, s.as_mut_ptr(), s.len());
                }
                if ret == -1 {
                    panic!("unexpected getentropy error: {}", errno());
                }
            }
        }
    }
}

#[cfg(target_os = "ios")]
mod imp {
    #[cfg(stage0)] use prelude::v1::*;

    use io;
    use mem;
    use ptr;
    use rand::Rng;
    use libc::{c_int, size_t};

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside
        // of this module
        _dummy: (),
    }

    enum SecRandom {}

    #[allow(non_upper_case_globals)]
    const kSecRandomDefault: *const SecRandom = ptr::null();

    #[link(name = "Security", kind = "framework")]
    extern "C" {
        fn SecRandomCopyBytes(rnd: *const SecRandom,
                              count: size_t, bytes: *mut u8) -> c_int;
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t,
                                   v.as_mut_ptr())
            };
            if ret == -1 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    use io;
    use mem;
    use rand::Rng;
    use sys::c;

    /// A random number generator that retrieves randomness straight from
    /// the operating system. Platform sources:
    ///
    /// - Unix-like systems (Linux, Android, Mac OSX): read directly from
    ///   `/dev/urandom`, or from `getrandom(2)` system call if available.
    /// - Windows: calls `CryptGenRandom`, using the default cryptographic
    ///   service provider with the `PROV_RSA_FULL` type.
    /// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
    /// - OpenBSD: uses the `getentropy(2)` system call.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: c::HCRYPTPROV
    }

    impl OsRng {
        /// Create a new `OsRng`.
        pub fn new() -> io::Result<OsRng> {
            let mut hcp = 0;
            let ret = unsafe {
                c::CryptAcquireContextA(&mut hcp, 0 as c::LPCSTR, 0 as c::LPCSTR,
                                        c::PROV_RSA_FULL,
                                        c::CRYPT_VERIFYCONTEXT | c::CRYPT_SILENT)
            };

            if ret == 0 {
                Err(io::Error::last_os_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0; 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0; 8];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn fill_bytes(&mut self, v: &mut [u8]) {
            let ret = unsafe {
                c::CryptGenRandom(self.hcryptprov, v.len() as c::DWORD,
                                  v.as_mut_ptr())
            };
            if ret == 0 {
                panic!("couldn't generate random bytes: {}",
                       io::Error::last_os_error());
            }
        }
    }

    impl Drop for OsRng {
        fn drop(&mut self) {
            let ret = unsafe {
                c::CryptReleaseContext(self.hcryptprov, 0)
            };
            if ret == 0 {
                panic!("couldn't release context: {}",
                       io::Error::last_os_error());
            }
        }
    }
}

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

    use sync::mpsc::channel;
    use rand::Rng;
    use super::OsRng;
    use thread;

    #[test]
    fn test_os_rng() {
        let mut r = OsRng::new().unwrap();

        r.next_u32();
        r.next_u64();

        let mut v = [0; 1000];
        r.fill_bytes(&mut v);
    }

    #[test]
    fn test_os_rng_tasks() {

        let mut txs = vec!();
        for _ in 0..20 {
            let (tx, rx) = channel();
            txs.push(tx);

            thread::spawn(move|| {
                // wait until all the threads are ready to go.
                rx.recv().unwrap();

                // deschedule to attempt to interleave things as much
                // as possible (XXX: is this a good test?)
                let mut r = OsRng::new().unwrap();
                thread::yield_now();
                let mut v = [0; 1000];

                for _ in 0..100 {
                    r.next_u32();
                    thread::yield_now();
                    r.next_u64();
                    thread::yield_now();
                    r.fill_bytes(&mut v);
                    thread::yield_now();
                }
            });
        }

        // start all the threads
        for tx in &txs {
            tx.send(()).unwrap();
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

#![feature(core)]

#[macro_use]
extern crate cgmath;

use cgmath::*;
use std::f64;
use std::num::Float;

#[test]
fn test_constructor() {
    assert_eq!(vec2(1f32, 2f32), Vector2::new(1f32, 2f32));
    assert_eq!(vec3(1f64, 2f64, 3f64), Vector3::new(1f64, 2f64, 3f64));
    assert_eq!(vec4(1is, 2is, 3is, 4is), Vector4::new(1is, 2is, 3is, 4is));
}

#[test]
fn test_from_value() {
    assert_eq!(Vector::from_value(102is), Vector2::new(102is, 102is));
    assert_eq!(Vector::from_value(22is), Vector3::new(22is, 22is, 22is));
    assert_eq!(Vector::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64));
}

#[test]
fn test_dot() {
    assert_eq!(Vector2::new(1is, 2is).dot(&Vector2::new(3is, 4is)), 11is);
    assert_eq!(Vector3::new(1is, 2is, 3is).dot(&Vector3::new(4is, 5is, 6is)), 32is);
    assert_eq!(Vector4::new(1is, 2is, 3is, 4is).dot(&Vector4::new(5is, 6is, 7is, 8is)), 70is);
}

#[test]
fn test_comp_add() {
    assert_eq!(Vector2::new(1is, 2is).comp_add(), 3is);
    assert_eq!(Vector3::new(1is, 2is, 3is).comp_add(), 6is);
    assert_eq!(Vector4::new(1is, 2is, 3is, 4is).comp_add(), 10is);

    assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_add(), 7.0f64);
    assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_add(), 15.0f64);
    assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_add(), 26.0f64);
}

#[test]
fn test_comp_mul() {
    assert_eq!(Vector2::new(1is, 2is).comp_mul(), 2is);
    assert_eq!(Vector3::new(1is, 2is, 3is).comp_mul(), 6is);
    assert_eq!(Vector4::new(1is, 2is, 3is, 4is).comp_mul(), 24is);

    assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_mul(), 12.0f64);
    assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_mul(), 120.0f64);
    assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_mul(), 1680.0f64);
}

#[test]
fn test_comp_min() {
    assert_eq!(Vector2::new(1is, 2is).comp_min(), 1is);
    assert_eq!(Vector3::new(1is, 2is, 3is).comp_min(), 1is);
    assert_eq!(Vector4::new(1is, 2is, 3is, 4is).comp_min(), 1is);

    assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_min(), 3.0f64);
    assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_min(), 4.0f64);
    assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_min(), 5.0f64);
}

#[test]
fn test_comp_max() {
    assert_eq!(Vector2::new(1is, 2is).comp_max(), 2is);
    assert_eq!(Vector3::new(1is, 2is, 3is).comp_max(), 3is);
    assert_eq!(Vector4::new(1is, 2is, 3is, 4is).comp_max(), 4is);

    assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_max(), 4.0f64);
    assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_max(), 6.0f64);
    assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_max(), 8.0f64);
}

#[test]
fn test_cross() {
    let a = Vector3::new(1is, 2is, 3is);
    let b = Vector3::new(4is, 5is, 6is);
    let r = Vector3::new(-3is, 6is, -3is);
    assert_eq!(a.cross(&b), r);

    let mut a = a;
    a.cross_self(&b);
    assert_eq!(a, r);
}

#[test]
fn test_is_perpendicular() {
    assert!(Vector2::new(1.0f64, 0.0f64).is_perpendicular(&Vector2::new(0.0f64, 1.0f64)));
    assert!(Vector3::new(0.0f64, 1.0f64, 0.0f64).is_perpendicular(&Vector3::new(0.0f64, 0.0f64, 1.0f64)));
    assert!(Vector4::new(1.0f64, 0.0f64, 0.0f64, 0.0f64).is_perpendicular(&Vector4::new(0.0f64, 0.0f64, 0.0f64, 1.0f64)));
}

#[cfg(test)]
mod test_length {
    use cgmath::*;

    #[test]
    fn test_vector2(){
        let (a, a_res) = (Vector2::new(3.0f64, 4.0f64), 5.0f64); // (3is, 4is, 5is) Pythagorean triple
        let (b, b_res) = (Vector2::new(5.0f64, 12.0f64), 13.0f64); // (5is, 12is, 13is) Pythagorean triple

        assert_eq!(a.length2(), a_res * a_res);
        assert_eq!(b.length2(), b_res * b_res);

        assert_eq!(a.length(), a_res);
        assert_eq!(b.length(), b_res);
    }

    #[test]
    fn test_vector3(){
        let (a, a_res) = (Vector3::new(2.0f64, 3.0f64, 6.0f64), 7.0f64); // (2is, 3is, 6is, 7is) Pythagorean quadruple
        let (b, b_res) = (Vector3::new(1.0f64, 4.0f64, 8.0f64), 9.0f64); // (1is, 4is, 8is, 9is) Pythagorean quadruple

        assert_eq!(a.length2(), a_res * a_res);
        assert_eq!(b.length2(), b_res * b_res);

        assert_eq!(a.length(), a_res);
        assert_eq!(b.length(), b_res);
    }

    #[test]
    fn test_vector4(){
        let (a, a_res) = (Vector4::new(1.0f64, 2.0f64, 4.0f64, 10.0f64), 11.0f64); // (1is, 2is, 4is, 10is, 11is) Pythagorean quintuple
        let (b, b_res) = (Vector4::new(1.0f64, 2.0f64, 8.0f64, 10.0f64), 13.0f64); // (1is, 2is, 8is, 10is, 13is) Pythagorean quintuple

        assert_eq!(a.length2(), a_res * a_res);
        assert_eq!(b.length2(), b_res * b_res);

        assert_eq!(a.length(), a_res);
        assert_eq!(b.length(), b_res);
    }
}

#[test]
fn test_angle() {
    assert!(Vector2::new(1.0f64, 0.0f64).angle(&Vector2::new(0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
    assert!(Vector2::new(10.0f64, 0.0f64).angle(&Vector2::new(0.0f64, 5.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
    assert!(Vector2::new(-1.0f64, 0.0f64).angle(&Vector2::new(0.0f64, 1.0f64)).approx_eq( &-rad(f64::consts::FRAC_PI_2) ));

    assert!(Vector3::new(1.0f64, 0.0f64, 1.0f64).angle(&Vector3::new(1.0f64, 1.0f64, 0.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_3) ));
    assert!(Vector3::new(10.0f64, 0.0f64, 10.0f64).angle(&Vector3::new(5.0f64, 5.0f64, 0.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_3) ));
    assert!(Vector3::new(-1.0f64, 0.0f64, -1.0f64).angle(&Vector3::new(1.0f64, -1.0f64, 0.0f64)).approx_eq( &rad(2.0f64 * f64::consts::FRAC_PI_3) ));

    assert!(Vector4::new(1.0f64, 0.0f64, 1.0f64, 0.0f64).angle(&Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
    assert!(Vector4::new(10.0f64, 0.0f64, 10.0f64, 0.0f64).angle(&Vector4::new(0.0f64, 5.0f64, 0.0f64, 5.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
    assert!(Vector4::new(-1.0f64, 0.0f64, -1.0f64, 0.0f64).angle(&Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
}

#[test]
fn test_normalize() {
    // TODO: test normalize_to, normalize_sel.0, and normalize_self_to
    assert!(Vector2::new(3.0f64, 4.0f64).normalize().approx_eq( &Vector2::new(3.0/5.0, 4.0/5.0) ));
    assert!(Vector3::new(2.0f64, 3.0f64, 6.0f64).normalize().approx_eq( &Vector3::new(2.0/7.0, 3.0/7.0, 6.0/7.0) ));
    assert!(Vector4::new(1.0f64, 2.0f64, 4.0f64, 10.0f64).normalize().approx_eq( &Vector4::new(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0) ));
}

#[test]
fn test_map() {
    assert_eq!(Vector3::new(7.12f64, 3.8f64, -6.98f64).map(|x| x.floor()), Vector3::new(7.0f64, 3.0f64, -7.0f64));
    assert_eq!(Vector3::new(7.12f64, 3.8f64, -6.98f64).map(|x| x.max(0.0f64)), Vector3::new(7.12f64, 3.8f64, 0.0f64));
}

#[test]
fn test_cast() {
    assert_approx_eq!(Vector2::new(0.9f64, 1.5).cast(), Vector2::new(0.9f32, 1.5));
    assert_approx_eq!(Vector3::new(1.0f64, 2.4, -3.13).cast(), Vector3::new(1.0f32, 2.4, -3.13));
    assert_approx_eq!(Vector4::new(13.5f64, -4.6, -8.3, 2.41).cast(), Vector4::new(13.5f32, -4.6, -8.3, 2.41));
}
<commit_msg>fix is->isize in vector<commit_after>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the AUTHORS file at the top-level directory of this distribution.
//
// 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.

#![feature(core)]

#[macro_use]
extern crate cgmath;

use cgmath::*;
use std::f64;
use std::num::Float;

#[test]
fn test_constructor() {
    assert_eq!(vec2(1f32, 2f32), Vector2::new(1f32, 2f32));
    assert_eq!(vec3(1f64, 2f64, 3f64), Vector3::new(1f64, 2f64, 3f64));
    assert_eq!(vec4(1isize, 2isize, 3isize, 4isize), Vector4::new(1isize, 2isize, 3isize, 4isize));
}

#[test]
fn test_from_value() {
    assert_eq!(Vector::from_value(102isize), Vector2::new(102isize, 102isize));
    assert_eq!(Vector::from_value(22isize), Vector3::new(22isize, 22isize, 22isize));
    assert_eq!(Vector::from_value(76.5f64), Vector4::new(76.5f64, 76.5f64, 76.5f64, 76.5f64));
}

#[test]
fn test_dot() {
    assert_eq!(Vector2::new(1isize, 2isize).dot(&Vector2::new(3isize, 4isize)), 11isize);
    assert_eq!(Vector3::new(1isize, 2isize, 3isize).dot(&Vector3::new(4isize, 5isize, 6isize)), 32isize);
    assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).dot(&Vector4::new(5isize, 6isize, 7isize, 8isize)), 70isize);
}

#[test]
fn test_comp_add() {
    assert_eq!(Vector2::new(1isize, 2isize).comp_add(), 3isize);
    assert_eq!(Vector3::new(1isize, 2isize, 3isize).comp_add(), 6isize);
    assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).comp_add(), 10isize);

    assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_add(), 7.0f64);
    assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_add(), 15.0f64);
    assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_add(), 26.0f64);
}

#[test]
fn test_comp_mul() {
    assert_eq!(Vector2::new(1isize, 2isize).comp_mul(), 2isize);
    assert_eq!(Vector3::new(1isize, 2isize, 3isize).comp_mul(), 6isize);
    assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).comp_mul(), 24isize);

    assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_mul(), 12.0f64);
    assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_mul(), 120.0f64);
    assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_mul(), 1680.0f64);
}

#[test]
fn test_comp_min() {
    assert_eq!(Vector2::new(1isize, 2isize).comp_min(), 1isize);
    assert_eq!(Vector3::new(1isize, 2isize, 3isize).comp_min(), 1isize);
    assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).comp_min(), 1isize);

    assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_min(), 3.0f64);
    assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_min(), 4.0f64);
    assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_min(), 5.0f64);
}

#[test]
fn test_comp_max() {
    assert_eq!(Vector2::new(1isize, 2isize).comp_max(), 2isize);
    assert_eq!(Vector3::new(1isize, 2isize, 3isize).comp_max(), 3isize);
    assert_eq!(Vector4::new(1isize, 2isize, 3isize, 4isize).comp_max(), 4isize);

    assert_eq!(Vector2::new(3.0f64, 4.0f64).comp_max(), 4.0f64);
    assert_eq!(Vector3::new(4.0f64, 5.0f64, 6.0f64).comp_max(), 6.0f64);
    assert_eq!(Vector4::new(5.0f64, 6.0f64, 7.0f64, 8.0f64).comp_max(), 8.0f64);
}

#[test]
fn test_cross() {
    let a = Vector3::new(1isize, 2isize, 3isize);
    let b = Vector3::new(4isize, 5isize, 6isize);
    let r = Vector3::new(-3isize, 6isize, -3isize);
    assert_eq!(a.cross(&b), r);

    let mut a = a;
    a.cross_self(&b);
    assert_eq!(a, r);
}

#[test]
fn test_is_perpendicular() {
    assert!(Vector2::new(1.0f64, 0.0f64).is_perpendicular(&Vector2::new(0.0f64, 1.0f64)));
    assert!(Vector3::new(0.0f64, 1.0f64, 0.0f64).is_perpendicular(&Vector3::new(0.0f64, 0.0f64, 1.0f64)));
    assert!(Vector4::new(1.0f64, 0.0f64, 0.0f64, 0.0f64).is_perpendicular(&Vector4::new(0.0f64, 0.0f64, 0.0f64, 1.0f64)));
}

#[cfg(test)]
mod test_length {
    use cgmath::*;

    #[test]
    fn test_vector2(){
        let (a, a_res) = (Vector2::new(3.0f64, 4.0f64), 5.0f64); // (3, 4, 5) Pythagorean triple
        let (b, b_res) = (Vector2::new(5.0f64, 12.0f64), 13.0f64); // (5, 12, 13) Pythagorean triple

        assert_eq!(a.length2(), a_res * a_res);
        assert_eq!(b.length2(), b_res * b_res);

        assert_eq!(a.length(), a_res);
        assert_eq!(b.length(), b_res);
    }

    #[test]
    fn test_vector3(){
        let (a, a_res) = (Vector3::new(2.0f64, 3.0f64, 6.0f64), 7.0f64); // (2, 3, 6, 7) Pythagorean quadruple
        let (b, b_res) = (Vector3::new(1.0f64, 4.0f64, 8.0f64), 9.0f64); // (1, 4, 8, 9) Pythagorean quadruple

        assert_eq!(a.length2(), a_res * a_res);
        assert_eq!(b.length2(), b_res * b_res);

        assert_eq!(a.length(), a_res);
        assert_eq!(b.length(), b_res);
    }

    #[test]
    fn test_vector4(){
        let (a, a_res) = (Vector4::new(1.0f64, 2.0f64, 4.0f64, 10.0f64), 11.0f64); // (1, 2, 4, 10, 11) Pythagorean quintuple
        let (b, b_res) = (Vector4::new(1.0f64, 2.0f64, 8.0f64, 10.0f64), 13.0f64); // (1, 2, 8, 10, 13) Pythagorean quintuple

        assert_eq!(a.length2(), a_res * a_res);
        assert_eq!(b.length2(), b_res * b_res);

        assert_eq!(a.length(), a_res);
        assert_eq!(b.length(), b_res);
    }
}

#[test]
fn test_angle() {
    assert!(Vector2::new(1.0f64, 0.0f64).angle(&Vector2::new(0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
    assert!(Vector2::new(10.0f64, 0.0f64).angle(&Vector2::new(0.0f64, 5.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
    assert!(Vector2::new(-1.0f64, 0.0f64).angle(&Vector2::new(0.0f64, 1.0f64)).approx_eq( &-rad(f64::consts::FRAC_PI_2) ));

    assert!(Vector3::new(1.0f64, 0.0f64, 1.0f64).angle(&Vector3::new(1.0f64, 1.0f64, 0.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_3) ));
    assert!(Vector3::new(10.0f64, 0.0f64, 10.0f64).angle(&Vector3::new(5.0f64, 5.0f64, 0.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_3) ));
    assert!(Vector3::new(-1.0f64, 0.0f64, -1.0f64).angle(&Vector3::new(1.0f64, -1.0f64, 0.0f64)).approx_eq( &rad(2.0f64 * f64::consts::FRAC_PI_3) ));

    assert!(Vector4::new(1.0f64, 0.0f64, 1.0f64, 0.0f64).angle(&Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
    assert!(Vector4::new(10.0f64, 0.0f64, 10.0f64, 0.0f64).angle(&Vector4::new(0.0f64, 5.0f64, 0.0f64, 5.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
    assert!(Vector4::new(-1.0f64, 0.0f64, -1.0f64, 0.0f64).angle(&Vector4::new(0.0f64, 1.0f64, 0.0f64, 1.0f64)).approx_eq( &rad(f64::consts::FRAC_PI_2) ));
}

#[test]
fn test_normalize() {
    // TODO: test normalize_to, normalize_sel.0, and normalize_self_to
    assert!(Vector2::new(3.0f64, 4.0f64).normalize().approx_eq( &Vector2::new(3.0/5.0, 4.0/5.0) ));
    assert!(Vector3::new(2.0f64, 3.0f64, 6.0f64).normalize().approx_eq( &Vector3::new(2.0/7.0, 3.0/7.0, 6.0/7.0) ));
    assert!(Vector4::new(1.0f64, 2.0f64, 4.0f64, 10.0f64).normalize().approx_eq( &Vector4::new(1.0/11.0, 2.0/11.0, 4.0/11.0, 10.0/11.0) ));
}

#[test]
fn test_map() {
    assert_eq!(Vector3::new(7.12f64, 3.8f64, -6.98f64).map(|x| x.floor()), Vector3::new(7.0f64, 3.0f64, -7.0f64));
    assert_eq!(Vector3::new(7.12f64, 3.8f64, -6.98f64).map(|x| x.max(0.0f64)), Vector3::new(7.12f64, 3.8f64, 0.0f64));
}

#[test]
fn test_cast() {
    assert_approx_eq!(Vector2::new(0.9f64, 1.5).cast(), Vector2::new(0.9f32, 1.5));
    assert_approx_eq!(Vector3::new(1.0f64, 2.4, -3.13).cast(), Vector3::new(1.0f32, 2.4, -3.13));
    assert_approx_eq!(Vector4::new(13.5f64, -4.6, -8.3, 2.41).cast(), Vector4::new(13.5f32, -4.6, -8.3, 2.41));
}
<|endoftext|>


<commit_before>//! An immutable map constructed at compile time.
use core::prelude::*;
use core::iter;
use core::slice;
use core::fmt;
use shared;
use shared::PhfHash;

/// An immutable map constructed at compile time.
///
/// `Map`s may be created with the `phf_map` macro:
///
/// ```rust
/// # #![feature(phase)]
/// extern crate phf;
/// #[phase(plugin)]
/// extern crate phf_mac;
///
/// static MY_MAP: phf::Map<&'static str, int> = phf_map! {
///    "hello" => 10,
///    "world" => 11,
/// };
///
/// # fn main() {}
/// ```
///
/// ## Note
///
/// The fields of this struct are public so that they may be initialized by the
/// `phf_map` macro. They are subject to change at any time and should never
/// be accessed directly.
pub struct Map<K:'static, V:'static> {
    #[doc(hidden)]
    pub key: u64,
    #[doc(hidden)]
    pub disps: &'static [(u32, u32)],
    #[doc(hidden)]
    pub entries: &'static [(K, V)],
}

impl<K, V> fmt::Show for Map<K, V> where K: fmt::Show, V: fmt::Show {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "{{"));
        let mut first = true;
        for &(ref k, ref v) in self.entries() {
            if !first {
                try!(write!(fmt, ", "));
            }
            try!(write!(fmt, "{}: {}", k, v))
            first = false;
        }
        write!(fmt, "}}")
    }
}

impl<K, V> Index<K, V> for Map<K, V> where K: PhfHash+Eq {
    fn index(&self, k: &K) -> &V {
        self.get(k).expect("invalid key")
    }
}

impl<K, V> Map<K, V> where K: PhfHash+Eq {
    /// Returns a reference to the value that `key` maps to.
    pub fn get(&self, key: &K) -> Option<&V> {
        self.get_entry_(key, |k| key == k).map(|e| &e.1)
    }

    /// Determines if `key` is in the `Map`.
    pub fn contains_key(&self, key: &K) -> bool {
        self.get(key).is_some()
    }

    /// Returns a reference to the map's internal static instance of the given
    /// key.
    ///
    /// This can be useful for interning schemes.
    pub fn get_key(&self, key: &K) -> Option<&K> {
        self.get_entry_(key, |k| key == k).map(|e| &e.0)
    }
}

impl<K, V> Map<K, V> {
    /// Returns true if the `Map` is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the number of entries in the `Map`.
    pub fn len(&self) -> uint {
        self.entries.len()
    }

    fn get_entry_<Sized? T>(&self, key: &T, check: |&K| -> bool) -> Option<&(K, V)> where T: PhfHash {
        let (g, f1, f2) = key.phf_hash(self.key);
        let (d1, d2) = self.disps[(g % (self.disps.len() as u32)) as uint];
        let entry = &self.entries[(shared::displace(f1, f2, d1, d2) % (self.entries.len() as u32))
                                  as uint];
        if check(&entry.0) {
            Some(entry)
        } else {
            None
        }
    }

    /// Like `get`, but returns both the key and the value.
    pub fn get_entry<Sized? T>(&self, key: &T) -> Option<(&K, &V)> where T: PhfHash+Equiv<K> {
        self.get_entry_(key, |k| key.equiv(k)).map(|e| (&e.0, &e.1))
    }

    /// Like `get`, but can operate on any type that is equivalent to a key.
    pub fn get_equiv<Sized? T>(&self, key: &T) -> Option<&V> where T: PhfHash+Equiv<K> {
        self.get_entry_(key, |k| key.equiv(k)).map(|e| &e.1)
    }

    /// Like `get_key`, but can operate on any type that is equivalent to a
    /// key.
    pub fn get_key_equiv<Sized? T>(&self, key: &T) -> Option<&K> where T: PhfHash+Equiv<K> {
        self.get_entry_(key, |k| key.equiv(k)).map(|e| &e.0)
    }

    /// Like `get_kv`, but can operate on any type that is equivalent to a
    /// key.
    pub fn get_kv_equiv<Sized? T>(&self, key: &T) -> Option<(&K, &V)> where T: PhfHash+Equiv<K> {
        self.get_entry_(key, |k| key.equiv(k)).map(|e| (&e.0, &e.1))
    }

    /// Returns an iterator over the key/value pairs in the map.
    ///
    /// Entries are retuned in an arbitrary but fixed order.
    pub fn entries<'a>(&'a self) -> Entries<'a, K, V> {
        Entries { iter: self.entries.iter() }
    }

    /// Returns an iterator over the keys in the map.
    ///
    /// Keys are returned in an arbitrary but fixed order.
    pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
        Keys { iter: self.entries().map(|e| &e.0) }
    }

    /// Returns an iterator over the values in the map.
    ///
    /// Values are returned in an arbitrary but fixed order.
    pub fn values<'a>(&'a self) -> Values<'a, K, V> {
        Values { iter: self.entries().map(|e | &e.1) }
    }
}

/// An iterator over the key/value pairs in a `Map`.
pub struct Entries<'a, K:'a, V:'a> {
    iter: slice::Items<'a, (K, V)>,
}

impl<'a, K, V> Iterator<&'a (K, V)> for Entries<'a, K, V> {
    fn next(&mut self) -> Option<&'a (K, V)> {
        self.iter.next()
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<'a, K, V> DoubleEndedIterator<&'a (K, V)> for Entries<'a, K, V> {
    fn next_back(&mut self) -> Option<&'a (K, V)> {
        self.iter.next_back()
    }
}

impl<'a, K, V> ExactSize<&'a (K, V)> for Entries<'a, K, V> {}

/// An iterator over the keys in a `Map`.
pub struct Keys<'a, K:'a, V:'a> {
    iter: iter::Map<'a, &'a (K, V), &'a K, Entries<'a, K, V>>,
}

impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
    fn next(&mut self) -> Option<&'a K> {
        self.iter.next()
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<'a, K, V> DoubleEndedIterator<&'a K> for Keys<'a, K, V> {
    fn next_back(&mut self) -> Option<&'a K> {
        self.iter.next_back()
    }
}

impl<'a, K, V> ExactSize<&'a K> for Keys<'a, K, V> {}

/// An iterator over the values in a `Map`.
pub struct Values<'a, K:'a, V:'a> {
    iter: iter::Map<'a, &'a (K, V), &'a V, Entries<'a, K, V>>,
}

impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
    fn next(&mut self) -> Option<&'a V> {
        self.iter.next()
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<'a, K, V> DoubleEndedIterator<&'a V> for Values<'a, K, V> {
    fn next_back(&mut self) -> Option<&'a V> {
        self.iter.next_back()
    }
}

impl<'a, K, V> ExactSize<&'a V> for Values<'a, K, V> {}
<commit_msg>s/kv/entry/<commit_after>//! An immutable map constructed at compile time.
use core::prelude::*;
use core::iter;
use core::slice;
use core::fmt;
use shared;
use shared::PhfHash;

/// An immutable map constructed at compile time.
///
/// `Map`s may be created with the `phf_map` macro:
///
/// ```rust
/// # #![feature(phase)]
/// extern crate phf;
/// #[phase(plugin)]
/// extern crate phf_mac;
///
/// static MY_MAP: phf::Map<&'static str, int> = phf_map! {
///    "hello" => 10,
///    "world" => 11,
/// };
///
/// # fn main() {}
/// ```
///
/// ## Note
///
/// The fields of this struct are public so that they may be initialized by the
/// `phf_map` macro. They are subject to change at any time and should never
/// be accessed directly.
pub struct Map<K:'static, V:'static> {
    #[doc(hidden)]
    pub key: u64,
    #[doc(hidden)]
    pub disps: &'static [(u32, u32)],
    #[doc(hidden)]
    pub entries: &'static [(K, V)],
}

impl<K, V> fmt::Show for Map<K, V> where K: fmt::Show, V: fmt::Show {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "{{"));
        let mut first = true;
        for &(ref k, ref v) in self.entries() {
            if !first {
                try!(write!(fmt, ", "));
            }
            try!(write!(fmt, "{}: {}", k, v))
            first = false;
        }
        write!(fmt, "}}")
    }
}

impl<K, V> Index<K, V> for Map<K, V> where K: PhfHash+Eq {
    fn index(&self, k: &K) -> &V {
        self.get(k).expect("invalid key")
    }
}

impl<K, V> Map<K, V> where K: PhfHash+Eq {
    /// Returns a reference to the value that `key` maps to.
    pub fn get(&self, key: &K) -> Option<&V> {
        self.get_entry_(key, |k| key == k).map(|e| &e.1)
    }

    /// Determines if `key` is in the `Map`.
    pub fn contains_key(&self, key: &K) -> bool {
        self.get(key).is_some()
    }

    /// Returns a reference to the map's internal static instance of the given
    /// key.
    ///
    /// This can be useful for interning schemes.
    pub fn get_key(&self, key: &K) -> Option<&K> {
        self.get_entry_(key, |k| key == k).map(|e| &e.0)
    }
}

impl<K, V> Map<K, V> {
    /// Returns true if the `Map` is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the number of entries in the `Map`.
    pub fn len(&self) -> uint {
        self.entries.len()
    }

    fn get_entry_<Sized? T>(&self, key: &T, check: |&K| -> bool) -> Option<&(K, V)> where T: PhfHash {
        let (g, f1, f2) = key.phf_hash(self.key);
        let (d1, d2) = self.disps[(g % (self.disps.len() as u32)) as uint];
        let entry = &self.entries[(shared::displace(f1, f2, d1, d2) % (self.entries.len() as u32))
                                  as uint];
        if check(&entry.0) {
            Some(entry)
        } else {
            None
        }
    }

    /// Like `get`, but returns both the key and the value.
    pub fn get_entry<Sized? T>(&self, key: &T) -> Option<(&K, &V)> where T: PhfHash+Equiv<K> {
        self.get_entry_(key, |k| key.equiv(k)).map(|e| (&e.0, &e.1))
    }

    /// Like `get`, but can operate on any type that is equivalent to a key.
    pub fn get_equiv<Sized? T>(&self, key: &T) -> Option<&V> where T: PhfHash+Equiv<K> {
        self.get_entry_(key, |k| key.equiv(k)).map(|e| &e.1)
    }

    /// Like `get_key`, but can operate on any type that is equivalent to a
    /// key.
    pub fn get_key_equiv<Sized? T>(&self, key: &T) -> Option<&K> where T: PhfHash+Equiv<K> {
        self.get_entry_(key, |k| key.equiv(k)).map(|e| &e.0)
    }

    /// Like `get_kv`, but can operate on any type that is equivalent to a
    /// key.
    pub fn get_entry_equiv<Sized? T>(&self, key: &T) -> Option<(&K, &V)> where T: PhfHash+Equiv<K> {
        self.get_entry_(key, |k| key.equiv(k)).map(|e| (&e.0, &e.1))
    }

    /// Returns an iterator over the key/value pairs in the map.
    ///
    /// Entries are retuned in an arbitrary but fixed order.
    pub fn entries<'a>(&'a self) -> Entries<'a, K, V> {
        Entries { iter: self.entries.iter() }
    }

    /// Returns an iterator over the keys in the map.
    ///
    /// Keys are returned in an arbitrary but fixed order.
    pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
        Keys { iter: self.entries().map(|e| &e.0) }
    }

    /// Returns an iterator over the values in the map.
    ///
    /// Values are returned in an arbitrary but fixed order.
    pub fn values<'a>(&'a self) -> Values<'a, K, V> {
        Values { iter: self.entries().map(|e | &e.1) }
    }
}

/// An iterator over the key/value pairs in a `Map`.
pub struct Entries<'a, K:'a, V:'a> {
    iter: slice::Items<'a, (K, V)>,
}

impl<'a, K, V> Iterator<&'a (K, V)> for Entries<'a, K, V> {
    fn next(&mut self) -> Option<&'a (K, V)> {
        self.iter.next()
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<'a, K, V> DoubleEndedIterator<&'a (K, V)> for Entries<'a, K, V> {
    fn next_back(&mut self) -> Option<&'a (K, V)> {
        self.iter.next_back()
    }
}

impl<'a, K, V> ExactSize<&'a (K, V)> for Entries<'a, K, V> {}

/// An iterator over the keys in a `Map`.
pub struct Keys<'a, K:'a, V:'a> {
    iter: iter::Map<'a, &'a (K, V), &'a K, Entries<'a, K, V>>,
}

impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
    fn next(&mut self) -> Option<&'a K> {
        self.iter.next()
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<'a, K, V> DoubleEndedIterator<&'a K> for Keys<'a, K, V> {
    fn next_back(&mut self) -> Option<&'a K> {
        self.iter.next_back()
    }
}

impl<'a, K, V> ExactSize<&'a K> for Keys<'a, K, V> {}

/// An iterator over the values in a `Map`.
pub struct Values<'a, K:'a, V:'a> {
    iter: iter::Map<'a, &'a (K, V), &'a V, Entries<'a, K, V>>,
}

impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
    fn next(&mut self) -> Option<&'a V> {
        self.iter.next()
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        self.iter.size_hint()
    }
}

impl<'a, K, V> DoubleEndedIterator<&'a V> for Values<'a, K, V> {
    fn next_back(&mut self) -> Option<&'a V> {
        self.iter.next_back()
    }
}

impl<'a, K, V> ExactSize<&'a V> for Values<'a, K, V> {}
<|endoftext|>


<commit_before>use std::env;
use std::process::Command;
use std::str::{self, FromStr};

// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
    let minor = match rustc_minor_version() {
        Some(minor) => minor,
        None => return,
    };

    let target = env::var("TARGET").unwrap();
    let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";

    // CString::into_boxed_c_str stabilized in Rust 1.20:
    // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
    if minor >= 20 {
        println!("cargo:rustc-cfg=de_boxed_c_str");
    }

    // From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
    // https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
    // https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
    if minor >= 21 {
        println!("cargo:rustc-cfg=de_rc_dst");
    }

    // Duration available in core since Rust 1.25:
    // https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
    if minor >= 25 {
        println!("cargo:rustc-cfg=core_duration");
    }

    // 128-bit integers stabilized in Rust 1.26:
    // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
    //
    // Disabled on Emscripten targets as Emscripten doesn't
    // currently support integers larger than 64 bits.
    if minor >= 26 && !emscripten {
        println!("cargo:rustc-cfg=integer128");
    }

    // Inclusive ranges methods stabilized in Rust 1.27:
    // https://github.com/rust-lang/rust/pull/50758
    if minor >= 27 {
        println!("cargo:rustc-cfg=range_inclusive");
    }

    // Non-zero integers stabilized in Rust 1.28:
    // https://github.com/rust-lang/rust/pull/50808
    if minor >= 28 {
        println!("cargo:rustc-cfg=num_nonzero");
    }
}

fn rustc_minor_version() -> Option<u32> {
    let rustc = match env::var_os("RUSTC") {
        Some(rustc) => rustc,
        None => return None,
    };

    let output = match Command::new(rustc).arg("--version").output() {
        Ok(output) => output,
        Err(_) => return None,
    };

    let version = match str::from_utf8(&output.stdout) {
        Ok(version) => version,
        Err(_) => return None,
    };

    // Temporary workaround to support the old 1.26-dev compiler on docs.rs.
    if version.contains("0eb87c9bf") {
        return Some(25);
    }

    let mut pieces = version.split('.');
    if pieces.next() != Some("rustc 1") {
        return None;
    }

    let next = match pieces.next() {
        Some(next) => next,
        None => return None,
    };

    u32::from_str(next).ok()
}
<commit_msg>Remove 1.26-dev docs.rs workaround<commit_after>use std::env;
use std::process::Command;
use std::str::{self, FromStr};

// The rustc-cfg strings below are *not* public API. Please let us know by
// opening a GitHub issue if your build environment requires some way to enable
// these cfgs other than by executing our build script.
fn main() {
    let minor = match rustc_minor_version() {
        Some(minor) => minor,
        None => return,
    };

    let target = env::var("TARGET").unwrap();
    let emscripten = target == "asmjs-unknown-emscripten" || target == "wasm32-unknown-emscripten";

    // CString::into_boxed_c_str stabilized in Rust 1.20:
    // https://doc.rust-lang.org/std/ffi/struct.CString.html#method.into_boxed_c_str
    if minor >= 20 {
        println!("cargo:rustc-cfg=de_boxed_c_str");
    }

    // From<Box<T>> for Rc<T> / Arc<T> stabilized in Rust 1.21:
    // https://doc.rust-lang.org/std/rc/struct.Rc.html#impl-From<Box<T>>
    // https://doc.rust-lang.org/std/sync/struct.Arc.html#impl-From<Box<T>>
    if minor >= 21 {
        println!("cargo:rustc-cfg=de_rc_dst");
    }

    // Duration available in core since Rust 1.25:
    // https://blog.rust-lang.org/2018/03/29/Rust-1.25.html#library-stabilizations
    if minor >= 25 {
        println!("cargo:rustc-cfg=core_duration");
    }

    // 128-bit integers stabilized in Rust 1.26:
    // https://blog.rust-lang.org/2018/05/10/Rust-1.26.html
    //
    // Disabled on Emscripten targets as Emscripten doesn't
    // currently support integers larger than 64 bits.
    if minor >= 26 && !emscripten {
        println!("cargo:rustc-cfg=integer128");
    }

    // Inclusive ranges methods stabilized in Rust 1.27:
    // https://github.com/rust-lang/rust/pull/50758
    if minor >= 27 {
        println!("cargo:rustc-cfg=range_inclusive");
    }

    // Non-zero integers stabilized in Rust 1.28:
    // https://github.com/rust-lang/rust/pull/50808
    if minor >= 28 {
        println!("cargo:rustc-cfg=num_nonzero");
    }
}

fn rustc_minor_version() -> Option<u32> {
    let rustc = match env::var_os("RUSTC") {
        Some(rustc) => rustc,
        None => return None,
    };

    let output = match Command::new(rustc).arg("--version").output() {
        Ok(output) => output,
        Err(_) => return None,
    };

    let version = match str::from_utf8(&output.stdout) {
        Ok(version) => version,
        Err(_) => return None,
    };

    let mut pieces = version.split('.');
    if pieces.next() != Some("rustc 1") {
        return None;
    }

    let next = match pieces.next() {
        Some(next) => next,
        None => return None,
    };

    u32::from_str(next).ok()
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::fmt;
use std::result;
use std::borrow::Cow;
use std::error::Error;

use common;
use name::{Name, OwnedName};
use attribute::Attribute;
use escape::{escape_str_attribute, escape_str_pcdata};
use common::XmlVersion;
use namespace::{NamespaceStack, NS_NO_PREFIX, NS_EMPTY_URI, NS_XMLNS_PREFIX, NS_XML_PREFIX};

use writer::config::EmitterConfig;

/// An error which may be returned by `XmlWriter` when writing XML events.
#[derive(Debug)]
pub enum EmitterError {
    /// An I/O error occured in the underlying `Write` instance.
    Io(io::Error),

    /// Document declaration has already been written to the output stream.
    DocumentStartAlreadyEmitted,

    /// The name of the last opening element is not available.
    LastElementNameNotAvailable,

    /// The name of the last opening element is not equal to the name of the provided
    /// closing element.
    EndElementNameIsNotEqualToLastStartElementName,

    /// End element name is not specified when it is needed, for example, when automatic
    /// closing is not enabled in configuration.
    EndElementNameIsNotSpecified
}

impl From<io::Error> for EmitterError {
    fn from(err: io::Error) -> EmitterError {
        EmitterError::Io(err)
    }
}

impl fmt::Display for EmitterError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        write!(f, "emitter error: ")?;
        match *self {
            EmitterError::Io(ref e) =>
                write!(f, "I/O error: {}", e),
            ref other =>
                write!(f, "{}", other.description()),
        }
    }
}

impl Error for EmitterError {
    fn description(&self) -> &str {
        match *self {
            EmitterError::Io(_) =>
                "I/O error",
            EmitterError::DocumentStartAlreadyEmitted =>
                "document start event has already been emitted",
            EmitterError::LastElementNameNotAvailable =>
                "last element name is not available",
            EmitterError::EndElementNameIsNotEqualToLastStartElementName =>
                "end element name is not equal to last start element name",
            EmitterError::EndElementNameIsNotSpecified =>
                "end element name is not specified and can't be inferred",
        }
    }
}

/// A result type yielded by `XmlWriter`.
pub type Result<T> = result::Result<T, EmitterError>;

// TODO: split into a low-level fast writer without any checks and formatting logic and a
// high-level indenting validating writer
pub struct Emitter {
    config: EmitterConfig,

    nst: NamespaceStack,

    indent_level: usize,
    indent_stack: Vec<IndentFlags>,

    element_names: Vec<OwnedName>,

    start_document_emitted: bool,
    just_wrote_start_element: bool
}

impl Emitter {
    pub fn new(config: EmitterConfig) -> Emitter {
        Emitter {
            config,

            nst: NamespaceStack::empty(),

            indent_level: 0,
            indent_stack: vec![IndentFlags::WroteNothing],

            element_names: Vec::new(),

            start_document_emitted: false,
            just_wrote_start_element: false
        }
    }
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum IndentFlags {
    WroteNothing,
    WroteMarkup,
    WroteText,
}

impl Emitter {
    /// Returns the current state of namespaces.
    #[inline]
    pub fn namespace_stack_mut(&mut self) -> &mut NamespaceStack {
        &mut self.nst
    }

    #[inline]
    fn wrote_text(&self) -> bool {
        *self.indent_stack.last().unwrap() == IndentFlags::WroteText
    }

    #[inline]
    fn wrote_markup(&self) -> bool {
        *self.indent_stack.last().unwrap() == IndentFlags::WroteMarkup
    }

    #[inline]
    fn set_wrote_text(&mut self) {
        *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteText;
    }

    #[inline]
    fn set_wrote_markup(&mut self) {
        *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteMarkup;
    }

    #[inline]
    fn reset_state(&mut self) {
        *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteNothing;
    }

    fn write_newline<W: Write>(&mut self, target: &mut W, level: usize) -> Result<()> {
        target.write(self.config.line_separator.as_bytes())?;
        for _ in 0..level {
            target.write(self.config.indent_string.as_bytes())?;
        }
        Ok(())
    }

    fn before_markup<W: Write>(&mut self, target: &mut W) -> Result<()> {
        if self.config.perform_indent && !self.wrote_text() &&
           (self.indent_level > 0 || self.wrote_markup()) {
            let indent_level = self.indent_level;
            self.write_newline(target, indent_level)?;
            if self.indent_level > 0 && self.config.indent_string.len() > 0 {
                self.after_markup();
            }
        }
        Ok(())
    }

    fn after_markup(&mut self) {
        self.set_wrote_markup();
    }

    fn before_start_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
        self.before_markup(target)?;
        self.indent_stack.push(IndentFlags::WroteNothing);
        Ok(())
    }

    fn after_start_element(&mut self) {
        self.after_markup();
        self.indent_level += 1;
    }

    fn before_end_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
        if self.config.perform_indent && self.indent_level > 0 && self.wrote_markup() &&
           !self.wrote_text() {
            let indent_level = self.indent_level;
            self.write_newline(target, indent_level - 1)
        } else {
            Ok(())
        }
    }

    fn after_end_element(&mut self) {
        if self.indent_level > 0 {
            self.indent_level -= 1;
            self.indent_stack.pop();
        }
        self.set_wrote_markup();
    }

    fn after_text(&mut self) {
        self.set_wrote_text();
    }

    pub fn emit_start_document<W: Write>(&mut self, target: &mut W,
                                         version: XmlVersion,
                                         encoding: &str,
                                         standalone: Option<bool>) -> Result<()> {
        if self.start_document_emitted {
            return Err(EmitterError::DocumentStartAlreadyEmitted);
        }
        self.start_document_emitted = true;

        self.before_markup(target)?;
        let result = {
            let mut write = move || {
                write!(target, "<?xml version=\"{}\" encoding=\"{}\"", version, encoding)?;

                if let Some(standalone) = standalone {
                    write!(target, " standalone=\"{}\"", if standalone { "yes" } else { "no" })?;
                }

                write!(target, "?>")?;

                Ok(())
            };
            write()
        };
        self.after_markup();

        result
    }

    fn check_document_started<W: Write>(&mut self, target: &mut W) -> Result<()> {
        if !self.start_document_emitted && self.config.write_document_declaration {
            self.emit_start_document(target, common::XmlVersion::Version10, "utf-8", None)
        } else {
            Ok(())
        }
    }

    fn fix_non_empty_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
        if self.config.normalize_empty_elements && self.just_wrote_start_element {
            self.just_wrote_start_element = false;
            target.write(b">").map(|_| ()).map_err(From::from)
        } else {
            Ok(())
        }
    }

    pub fn emit_processing_instruction<W: Write>(&mut self,
                                                 target: &mut W,
                                                 name: &str,
                                                 data: Option<&str>) -> Result<()> {
        self.check_document_started(target)?;
        self.fix_non_empty_element(target)?;

        self.before_markup(target)?;

        let result = {
            let mut write = || {
                write!(target, "<?{}", name)?;

                if let Some(data) = data {
                    write!(target, " {}", data)?;
                }

                write!(target, "?>")?;

                Ok(())
            };
            write()
        };

        self.after_markup();

        result
    }

    fn emit_start_element_initial<W>(&mut self, target: &mut W,
                                     name: Name,
                                     attributes: &[Attribute]) -> Result<()>
        where W: Write
    {
        self.check_document_started(target)?;
        self.fix_non_empty_element(target)?;
        self.before_start_element(target)?;
        write!(target, "<{}", name.repr_display())?;
        self.emit_current_namespace_attributes(target)?;
        self.emit_attributes(target, attributes)?;
        self.after_start_element();
        Ok(())
    }

    pub fn emit_start_element<W>(&mut self, target: &mut W,
                                 name: Name,
                                 attributes: &[Attribute]) -> Result<()>
        where W: Write
    {
        if self.config.keep_element_names_stack {
            self.element_names.push(name.to_owned());
        }

        self.emit_start_element_initial(target, name, attributes)?;
        self.just_wrote_start_element = true;

        if !self.config.normalize_empty_elements {
            write!(target, ">")?;
        }

        Ok(())
    }

    pub fn emit_current_namespace_attributes<W>(&mut self, target: &mut W) -> Result<()>
        where W: Write
    {
        for (prefix, uri) in self.nst.peek() {
            match prefix {
                // internal namespaces are not emitted
                NS_XMLNS_PREFIX | NS_XML_PREFIX => Ok(()),
                //// there is already a namespace binding with this prefix in scope
                //prefix if self.nst.get(prefix) == Some(uri) => Ok(()),
                // emit xmlns only if it is overridden
                NS_NO_PREFIX => if uri != NS_EMPTY_URI {
                    write!(target, " xmlns=\"{}\"", uri)
                } else { Ok(()) },
                // everything else
                prefix => write!(target, " xmlns:{}=\"{}\"", prefix, uri)
            }?;
        }
        Ok(())
    }

    pub fn emit_attributes<W: Write>(&mut self, target: &mut W,
                                      attributes: &[Attribute]) -> Result<()> {
        for attr in attributes.iter() {
            write!(
                target, " {}=\"{}\"",
                attr.name.repr_display(),
                if self.config.perform_escaping { escape_str_attribute(attr.value) } else { Cow::Borrowed(attr.value) }
            )?
        }
        Ok(())
    }

    pub fn emit_end_element<W: Write>(&mut self, target: &mut W,
                                      name: Option<Name>) -> Result<()> {
        let owned_name = if self.config.keep_element_names_stack {
            Some(self.element_names.pop().ok_or(EmitterError::LastElementNameNotAvailable)?)
        } else {
            None
        };

        // Check that last started element name equals to the provided name, if there are both
        if let Some(ref last_name) = owned_name {
            if let Some(ref name) = name {
                if last_name.borrow() != *name {
                    return Err(EmitterError::EndElementNameIsNotEqualToLastStartElementName);
                }
            }
        }

        if let Some(name) = owned_name.as_ref().map(|n| n.borrow()).or(name) {
            if self.config.normalize_empty_elements && self.just_wrote_start_element {
                self.just_wrote_start_element = false;
                let termination = if self.config.pad_self_closing { " />" } else { "/>" };
                let result = target.write(termination.as_bytes()).map_err(From::from);
                self.after_end_element();
                result.map(|_| ())
            } else {
                self.just_wrote_start_element = false;

                self.before_end_element(target)?;
                let result = write!(target, "</{}>", name.repr_display()).map_err(From::from);
                self.after_end_element();

                result
            }
        } else {
            Err(EmitterError::EndElementNameIsNotSpecified)
        }
    }

    pub fn emit_cdata<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
        self.fix_non_empty_element(target)?;
        if self.config.cdata_to_characters {
            self.emit_characters(target, content)
        } else {
            // TODO: escape ']]>' characters in CDATA as two adjacent CDATA blocks
            target.write(b"<![CDATA[")?;
            target.write(content.as_bytes())?;
            target.write(b"]]>")?;

            self.after_text();

            Ok(())
        }
    }

    pub fn emit_characters<W: Write>(&mut self, target: &mut W,
                                      content: &str) -> Result<()> {
        self.fix_non_empty_element(target)?;
        target.write(
            (if self.config.perform_escaping {
                escape_str_pcdata(content)
            } else {
                Cow::Borrowed(content)
            }).as_bytes()
        )?;
        self.after_text();
        Ok(())
    }

    pub fn emit_comment<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
        self.fix_non_empty_element(target)?;

        // TODO: add escaping dashes at the end of the comment

        let autopad_comments = self.config.autopad_comments;
        let write = |target: &mut W| -> Result<()> {
            target.write(b"<!--")?;

            if autopad_comments && !content.starts_with(char::is_whitespace) {
                target.write(b" ")?;
            }

            target.write(content.as_bytes())?;

            if autopad_comments && !content.ends_with(char::is_whitespace) {
                target.write(b" ")?;
            }

            target.write(b"-->")?;

            Ok(())
        };

        self.before_markup(target)?;
        let result = write(target);
        self.after_markup();

        result
    }
}
<commit_msg>Force XML document declaration to be output before characters<commit_after>use std::io;
use std::io::prelude::*;
use std::fmt;
use std::result;
use std::borrow::Cow;
use std::error::Error;

use common;
use name::{Name, OwnedName};
use attribute::Attribute;
use escape::{escape_str_attribute, escape_str_pcdata};
use common::XmlVersion;
use namespace::{NamespaceStack, NS_NO_PREFIX, NS_EMPTY_URI, NS_XMLNS_PREFIX, NS_XML_PREFIX};

use writer::config::EmitterConfig;

/// An error which may be returned by `XmlWriter` when writing XML events.
#[derive(Debug)]
pub enum EmitterError {
    /// An I/O error occured in the underlying `Write` instance.
    Io(io::Error),

    /// Document declaration has already been written to the output stream.
    DocumentStartAlreadyEmitted,

    /// The name of the last opening element is not available.
    LastElementNameNotAvailable,

    /// The name of the last opening element is not equal to the name of the provided
    /// closing element.
    EndElementNameIsNotEqualToLastStartElementName,

    /// End element name is not specified when it is needed, for example, when automatic
    /// closing is not enabled in configuration.
    EndElementNameIsNotSpecified
}

impl From<io::Error> for EmitterError {
    fn from(err: io::Error) -> EmitterError {
        EmitterError::Io(err)
    }
}

impl fmt::Display for EmitterError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {

        write!(f, "emitter error: ")?;
        match *self {
            EmitterError::Io(ref e) =>
                write!(f, "I/O error: {}", e),
            ref other =>
                write!(f, "{}", other.description()),
        }
    }
}

impl Error for EmitterError {
    fn description(&self) -> &str {
        match *self {
            EmitterError::Io(_) =>
                "I/O error",
            EmitterError::DocumentStartAlreadyEmitted =>
                "document start event has already been emitted",
            EmitterError::LastElementNameNotAvailable =>
                "last element name is not available",
            EmitterError::EndElementNameIsNotEqualToLastStartElementName =>
                "end element name is not equal to last start element name",
            EmitterError::EndElementNameIsNotSpecified =>
                "end element name is not specified and can't be inferred",
        }
    }
}

/// A result type yielded by `XmlWriter`.
pub type Result<T> = result::Result<T, EmitterError>;

// TODO: split into a low-level fast writer without any checks and formatting logic and a
// high-level indenting validating writer
pub struct Emitter {
    config: EmitterConfig,

    nst: NamespaceStack,

    indent_level: usize,
    indent_stack: Vec<IndentFlags>,

    element_names: Vec<OwnedName>,

    start_document_emitted: bool,
    just_wrote_start_element: bool
}

impl Emitter {
    pub fn new(config: EmitterConfig) -> Emitter {
        Emitter {
            config,

            nst: NamespaceStack::empty(),

            indent_level: 0,
            indent_stack: vec![IndentFlags::WroteNothing],

            element_names: Vec::new(),

            start_document_emitted: false,
            just_wrote_start_element: false
        }
    }
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
enum IndentFlags {
    WroteNothing,
    WroteMarkup,
    WroteText,
}

impl Emitter {
    /// Returns the current state of namespaces.
    #[inline]
    pub fn namespace_stack_mut(&mut self) -> &mut NamespaceStack {
        &mut self.nst
    }

    #[inline]
    fn wrote_text(&self) -> bool {
        *self.indent_stack.last().unwrap() == IndentFlags::WroteText
    }

    #[inline]
    fn wrote_markup(&self) -> bool {
        *self.indent_stack.last().unwrap() == IndentFlags::WroteMarkup
    }

    #[inline]
    fn set_wrote_text(&mut self) {
        *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteText;
    }

    #[inline]
    fn set_wrote_markup(&mut self) {
        *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteMarkup;
    }

    #[inline]
    fn reset_state(&mut self) {
        *self.indent_stack.last_mut().unwrap() = IndentFlags::WroteNothing;
    }

    fn write_newline<W: Write>(&mut self, target: &mut W, level: usize) -> Result<()> {
        target.write(self.config.line_separator.as_bytes())?;
        for _ in 0..level {
            target.write(self.config.indent_string.as_bytes())?;
        }
        Ok(())
    }

    fn before_markup<W: Write>(&mut self, target: &mut W) -> Result<()> {
        if self.config.perform_indent && !self.wrote_text() &&
           (self.indent_level > 0 || self.wrote_markup()) {
            let indent_level = self.indent_level;
            self.write_newline(target, indent_level)?;
            if self.indent_level > 0 && self.config.indent_string.len() > 0 {
                self.after_markup();
            }
        }
        Ok(())
    }

    fn after_markup(&mut self) {
        self.set_wrote_markup();
    }

    fn before_start_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
        self.before_markup(target)?;
        self.indent_stack.push(IndentFlags::WroteNothing);
        Ok(())
    }

    fn after_start_element(&mut self) {
        self.after_markup();
        self.indent_level += 1;
    }

    fn before_end_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
        if self.config.perform_indent && self.indent_level > 0 && self.wrote_markup() &&
           !self.wrote_text() {
            let indent_level = self.indent_level;
            self.write_newline(target, indent_level - 1)
        } else {
            Ok(())
        }
    }

    fn after_end_element(&mut self) {
        if self.indent_level > 0 {
            self.indent_level -= 1;
            self.indent_stack.pop();
        }
        self.set_wrote_markup();
    }

    fn after_text(&mut self) {
        self.set_wrote_text();
    }

    pub fn emit_start_document<W: Write>(&mut self, target: &mut W,
                                         version: XmlVersion,
                                         encoding: &str,
                                         standalone: Option<bool>) -> Result<()> {
        if self.start_document_emitted {
            return Err(EmitterError::DocumentStartAlreadyEmitted);
        }
        self.start_document_emitted = true;

        self.before_markup(target)?;
        let result = {
            let mut write = move || {
                write!(target, "<?xml version=\"{}\" encoding=\"{}\"", version, encoding)?;

                if let Some(standalone) = standalone {
                    write!(target, " standalone=\"{}\"", if standalone { "yes" } else { "no" })?;
                }

                write!(target, "?>")?;

                Ok(())
            };
            write()
        };
        self.after_markup();

        result
    }

    fn check_document_started<W: Write>(&mut self, target: &mut W) -> Result<()> {
        if !self.start_document_emitted && self.config.write_document_declaration {
            self.emit_start_document(target, common::XmlVersion::Version10, "utf-8", None)
        } else {
            Ok(())
        }
    }

    fn fix_non_empty_element<W: Write>(&mut self, target: &mut W) -> Result<()> {
        if self.config.normalize_empty_elements && self.just_wrote_start_element {
            self.just_wrote_start_element = false;
            target.write(b">").map(|_| ()).map_err(From::from)
        } else {
            Ok(())
        }
    }

    pub fn emit_processing_instruction<W: Write>(&mut self,
                                                 target: &mut W,
                                                 name: &str,
                                                 data: Option<&str>) -> Result<()> {
        self.check_document_started(target)?;
        self.fix_non_empty_element(target)?;

        self.before_markup(target)?;

        let result = {
            let mut write = || {
                write!(target, "<?{}", name)?;

                if let Some(data) = data {
                    write!(target, " {}", data)?;
                }

                write!(target, "?>")?;

                Ok(())
            };
            write()
        };

        self.after_markup();

        result
    }

    fn emit_start_element_initial<W>(&mut self, target: &mut W,
                                     name: Name,
                                     attributes: &[Attribute]) -> Result<()>
        where W: Write
    {
        self.check_document_started(target)?;
        self.fix_non_empty_element(target)?;
        self.before_start_element(target)?;
        write!(target, "<{}", name.repr_display())?;
        self.emit_current_namespace_attributes(target)?;
        self.emit_attributes(target, attributes)?;
        self.after_start_element();
        Ok(())
    }

    pub fn emit_start_element<W>(&mut self, target: &mut W,
                                 name: Name,
                                 attributes: &[Attribute]) -> Result<()>
        where W: Write
    {
        if self.config.keep_element_names_stack {
            self.element_names.push(name.to_owned());
        }

        self.emit_start_element_initial(target, name, attributes)?;
        self.just_wrote_start_element = true;

        if !self.config.normalize_empty_elements {
            write!(target, ">")?;
        }

        Ok(())
    }

    pub fn emit_current_namespace_attributes<W>(&mut self, target: &mut W) -> Result<()>
        where W: Write
    {
        for (prefix, uri) in self.nst.peek() {
            match prefix {
                // internal namespaces are not emitted
                NS_XMLNS_PREFIX | NS_XML_PREFIX => Ok(()),
                //// there is already a namespace binding with this prefix in scope
                //prefix if self.nst.get(prefix) == Some(uri) => Ok(()),
                // emit xmlns only if it is overridden
                NS_NO_PREFIX => if uri != NS_EMPTY_URI {
                    write!(target, " xmlns=\"{}\"", uri)
                } else { Ok(()) },
                // everything else
                prefix => write!(target, " xmlns:{}=\"{}\"", prefix, uri)
            }?;
        }
        Ok(())
    }

    pub fn emit_attributes<W: Write>(&mut self, target: &mut W,
                                      attributes: &[Attribute]) -> Result<()> {
        for attr in attributes.iter() {
            write!(
                target, " {}=\"{}\"",
                attr.name.repr_display(),
                if self.config.perform_escaping { escape_str_attribute(attr.value) } else { Cow::Borrowed(attr.value) }
            )?
        }
        Ok(())
    }

    pub fn emit_end_element<W: Write>(&mut self, target: &mut W,
                                      name: Option<Name>) -> Result<()> {
        let owned_name = if self.config.keep_element_names_stack {
            Some(self.element_names.pop().ok_or(EmitterError::LastElementNameNotAvailable)?)
        } else {
            None
        };

        // Check that last started element name equals to the provided name, if there are both
        if let Some(ref last_name) = owned_name {
            if let Some(ref name) = name {
                if last_name.borrow() != *name {
                    return Err(EmitterError::EndElementNameIsNotEqualToLastStartElementName);
                }
            }
        }

        if let Some(name) = owned_name.as_ref().map(|n| n.borrow()).or(name) {
            if self.config.normalize_empty_elements && self.just_wrote_start_element {
                self.just_wrote_start_element = false;
                let termination = if self.config.pad_self_closing { " />" } else { "/>" };
                let result = target.write(termination.as_bytes()).map_err(From::from);
                self.after_end_element();
                result.map(|_| ())
            } else {
                self.just_wrote_start_element = false;

                self.before_end_element(target)?;
                let result = write!(target, "</{}>", name.repr_display()).map_err(From::from);
                self.after_end_element();

                result
            }
        } else {
            Err(EmitterError::EndElementNameIsNotSpecified)
        }
    }

    pub fn emit_cdata<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
        self.fix_non_empty_element(target)?;
        if self.config.cdata_to_characters {
            self.emit_characters(target, content)
        } else {
            // TODO: escape ']]>' characters in CDATA as two adjacent CDATA blocks
            target.write(b"<![CDATA[")?;
            target.write(content.as_bytes())?;
            target.write(b"]]>")?;

            self.after_text();

            Ok(())
        }
    }

    pub fn emit_characters<W: Write>(&mut self, target: &mut W,
                                      content: &str) -> Result<()> {
        self.check_document_started(target)?;
        self.fix_non_empty_element(target)?;
        target.write(
            (if self.config.perform_escaping {
                escape_str_pcdata(content)
            } else {
                Cow::Borrowed(content)
            }).as_bytes()
        )?;
        self.after_text();
        Ok(())
    }

    pub fn emit_comment<W: Write>(&mut self, target: &mut W, content: &str) -> Result<()> {
        self.fix_non_empty_element(target)?;

        // TODO: add escaping dashes at the end of the comment

        let autopad_comments = self.config.autopad_comments;
        let write = |target: &mut W| -> Result<()> {
            target.write(b"<!--")?;

            if autopad_comments && !content.starts_with(char::is_whitespace) {
                target.write(b" ")?;
            }

            target.write(content.as_bytes())?;

            if autopad_comments && !content.ends_with(char::is_whitespace) {
                target.write(b" ")?;
            }

            target.write(b"-->")?;

            Ok(())
        };

        self.before_markup(target)?;
        let result = write(target);
        self.after_markup();

        result
    }
}
<|endoftext|>