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

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

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::Result::{Ok, Err};
    use slice::SliceExt;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    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(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

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

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

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v.slice_from_mut(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 uint;
            }
        }
    }

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

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8, ..8] = [0u8, ..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")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL;
        static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8, ..0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    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.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

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

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

            let reader = try!(File::open(&Path::new("/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 = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use mem;
    use os;
    use rand::Rng;
    use result::Result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::SliceExt;

    /// 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.
    ///
    /// This does not block.
    #[allow(missing_copy_implementations)]
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside of this module
        _dummy: (),
    }

    #[repr(C)]
    struct SecRandom;

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[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() -> IoResult<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 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: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::Result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::SliceExt;

    type HCRYPTPROV = LONG_PTR;

    /// 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.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

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

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

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

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

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

    use super::OsRng;
    use rand::Rng;
    use thread::Thread;

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

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

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

    #[test]
    fn test_os_rng_tasks() {

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

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

                // 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 = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    Thread::yield_now();
                    r.next_u64();
                    Thread::yield_now();
                    r.fill_bytes(&mut v);
                    Thread::yield_now();
                }
            }).detach();
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<commit_msg>iOS: fallout of Sync oibit<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

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

pub use self::imp::OsRng;

#[cfg(all(unix, not(target_os = "ios")))]
mod imp {
    extern crate libc;

    use self::OsRngInner::*;

    use io::{IoResult, File};
    use path::Path;
    use rand::Rng;
    use rand::reader::ReaderRng;
    use result::Result::{Ok, Err};
    use slice::SliceExt;
    use mem;
    use os::errno;

    #[cfg(all(target_os = "linux",
              any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm")))]
    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(target_arch = "arm")]
        const NR_GETRANDOM: libc::c_long = 384;

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

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

    fn getrandom_fill_bytes(v: &mut [u8]) {
        let mut read = 0;
        let len = v.len();
        while read < len {
            let result = getrandom(v.slice_from_mut(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 uint;
            }
        }
    }

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

    fn getrandom_next_u64() -> u64 {
        let mut buf: [u8, ..8] = [0u8, ..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")))]
    fn is_getrandom_available() -> bool {
        use sync::atomic::{AtomicBool, INIT_ATOMIC_BOOL, Relaxed};

        static GETRANDOM_CHECKED: AtomicBool = INIT_ATOMIC_BOOL;
        static GETRANDOM_AVAILABLE: AtomicBool = INIT_ATOMIC_BOOL;

        if !GETRANDOM_CHECKED.load(Relaxed) {
            let mut buf: [u8, ..0] = [];
            let result = getrandom(&mut buf);
            let available = if result == -1 {
                let err = errno() as libc::c_int;
                err != libc::ENOSYS
            } else {
                true
            };
            GETRANDOM_AVAILABLE.store(available, Relaxed);
            GETRANDOM_CHECKED.store(true, Relaxed);
            available
        } else {
            GETRANDOM_AVAILABLE.load(Relaxed)
        }
    }

    #[cfg(not(all(target_os = "linux",
                  any(target_arch = "x86_64", target_arch = "x86", target_arch = "arm"))))]
    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.
    ///
    /// This does not block.
    pub struct OsRng {
        inner: OsRngInner,
    }

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

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

            let reader = try!(File::open(&Path::new("/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 = "ios")]
mod imp {
    extern crate libc;

    use io::{IoResult};
    use kinds::Sync;
    use mem;
    use os;
    use rand::Rng;
    use result::Result::{Ok};
    use self::libc::{c_int, size_t};
    use slice::SliceExt;

    /// 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.
    ///
    /// This does not block.
    #[allow(missing_copy_implementations)]
    pub struct OsRng {
        // dummy field to ensure that this struct cannot be constructed outside of this module
        _dummy: (),
    }

    #[repr(C)]
    struct SecRandom;

    unsafe impl Sync for *const SecRandom {}

    #[allow(non_upper_case_globals)]
    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;

    #[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() -> IoResult<OsRng> {
            Ok(OsRng { _dummy: () })
        }
    }

    impl Rng for OsRng {
        fn next_u32(&mut self) -> u32 {
            let mut v = [0u8, .. 4];
            self.fill_bytes(&mut v);
            unsafe { mem::transmute(v) }
        }
        fn next_u64(&mut self) -> u64 {
            let mut v = [0u8, .. 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: {}", os::last_os_error());
            }
        }
    }
}

#[cfg(windows)]
mod imp {
    extern crate libc;

    use io::{IoResult, IoError};
    use mem;
    use ops::Drop;
    use os;
    use rand::Rng;
    use result::Result::{Ok, Err};
    use self::libc::{DWORD, BYTE, LPCSTR, BOOL};
    use self::libc::types::os::arch::extra::{LONG_PTR};
    use slice::SliceExt;

    type HCRYPTPROV = LONG_PTR;

    /// 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.
    ///
    /// This does not block.
    pub struct OsRng {
        hcryptprov: HCRYPTPROV
    }

    static PROV_RSA_FULL: DWORD = 1;
    static CRYPT_SILENT: DWORD = 64;
    static CRYPT_VERIFYCONTEXT: DWORD = 0xF0000000;

    #[allow(non_snake_case)]
    extern "system" {
        fn CryptAcquireContextA(phProv: *mut HCRYPTPROV,
                                pszContainer: LPCSTR,
                                pszProvider: LPCSTR,
                                dwProvType: DWORD,
                                dwFlags: DWORD) -> BOOL;
        fn CryptGenRandom(hProv: HCRYPTPROV,
                          dwLen: DWORD,
                          pbBuffer: *mut BYTE) -> BOOL;
        fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) -> BOOL;
    }

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

            if ret == 0 {
                Err(IoError::last_error())
            } else {
                Ok(OsRng { hcryptprov: hcp })
            }
        }
    }

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

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

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

    use super::OsRng;
    use rand::Rng;
    use thread::Thread;

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

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

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

    #[test]
    fn test_os_rng_tasks() {

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

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

                // 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 = [0u8, .. 1000];

                for _ in range(0u, 100) {
                    r.next_u32();
                    Thread::yield_now();
                    r.next_u64();
                    Thread::yield_now();
                    r.fill_bytes(&mut v);
                    Thread::yield_now();
                }
            }).detach();
        }

        // start all the tasks
        for tx in txs.iter() {
            tx.send(())
        }
    }
}
<|endoftext|>


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

use libc;
use uint;
use option::{Some, None};
use cell::Cell;
use clone::Clone;
use container::Container;
use iterator::IteratorUtil;
use vec::{OwnedVector, MutableVector};
use super::io::net::ip::{IpAddr, Ipv4, Ipv6};
use rt::sched::Scheduler;
use rt::local::Local;
use unstable::run_in_bare_thread;
use rt::thread::Thread;
use rt::task::Task;
use rt::uv::uvio::UvEventLoop;
use rt::work_queue::WorkQueue;
use rt::sleeper_list::SleeperList;
use rt::task::{Sched};
use rt::comm::oneshot;
use result::{Result, Ok, Err};

pub fn new_test_uv_sched() -> Scheduler {

    let mut sched = Scheduler::new(~UvEventLoop::new(),
                                   WorkQueue::new(),
                                   SleeperList::new());
    // Don't wait for the Shutdown message
    sched.no_sleep = true;
    return sched;
}

/// Creates a new scheduler in a new thread and runs a task in it,
/// then waits for the scheduler to exit. Failure of the task
/// will abort the process.
pub fn run_in_newsched_task(f: ~fn()) {
    let f = Cell::new(f);

    do run_in_bare_thread {
        let mut sched = ~new_test_uv_sched();
        let on_exit: ~fn(bool) = |exit_status| rtassert!(exit_status);
        let mut task = ~Task::new_root(&mut sched.stack_pool,
                                       f.take());
        rtdebug!("newsched_task: %x", to_uint(task));
        task.on_exit = Some(on_exit);
        sched.enqueue_task(task);
        sched.run();
    }
}

/// Create more than one scheduler and run a function in a task
/// in one of the schedulers. The schedulers will stay alive
/// until the function `f` returns.
pub fn run_in_mt_newsched_task(f: ~fn()) {
    use os;
    use from_str::FromStr;
    use rt::sched::Shutdown;
    use rt::util;

    let f_cell = Cell::new(f);

    do run_in_bare_thread {
        let nthreads = match os::getenv("RUST_TEST_THREADS") {
            Some(nstr) => FromStr::from_str(nstr).get(),
            None => {
                // Using more threads than cores in test code
                // to force the OS to preempt them frequently.
                // Assuming that this help stress test concurrent types.
                util::num_cpus() * 2
            }
        };

        let sleepers = SleeperList::new();
        let work_queue = WorkQueue::new();

        let mut handles = ~[];
        let mut scheds = ~[];

        for uint::range(0, nthreads) |_| {
            let loop_ = ~UvEventLoop::new();
            let mut sched = ~Scheduler::new(loop_,
                                            work_queue.clone(),
                                            sleepers.clone());
            let handle = sched.make_handle();

            handles.push(handle);
            scheds.push(sched);
        }

        let f_cell = Cell::new(f_cell.take());
        let handles = Cell::new(handles);
        let on_exit: ~fn(bool) = |exit_status| {
            let mut handles = handles.take();
            // Tell schedulers to exit
            for handles.mut_iter().advance |handle| {
                handle.send(Shutdown);
            }

            rtassert!(exit_status);
        };
        let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool,
                                        f_cell.take());
        main_task.on_exit = Some(on_exit);
        scheds[0].enqueue_task(main_task);

        let mut threads = ~[];

        while !scheds.is_empty() {
            let sched = scheds.pop();
            let sched_cell = Cell::new(sched);
            let thread = do Thread::start {
                let sched = sched_cell.take();
                sched.run();
            };

            threads.push(thread);
        }

        // Wait for schedulers
        let _threads = threads;
    }

}

/// Test tasks will abort on failure instead of unwinding
pub fn spawntask(f: ~fn()) {
    use super::sched::*;
    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        rtdebug!("spawntask taking the scheduler from TLS");

        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool, f.take())
        }
    };

    rtdebug!("new task pointer: %x", to_uint(task));

    let sched = Local::take::<Scheduler>();
    rtdebug!("spawntask scheduling the new task");
    sched.schedule_task(task);
}

/// Create a new task and run it right now. Aborts on failure
pub fn spawntask_immediately(f: ~fn()) {
    use super::sched::*;

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())
        }
    };

    let sched = Local::take::<Scheduler>();
    do sched.switch_running_tasks_and_then(task) |sched, task| {
        sched.enqueue_task(task);
    }
}

/// Create a new task and run it right now. Aborts on failure
pub fn spawntask_later(f: ~fn()) {
    use super::sched::*;
    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool, f.take())
        }
    };

    let mut sched = Local::take::<Scheduler>();
    sched.enqueue_task(task);
    Local::put(sched);
}

/// Spawn a task and either run it immediately or run it later
pub fn spawntask_random(f: ~fn()) {
    use super::sched::*;
    use rand::{Rand, rng};

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())

        }
    };

    let mut sched = Local::take::<Scheduler>();

    let mut rng = rng();
    let run_now: bool = Rand::rand(&mut rng);

    if run_now {
        do sched.switch_running_tasks_and_then(task) |sched, task| {
            sched.enqueue_task(task);
        }
    } else {
        sched.enqueue_task(task);
        Local::put(sched);
    }
}

/// Spawn a task, with the current scheduler as home, and queue it to
/// run later.
pub fn spawntask_homed(scheds: &mut ~[~Scheduler], f: ~fn()) {
    use super::sched::*;
    use rand::{rng, RngUtil};
    let mut rng = rng();

    let task = {
        let sched = &mut scheds[rng.gen_int_range(0,scheds.len() as int)];
        let handle = sched.make_handle();
        let home_id = handle.sched_id;

        // now that we know where this is going, build a new function
        // that can assert it is in the right place
        let af: ~fn() = || {
            do Local::borrow::<Scheduler,()>() |sched| {
                rtdebug!("home_id: %u, runtime loc: %u",
                         home_id,
                         sched.sched_id());
                assert!(home_id == sched.sched_id());
            };
            f()
        };

        ~Task::new_root_homed(&mut sched.stack_pool,
                              Sched(handle),
                              af)
    };
    let dest_sched = &mut scheds[rng.gen_int_range(0,scheds.len() as int)];
    // enqueue it for future execution
    dest_sched.enqueue_task(task);
}

/// Spawn a task and wait for it to finish, returning whether it
/// completed successfully or failed
pub fn spawntask_try(f: ~fn()) -> Result<(), ()> {
    use cell::Cell;
    use super::sched::*;

    let f = Cell::new(f);

    let (port, chan) = oneshot();
    let chan = Cell::new(chan);
    let on_exit: ~fn(bool) = |exit_status| chan.take().send(exit_status);
    let mut new_task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task> |_running_task| {

            // I don't understand why using a child task here fails. I
            // think the fail status is propogating back up the task
            // tree and triggering a fail for the parent, which we
            // aren't correctly expecting.

            // ~running_task.new_child(&mut (*sched).stack_pool,
            ~Task::new_root(&mut (*sched).stack_pool,
                           f.take())
        }
    };
    new_task.on_exit = Some(on_exit);

    let sched = Local::take::<Scheduler>();
    do sched.switch_running_tasks_and_then(new_task) |sched, old_task| {
        sched.enqueue_task(old_task);
    }

    rtdebug!("enqueued the new task, now waiting on exit_status");

    let exit_status = port.recv();
    if exit_status { Ok(()) } else { Err(()) }
}

// Spawn a new task in a new scheduler and return a thread handle.
pub fn spawntask_thread(f: ~fn()) -> Thread {
    use rt::sched::*;

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())
        }
    };

    let task = Cell::new(task);

    let thread = do Thread::start {
        let mut sched = ~new_test_uv_sched();
        sched.enqueue_task(task.take());
        sched.run();
    };
    return thread;
}

/// Get a port number, starting at 9600, for use in tests
pub fn next_test_port() -> u16 {
    unsafe {
        return rust_dbg_next_port(base_port() as libc::uintptr_t) as u16;
    }
    extern {
        fn rust_dbg_next_port(base: libc::uintptr_t) -> libc::uintptr_t;
    }
}

/// Get a unique IPv4 localhost:port pair starting at 9600
pub fn next_test_ip4() -> IpAddr {
    Ipv4(127, 0, 0, 1, next_test_port())
}

/// Get a unique IPv6 localhost:port pair starting at 9600
pub fn next_test_ip6() -> IpAddr {
    Ipv6(0, 0, 0, 0, 0, 0, 0, 1, next_test_port())
}

/*
XXX: Welcome to MegaHack City.

The bots run multiple builds at the same time, and these builds
all want to use ports. This function figures out which workspace
it is running in and assigns a port range based on it.
*/
fn base_port() -> uint {
    use os;
    use str::StrSlice;
    use to_str::ToStr;
    use vec::ImmutableVector;

    let base = 9600u;
    let range = 1000;

    let bases = [
        ("32-opt", base + range * 1),
        ("32-noopt", base + range * 2),
        ("64-opt", base + range * 3),
        ("64-noopt", base + range * 4),
        ("64-opt-vg", base + range * 5),
        ("all-opt", base + range * 6),
        ("snap3", base + range * 7),
        ("dist", base + range * 8)
    ];

    let path = os::getcwd().to_str();

    let mut final_base = base;

    for bases.iter().advance |&(dir, base)| {
        if path.contains(dir) {
            final_base = base;
            break;
        }
    }

    return final_base;
}

/// Get a constant that represents the number of times to repeat
/// stress tests. Default 1.
pub fn stress_factor() -> uint {
    use os::getenv;

    match getenv("RUST_RT_STRESS") {
        Some(val) => uint::from_str(val).get(),
        None => 1
    }
}
<commit_msg>std::rt: Use a constant 4 threads for multithreaded sched tests. #7772<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use libc;
use uint;
use option::{Some, None};
use cell::Cell;
use clone::Clone;
use container::Container;
use iterator::IteratorUtil;
use vec::{OwnedVector, MutableVector};
use super::io::net::ip::{IpAddr, Ipv4, Ipv6};
use rt::sched::Scheduler;
use rt::local::Local;
use unstable::run_in_bare_thread;
use rt::thread::Thread;
use rt::task::Task;
use rt::uv::uvio::UvEventLoop;
use rt::work_queue::WorkQueue;
use rt::sleeper_list::SleeperList;
use rt::task::{Sched};
use rt::comm::oneshot;
use result::{Result, Ok, Err};

pub fn new_test_uv_sched() -> Scheduler {

    let mut sched = Scheduler::new(~UvEventLoop::new(),
                                   WorkQueue::new(),
                                   SleeperList::new());
    // Don't wait for the Shutdown message
    sched.no_sleep = true;
    return sched;
}

/// Creates a new scheduler in a new thread and runs a task in it,
/// then waits for the scheduler to exit. Failure of the task
/// will abort the process.
pub fn run_in_newsched_task(f: ~fn()) {
    let f = Cell::new(f);

    do run_in_bare_thread {
        let mut sched = ~new_test_uv_sched();
        let on_exit: ~fn(bool) = |exit_status| rtassert!(exit_status);
        let mut task = ~Task::new_root(&mut sched.stack_pool,
                                       f.take());
        rtdebug!("newsched_task: %x", to_uint(task));
        task.on_exit = Some(on_exit);
        sched.enqueue_task(task);
        sched.run();
    }
}

/// Create more than one scheduler and run a function in a task
/// in one of the schedulers. The schedulers will stay alive
/// until the function `f` returns.
pub fn run_in_mt_newsched_task(f: ~fn()) {
    use os;
    use from_str::FromStr;
    use rt::sched::Shutdown;

    let f_cell = Cell::new(f);

    do run_in_bare_thread {
        let nthreads = match os::getenv("RUST_TEST_THREADS") {
            Some(nstr) => FromStr::from_str(nstr).get(),
            None => {
                // A reasonable number of threads for testing
                // multithreading. NB: It's easy to exhaust OS X's
                // low maximum fd limit by setting this too high (#7772)
                4
            }
        };

        let sleepers = SleeperList::new();
        let work_queue = WorkQueue::new();

        let mut handles = ~[];
        let mut scheds = ~[];

        for uint::range(0, nthreads) |_| {
            let loop_ = ~UvEventLoop::new();
            let mut sched = ~Scheduler::new(loop_,
                                            work_queue.clone(),
                                            sleepers.clone());
            let handle = sched.make_handle();

            handles.push(handle);
            scheds.push(sched);
        }

        let f_cell = Cell::new(f_cell.take());
        let handles = Cell::new(handles);
        let on_exit: ~fn(bool) = |exit_status| {
            let mut handles = handles.take();
            // Tell schedulers to exit
            for handles.mut_iter().advance |handle| {
                handle.send(Shutdown);
            }

            rtassert!(exit_status);
        };
        let mut main_task = ~Task::new_root(&mut scheds[0].stack_pool,
                                        f_cell.take());
        main_task.on_exit = Some(on_exit);
        scheds[0].enqueue_task(main_task);

        let mut threads = ~[];

        while !scheds.is_empty() {
            let sched = scheds.pop();
            let sched_cell = Cell::new(sched);
            let thread = do Thread::start {
                let sched = sched_cell.take();
                sched.run();
            };

            threads.push(thread);
        }

        // Wait for schedulers
        let _threads = threads;
    }

}

/// Test tasks will abort on failure instead of unwinding
pub fn spawntask(f: ~fn()) {
    use super::sched::*;
    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        rtdebug!("spawntask taking the scheduler from TLS");

        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool, f.take())
        }
    };

    rtdebug!("new task pointer: %x", to_uint(task));

    let sched = Local::take::<Scheduler>();
    rtdebug!("spawntask scheduling the new task");
    sched.schedule_task(task);
}

/// Create a new task and run it right now. Aborts on failure
pub fn spawntask_immediately(f: ~fn()) {
    use super::sched::*;

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())
        }
    };

    let sched = Local::take::<Scheduler>();
    do sched.switch_running_tasks_and_then(task) |sched, task| {
        sched.enqueue_task(task);
    }
}

/// Create a new task and run it right now. Aborts on failure
pub fn spawntask_later(f: ~fn()) {
    use super::sched::*;
    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool, f.take())
        }
    };

    let mut sched = Local::take::<Scheduler>();
    sched.enqueue_task(task);
    Local::put(sched);
}

/// Spawn a task and either run it immediately or run it later
pub fn spawntask_random(f: ~fn()) {
    use super::sched::*;
    use rand::{Rand, rng};

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())

        }
    };

    let mut sched = Local::take::<Scheduler>();

    let mut rng = rng();
    let run_now: bool = Rand::rand(&mut rng);

    if run_now {
        do sched.switch_running_tasks_and_then(task) |sched, task| {
            sched.enqueue_task(task);
        }
    } else {
        sched.enqueue_task(task);
        Local::put(sched);
    }
}

/// Spawn a task, with the current scheduler as home, and queue it to
/// run later.
pub fn spawntask_homed(scheds: &mut ~[~Scheduler], f: ~fn()) {
    use super::sched::*;
    use rand::{rng, RngUtil};
    let mut rng = rng();

    let task = {
        let sched = &mut scheds[rng.gen_int_range(0,scheds.len() as int)];
        let handle = sched.make_handle();
        let home_id = handle.sched_id;

        // now that we know where this is going, build a new function
        // that can assert it is in the right place
        let af: ~fn() = || {
            do Local::borrow::<Scheduler,()>() |sched| {
                rtdebug!("home_id: %u, runtime loc: %u",
                         home_id,
                         sched.sched_id());
                assert!(home_id == sched.sched_id());
            };
            f()
        };

        ~Task::new_root_homed(&mut sched.stack_pool,
                              Sched(handle),
                              af)
    };
    let dest_sched = &mut scheds[rng.gen_int_range(0,scheds.len() as int)];
    // enqueue it for future execution
    dest_sched.enqueue_task(task);
}

/// Spawn a task and wait for it to finish, returning whether it
/// completed successfully or failed
pub fn spawntask_try(f: ~fn()) -> Result<(), ()> {
    use cell::Cell;
    use super::sched::*;

    let f = Cell::new(f);

    let (port, chan) = oneshot();
    let chan = Cell::new(chan);
    let on_exit: ~fn(bool) = |exit_status| chan.take().send(exit_status);
    let mut new_task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task> |_running_task| {

            // I don't understand why using a child task here fails. I
            // think the fail status is propogating back up the task
            // tree and triggering a fail for the parent, which we
            // aren't correctly expecting.

            // ~running_task.new_child(&mut (*sched).stack_pool,
            ~Task::new_root(&mut (*sched).stack_pool,
                           f.take())
        }
    };
    new_task.on_exit = Some(on_exit);

    let sched = Local::take::<Scheduler>();
    do sched.switch_running_tasks_and_then(new_task) |sched, old_task| {
        sched.enqueue_task(old_task);
    }

    rtdebug!("enqueued the new task, now waiting on exit_status");

    let exit_status = port.recv();
    if exit_status { Ok(()) } else { Err(()) }
}

// Spawn a new task in a new scheduler and return a thread handle.
pub fn spawntask_thread(f: ~fn()) -> Thread {
    use rt::sched::*;

    let f = Cell::new(f);

    let task = unsafe {
        let sched = Local::unsafe_borrow::<Scheduler>();
        do Local::borrow::<Task, ~Task>() |running_task| {
            ~running_task.new_child(&mut (*sched).stack_pool,
                                    f.take())
        }
    };

    let task = Cell::new(task);

    let thread = do Thread::start {
        let mut sched = ~new_test_uv_sched();
        sched.enqueue_task(task.take());
        sched.run();
    };
    return thread;
}

/// Get a port number, starting at 9600, for use in tests
pub fn next_test_port() -> u16 {
    unsafe {
        return rust_dbg_next_port(base_port() as libc::uintptr_t) as u16;
    }
    extern {
        fn rust_dbg_next_port(base: libc::uintptr_t) -> libc::uintptr_t;
    }
}

/// Get a unique IPv4 localhost:port pair starting at 9600
pub fn next_test_ip4() -> IpAddr {
    Ipv4(127, 0, 0, 1, next_test_port())
}

/// Get a unique IPv6 localhost:port pair starting at 9600
pub fn next_test_ip6() -> IpAddr {
    Ipv6(0, 0, 0, 0, 0, 0, 0, 1, next_test_port())
}

/*
XXX: Welcome to MegaHack City.

The bots run multiple builds at the same time, and these builds
all want to use ports. This function figures out which workspace
it is running in and assigns a port range based on it.
*/
fn base_port() -> uint {
    use os;
    use str::StrSlice;
    use to_str::ToStr;
    use vec::ImmutableVector;

    let base = 9600u;
    let range = 1000;

    let bases = [
        ("32-opt", base + range * 1),
        ("32-noopt", base + range * 2),
        ("64-opt", base + range * 3),
        ("64-noopt", base + range * 4),
        ("64-opt-vg", base + range * 5),
        ("all-opt", base + range * 6),
        ("snap3", base + range * 7),
        ("dist", base + range * 8)
    ];

    let path = os::getcwd().to_str();

    let mut final_base = base;

    for bases.iter().advance |&(dir, base)| {
        if path.contains(dir) {
            final_base = base;
            break;
        }
    }

    return final_base;
}

/// Get a constant that represents the number of times to repeat
/// stress tests. Default 1.
pub fn stress_factor() -> uint {
    use os::getenv;

    match getenv("RUST_RT_STRESS") {
        Some(val) => uint::from_str(val).get(),
        None => 1
    }
}
<|endoftext|>


<commit_before><commit_msg>Add `glyph_cache` example.<commit_after>//! How to glyph cache text render in ggez.
extern crate ggez;

use ggez::conf;
use ggez::event::{self, EventHandler};
use ggez::graphics::glyphcache::{GlyphCache, HorizontalAlign, Layout, TextParam};
use ggez::graphics::{self, Color, Point2};
use ggez::{Context, ContextBuilder, GameResult};

struct MainState {
    frames: usize,
    glyph_brush: GlyphCache<'static>,
    text_base: String,
    text_src: Vec<char>,
    window_w: f32,
    window_h: f32,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        // Set window size.
        let (window_w, window_h) = (
            ctx.conf.window_mode.width as f32,
            ctx.conf.window_mode.height as f32,
        );

        // currently `GlyphCache` no compatible `graphics::Font`
        let font = include_bytes!("../resources/DejaVuSerif.ttf");

        // build glyph brush
        let glyph_brush = GlyphCache::from_bytes(ctx, font as &[u8]);

        // Set background color.
        let bg_color = graphics::Color::from_rgba(50, 50, 50, 255);
        graphics::set_background_color(ctx, bg_color);

        Ok(MainState {
            frames: 0,
            text_base: String::new(),
            text_src: "Lorem ipsum dolor sit amet, ferri simul omittantur eam eu, no debet doming dolorem ius.".chars().collect(),
            glyph_brush,
            window_w,
            window_h,
        })
    }
}

impl EventHandler for MainState {
    fn update(&mut self, ctx: &mut Context) -> GameResult<()> {
        self.frames += 1;
        if self.frames % 100 == 0 {
            println!("FPS: {}", ggez::timer::get_fps(ctx));
        }

        // Update typewriter like text message
        {
            let i = self.text_base.chars().count();

            if self.frames % 2 == 0 {
                if i < self.text_src.len() {
                    self.text_base.push(self.text_src[i]);
                } else {
                    self.text_base.clear();
                }
            }
        }

        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        graphics::clear(ctx);

        // glyph cache queue
        {
            // Default setting except font_size and color.
            self.glyph_brush.queue(TextParam {
                text: "Hello, world.",
                font_size: 42.0,
                color: Color::new(0.9, 0.9, 0.9, 1.0),
                ..TextParam::default()
            });

            // Center align(no bounds)
            self.glyph_brush.queue(TextParam {
                text: "Let's resize this window!",
                position: Point2::new(self.window_w / 2.0, self.window_h * 0.1),
                font_size: 42.0,
                color: Color::new(0.9, 0.9, 0.3, 1.0),
                layout: Layout::default().h_align(HorizontalAlign::Center),
                ..TextParam::default()
            });

            // Divided into three parts(left)
            self.glyph_brush.queue(TextParam {
                text: "The quick brown fox jumps over the lazy dog",
                position: Point2::new(0.0, self.window_h * 0.25),
                bounds: Point2::new(self.window_w / 3.15, self.window_h),
                font_size: 24.0,
                color: Color::new(0.3, 0.3, 0.9, 1.0),
                ..TextParam::default()
            });

            // Divided into three parts(center)
            self.glyph_brush.queue(TextParam {
                text: "The quick brown fox jumps over the lazy dog",
                position: Point2::new(self.window_w / 2.0, self.window_h * 0.25),
                bounds: Point2::new(self.window_w / 3.15, self.window_h),
                font_size: 24.0,
                color: Color::new(0.3, 0.3, 0.9, 1.0),
                layout: Layout::default().h_align(HorizontalAlign::Center),
                ..TextParam::default()
            });

            // Divided into three parts(right)
            self.glyph_brush.queue(TextParam {
                text: "The quick brown fox jumps over the lazy dog",
                position: Point2::new(self.window_w, self.window_h * 0.25),
                bounds: Point2::new(self.window_w / 3.15, self.window_h),
                font_size: 24.0,
                color: Color::new(0.3, 0.3, 0.9, 1.0),
                layout: Layout::default().h_align(HorizontalAlign::Right),
                ..TextParam::default()
            });

            // Multi line text
            self.glyph_brush.queue(TextParam {
                text: "1. Multi line test text\n2. Multi line test text\n3. Multi line test text",
                position: Point2::new(0.0, self.window_h * 0.5),
                bounds: Point2::new(self.window_w, self.window_h),
                font_size: 24.0,
                color: Color::new(0.9, 0.3, 0.3, 1.0),
                layout: Layout::default_wrap(),
                ..TextParam::default()
            });

            // Like a typewriter
            self.glyph_brush.queue(TextParam {
                text: &self.text_base,
                position: Point2::new(0.0, self.window_h * 0.7),
                bounds: Point2::new(self.window_w, self.window_h),
                font_size: 36.0,
                color: Color::new(0.3, 0.9, 0.3, 1.0),
                ..TextParam::default()
            });

            // Draws all queue
            self.glyph_brush.draw(ctx)?;
        } // end glyph cache closure

        graphics::present(ctx);

        Ok(())
    }

    fn resize_event(&mut self, _ctx: &mut Context, width: u32, height: u32) {
        println!("Resized screen to {}, {}", width, height);
        // reset window size
        self.window_w = width as f32;
        self.window_h = height as f32;
    }
}

/// In default, ggez has create `user_config_dir` and `user_data_dir`.
/// e.g. `$HOME/.config/foobar` and `$HOME/.local/share/foobar`
///
/// but this example don't use these directory.
///
/// "Cast no dirt into the well that gives you water".
fn unused_dir_remove(ctx: &mut Context) -> GameResult<()> {
    let user_conf_dir_path = ctx.filesystem.get_user_config_dir();
    let user_data_dir_path = ctx.filesystem.get_user_data_dir();

    if user_conf_dir_path.is_dir() {
        ::std::fs::remove_dir(user_conf_dir_path)?;
    }

    if user_data_dir_path.is_dir() {
        ::std::fs::remove_dir(user_data_dir_path)?;
    }

    Ok(())
}

pub fn main() {
    let mut cb = ContextBuilder::new("glyph_cache_example", "ggez")
        .window_setup(
            conf::WindowSetup::default()
                .title("glyph cache example")
                .resizable(true),
        )
        .window_mode(conf::WindowMode::default().dimensions(512, 512));

    if let Ok(manifest_dir) = std::env::var("CARGO_MANIFEST_DIR") {
        let mut path = std::path::PathBuf::from(manifest_dir);
        path.push("resources");
        cb = cb.add_resource_path(path);
    } else {
        println!("Not building from cargo?  Ok.");
    }

    let ctx = &mut cb.build().unwrap();

    // User directory clean up.
    let _ = unused_dir_remove(ctx);

    let state = &mut MainState::new(ctx).unwrap();
    if let Err(e) = event::run(ctx, state) {
        println!("Error encountered: {}", e);
    } else {
        println!("Game exited cleanly.");
    }
}
<|endoftext|>


<commit_before><commit_msg>Add more trace output<commit_after><|endoftext|>


<commit_before><commit_msg>info keeper exit<commit_after><|endoftext|>


<commit_before><commit_msg>doc BTree<commit_after><|endoftext|>


<commit_before><commit_msg>Complete mess, right now. Leave me alone<commit_after><|endoftext|>


<commit_before><commit_msg>Forgot base.rs<commit_after>/*
 * Copyright (c) 2015, Hewlett Packard Development Company L.P.
 *
 * 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.
 */

use std::fmt;
use std::collections::HashMap;
use std::net::{TcpListener, SocketAddr, SocketAddrV4, SocketAddrV6};
use std::sync::{Mutex, MutexGuard, Condvar, Arc};
use std::sync::mpsc::channel;
use std::sync::mpsc::{Receiver, Sender, RecvError};
use std::thread;
use std::thread::{JoinHandle, sleep_ms};

use hash_ring::HashRing;

use connection::Connection;
use packet::Packet;
use util::LoggingRwLock as RwLock;

#[derive(Clone)]
#[derive(Eq)]
#[derive(PartialEq)]
#[derive(Hash)]
pub struct NodeInfo {
    host: String,
    port: u16,
}

impl fmt::Display for NodeInfo {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.write_fmt(format_args!("{}:{}", self.host, self.port))
    }
}

pub trait HandlePacket: Send {
    fn handle_packet(&self, packet: Packet);
}

pub struct BaseClientServer {
    pub client_id: Vec<u8>,
    pub active_connections: HashMap<NodeInfo, Arc<Mutex<Box<Connection>>>>,
    pub active_connections_cond: Arc<Box<(Mutex<bool>, Condvar)>>,
    pub active_ring: HashRing<NodeInfo>,
    pub hosts: Vec<String>,
    pub stop_cm_tx: Option<Arc<Mutex<Box<Sender<()>>>>>,
    pub stop_pm_tx: Option<Arc<Mutex<Box<Sender<()>>>>>,
    pub host_tx: Option<Arc<Mutex<Box<Sender<Arc<Mutex<Box<(String, u16)>>>>>>>>,
    pub handler: Option<Arc<Mutex<Box<HandlePacket + Send>>>>,
    pub binds: Option<Arc<Mutex<Box<Vec<SocketAddr>>>>>,
}

impl BaseClientServer {

    pub fn new(client_id: Vec<u8>) -> BaseClientServer {
        BaseClientServer {
            client_id: client_id,
            active_connections: HashMap::new(),
            active_connections_cond: Arc::new(Box::new((Mutex::new(false), Condvar::new()))),
            active_ring: HashRing::new(Vec::new(), 1),
            hosts: Vec::new(),
            stop_cm_tx: None,
            stop_pm_tx: None,
            host_tx: None,
            handler: None,
            binds: None,
        }
    }

    /// Runs the client or server threads associated with this BCS
    pub fn run(client_id: Vec<u8>, binds: Option<Vec<SocketAddr>>) -> (Arc<RwLock<Box<BaseClientServer>>>, Vec<JoinHandle<()>>) {
        let mut bcs = Box::new(BaseClientServer::new(client_id));
        let (host_tx, host_rx): (Sender<Arc<Mutex<Box<(String, u16)>>>>, Receiver<Arc<Mutex<Box<(String, u16)>>>>) = channel();
        let (conn_tx, conn_rx) = channel();
        let (stop_cm_tx, stop_cm_rx) = channel();
        let (stop_pm_tx, stop_pm_rx) = channel();
        bcs.stop_cm_tx = Some(Arc::new(Mutex::new(Box::new(stop_cm_tx.clone()))));
        bcs.stop_pm_tx = Some(Arc::new(Mutex::new(Box::new(stop_pm_tx.clone()))));
        bcs.host_tx = Some(Arc::new(Mutex::new(Box::new(host_tx.clone()))));
        let mut bcs: Arc<RwLock<Box<BaseClientServer>>> = Arc::new(RwLock::new(bcs));
        let bcs0 = bcs.clone();
        let bcs1 = bcs.clone();
        let bcs2 = bcs.clone();
        let conn_tx = conn_tx.clone();
        let host_tx = host_tx.clone();
        let mut threads = Vec::new();
        {
            match binds {
                Some(binds) => {
                    let listen_binds = bcs0.read(line!()).unwrap().binds.clone();
                    match listen_binds {
                        Some(_) => unreachable!(),
                        None => {
                            bcs0.write(line!()).unwrap().binds = Some(Arc::new(Mutex::new(Box::new(binds))))
                        },
                    }
                    threads.push(thread::spawn(move || {
                        BaseClientServer::listen_manager(bcs0, stop_cm_rx, conn_tx);
                    }));
                    threads.push(thread::spawn(move || {
                        BaseClientServer::disconnect_manager(bcs2, host_rx);
                    }));
                },
                None => {
                    threads.push(thread::spawn(move || {
                        BaseClientServer::connection_manager(bcs0, stop_cm_rx, host_rx, conn_tx);
                    }));
                }
            };
            threads.push(thread::spawn(move || {
                BaseClientServer::polling_manager(bcs1, stop_pm_rx, host_tx, conn_rx);
            }));
        }
        (bcs, threads)
    }

    pub fn stop(&self) {
        {
            let stop_cm_tx: Option<Arc<Mutex<Box<Sender<()>>>>> = self.stop_cm_tx.clone();
            match stop_cm_tx {
                Some(stop_cm_tx) => { stop_cm_tx.lock().unwrap().send(()); },
                None => { panic!("No stop cm channel"); },
            }
        }
        {
            let stop_pm_tx: Option<Arc<Mutex<Box<Sender<()>>>>> = self.stop_cm_tx.clone();
            match stop_pm_tx {
                Some(stop_pm_tx) => { stop_pm_tx.lock().unwrap().send(()); },
                None => { panic!("No stop pm channel"); },
            }
        }
    }

    fn connection_manager(bcs: Arc<RwLock<Box<BaseClientServer>>>,
                         stop_rx: Receiver<()>,
                         host_rx: Receiver<Arc<Mutex<Box<(String, u16)>>>>,
                         conn_tx: Sender<Arc<Mutex<Box<Connection>>>>) {
        /* Run as a dedicated thread to manage the list of active/inactive connections */
        let (new_tx, new_rx) = channel();
        let mut host: String;
        let mut port: u16;
        loop {
            let container: Result<Arc<Mutex<Box<(String, u16)>>>, RecvError>;
            /* either a new conn is requested, or a new conn is connected */
            select!(
                container = host_rx.recv() => {
                    let container = match container {
                        Ok(container) => container,
                        Err(_) => panic!("Could not receive in connection manager"),
                    };
                    let container = container.clone();
                    {
                        let ref mut hostport = **container.lock().unwrap();
                        host = hostport.0.clone();
                        port = hostport.1;
                    }
                    debug!("received {}:{}", host, port);
                    let conn_tx = conn_tx.clone();
                    let new_tx = new_tx.clone();
                    {
                        let nodeinfo = NodeInfo { host: host.clone(), port: port };
                        debug!("searching for {}:{}", host, port);
                        let found = {
                            let bcs = bcs.read(line!()).unwrap();
                            match bcs.active_connections.get(&nodeinfo) {
                                Some(conn) => Some(conn.clone()),
                                None => None,
                            }
                        };
                        match found {
                            Some(conn) => {
                                debug!("found {}:{}", host, port);
                                // stop sending things to it
                                {
                                    bcs.write(line!()).unwrap().active_ring.remove_node(&NodeInfo{host: host.clone(), port: port});
                                }
                                let conn = conn.clone();
                                thread::scoped(move || {
                                    let mut real_conn = conn.lock().unwrap();
                                    loop {
                                        match real_conn.reconnect() {
                                            Ok(_) => break,
                                            Err(err) => {
                                                info!("Connection to {} failed with ({}). Retry in 1s", *real_conn, err);
                                                thread::sleep_ms(1000);
                                            },
                                        }
                                    };
                                    conn_tx.send(conn.clone());
                                });
                            },
                            None => {
                                debug!("NEW {}:{}", host, port);
                                thread::scoped(move || {
                                    let conn: Arc<Mutex<Box<Connection>>> = Arc::new(Mutex::new(Box::new(Connection::new(&host, port)))).clone();
                                    {
                                        let mut real_conn = conn.lock().unwrap();
                                        loop {
                                            debug!("trying to connect {}", *real_conn);
                                            match real_conn.connect() {
                                                Ok(_) => break,
                                                Err(err) => {
                                                    info!("Connection to {} failed with ({}). Retry in 1s", *real_conn, err);
                                                    thread::sleep_ms(1000);
                                                }
                                            }
                                        };
                                    }
                                    debug!("sending {}", *conn.lock().unwrap());
                                    new_tx.send(conn.clone());
                                });
                            }
                        };
                    } // unlock bcs
                },
                conn = new_rx.recv() => {
                    let conn = match conn {
                        Ok(conn) => conn,
                        Err(_) => panic!("Could not receive in connection manager"),
                    };
                    debug!("received {}", *conn.lock().unwrap());
                    {
                        let ref real_conn = **conn.lock().unwrap();
                        let host = real_conn.host.clone();
                        {
                            debug!("locking bcs");
                            let bcs = &mut bcs.write(line!()).unwrap();
                            debug!("locked bcs");
                            let host = host.clone();
                            let nodeinfo = NodeInfo{ host: host, port: real_conn.port };
                            bcs.active_connections.insert(nodeinfo.clone(), conn.clone());
                            bcs.active_ring.add_node(&nodeinfo);
                            let &(ref lock, ref cvar) = &**bcs.active_connections_cond;
                            let mut available = lock.lock().unwrap();
                            *available = true;
                            cvar.notify_all();
                        }
                    }
                    conn_tx.send(conn.clone());
                },
                _ = stop_rx.recv() => { break }
            )
        }
        for (_, conn) in bcs.read(line!()).unwrap().active_connections.iter() {
            let mut conn = conn.lock().unwrap();
            conn.disconnect();
        }
        // scoped threads should join here
    }

    /// Hosts that have been disconnected go through here for cleanup
    fn disconnect_manager(bcs: Arc<RwLock<Box<BaseClientServer>>>,
                          host_rx: Receiver<Arc<Mutex<Box<(String, u16)>>>>)
    {
        loop {
            let host = host_rx.recv().unwrap();
            let host = host.lock().unwrap();
            let nodeinfo = NodeInfo { host: host.0.clone(), port: host.1 };
            info!("{} disconnected", nodeinfo);
            let mut delete = false;
            match bcs.read(line!()).unwrap().active_connections.get(&nodeinfo) {
                Some(conn) => {
                    conn.lock().unwrap().disconnect();
                    /* TODO Handler for reassigning jobs will need to go here */
                    delete = true;
                },
                None => {
                    warn!("Disconnected host {} not found in active connections", nodeinfo);
                },
            }
            if delete {
                bcs.write(line!()).unwrap().active_connections.remove(&nodeinfo);
            }
        }
    }

    /// Listens for new connections. Server complement to connection_manager
    fn listen_manager(bcs: Arc<RwLock<Box<BaseClientServer>>>,
                      stop_rx: Receiver<()>,
                      conn_tx: Sender<Arc<Mutex<Box<Connection>>>>) {
        // This block here is intended to just copy the vector. Seems like maybe
        // this should be turned into a parameter for simplicity sake.
        let binds = bcs.read(line!()).unwrap().binds.clone();
        let binds = match binds {
            None => panic!("No binds for server!"),
            Some(binds) => binds,
        };
        let real_binds = binds.clone();
        let binds: Vec<SocketAddr>;
        {
            binds = *real_binds.lock().unwrap().clone();
        }
        let mut offset = 0;
        for bind in binds.iter() {
            info!("Binding to {}", bind);
            let bind = bind.clone();
            let conn_tx = conn_tx.clone();
            let bcs = bcs.clone();
            thread::spawn(move || {
                let listener = TcpListener::bind(bind).unwrap();
                let assignedport = listener.local_addr().unwrap().port();
                if bind.port() == 0 {
                    let bcs = bcs.clone();
                    let bcs = bcs.read(line!()).unwrap();
                    debug!("port == 0, reading assigned from socket");
                    let binds = bcs.binds.clone();
                    let binds = match binds {
                        None => panic!("Somehow got no binds despite being in binds for loop."),
                        Some(binds) => binds,
                    };
                    binds.lock().unwrap()[offset] = match bind {
                        SocketAddr::V4(bind) => {
                            SocketAddr::V4(SocketAddrV4::new(bind.ip().clone(), assignedport))
                        },
                        SocketAddr::V6(bind) => {
                            SocketAddr::V6(SocketAddrV6::new(bind.ip().clone(), assignedport, bind.flowinfo(), bind.scope_id()))
                        },
                    };
                } else {
                    debug!("port != 0 but == {}", bind.port());
                }
                info!("Bound to {}", bind);
                for stream in listener.incoming() {
                    debug!("incoming connection!");
                    let conn_tx = conn_tx.clone();
                    let bcs = bcs.clone();
                    thread::scoped(move || {
                        let stream = stream.unwrap();
                        let peer_addr = stream.peer_addr().unwrap();
                        let host = format!("{}", peer_addr.ip());
                        let nodeinfo = NodeInfo{ host: host.clone(), port: peer_addr.port() };
                        let conn = Arc::new(Mutex::new(Box::new(Connection::new_incoming(&host[..], peer_addr.port(), stream))));
                        {
                            let bcs = &mut bcs.write(line!()).unwrap();
                            bcs.active_connections.insert(nodeinfo.clone(), conn.clone());
                        }
                        let bcs = bcs.read(line!()).unwrap();
                        // no need for filling active_ring it's not used in servers
                        let &(ref lock, ref cvar) = &**bcs.active_connections_cond;
                        let mut available = lock.lock().unwrap();
                        *available = true;
                        cvar.notify_all();
                        conn_tx.send(conn.clone());
                    });
                }
            });
            offset += 1;
        }
        // No joining, just accept the explosion because TcpListener has no
        // real way to be interrupted.
        info!("Waiting for stop");
        let _ = stop_rx.recv().unwrap();
        info!("Got stop");
    }

    pub fn add_server(&self, host: String, port: u16) {
        let host_tx = self.host_tx.clone();
        match host_tx {
            None => panic!("adding server to broken BaseClientServer object."),
            Some(host_tx) => {
                debug!("Sending {}:{}", host, port);
                host_tx.lock().unwrap().send(Arc::new(Mutex::new(Box::new((host, port)))));
            },
        }
    }

    fn polling_manager(bcs: Arc<RwLock<Box<BaseClientServer>>>,
                      stop_rx: Receiver<()>,
                      host_tx: Sender<Arc<Mutex<Box<(String, u16)>>>>,
                      conn_rx: Receiver<Arc<Mutex<Box<Connection>>>>) {
        let mut threads: Vec<JoinHandle<()>> = Vec::new();
        let bcs = bcs.clone();
        loop {
            let conn: Result<Arc<Mutex<Box<Connection>>>, RecvError>;
            select!(
                conn = conn_rx.recv() => {
                    let conn = conn.unwrap();
                    let host_tx = host_tx.clone();
                    // poll this conn
                    let bcs = bcs.clone();
                    threads.push(thread::spawn(move || {
                        loop {
                            let mut conn = conn.lock().unwrap();
                            match conn.read_packet() {
                                Ok(p) => {
                                    bcs.read(line!()).unwrap().handle_packet(p);
                                }
                                Err(_) => {
                                    warn!("{} failed to read packet", *conn);
                                    host_tx.send(Arc::new(Mutex::new(Box::new((conn.host.clone(), conn.port)))));
                                    break;
                                }
                            }
                        }
                    }));
                },
                _ = stop_rx.recv() => { break }
            );
        };
        // scoped threads all joined here
        for thread in threads {
            thread.join();
        }
    }

    fn handle_packet(&self, packet: Packet) {
        match self.handler {
            None => return,
            Some(ref handler) => {
                let handler = handler.clone();
                handler.lock().unwrap().handle_packet(packet);
            }
        }
    }

    /// Wait for connection condition from connection_manager.
    ///
    /// We need the rwlock, and not just an unlocked structure, so that we can
    /// just peek at the structure to see the condition variable, and then let
    /// other threads write lock.
    pub fn wait_for_connection(bcs: Arc<RwLock<Box<BaseClientServer>>>, timeout: Option<u32>) -> Result<bool, &'static str> {
        loop {
            let mut active_connections_cond: Arc<Box<(Mutex<bool>, Condvar)>>;
            {
                let bcs = bcs.read(line!()).unwrap();
                active_connections_cond = bcs.active_connections_cond.clone();
            }
            let lock = &active_connections_cond.clone().0;
            let cvar = &active_connections_cond.clone().1;
            let mut available = lock.lock().unwrap();
            if *available {
                break;
            }
            // will wait until there are perceived active connections
            match timeout {
                Some(timeout) => {
                    let wait_result = cvar.wait_timeout_ms(available, timeout).unwrap();
                    if !wait_result.1 {
                        return Err("Timed out waiting for connections")
                    }
                    available = wait_result.0;
                },
                None => {
                    available = cvar.wait(available).unwrap();
                }
            }
        }
        Ok(true)
    }

    // mutable self because active_ring.get_node wants mutable
    pub fn select_connection(&mut self, key: String) -> Arc<Mutex<Box<Connection>>> {
        let nodeinfo = self.active_ring.get_node(key);
        match self.active_connections.get(nodeinfo) {
            Some(conn) => { conn.clone() },
            None => panic!("Hash ring contains non-existant node!"),
        }
    }

}
<|endoftext|>


<commit_before><commit_msg>refactored Cell<commit_after><|endoftext|>


<commit_before><commit_msg>Add padded fill layout<commit_after><|endoftext|>


<commit_before><commit_msg>CartesianMotionPlanner math v1 finished<commit_after><|endoftext|>


<commit_before><commit_msg>add loop with constant refreshing time<commit_after>extern crate clock_ticks;

use std::time::duration::Duration;

pub enum Action {
    Stop,
    Continue,
}

pub fn start_loop<F>(mut callback: F) where F: FnMut() -> Action {
    let mut accumulator = 0;
    let mut previous_clock = clock_ticks::precise_time_ns();

    loop {
        match callback() {
            Action::Stop => break,
            Action::Continue => ()
        };

        let now = clock_ticks::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;

        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;

            // if you have a game, update the state here
        }

        timer::sleep(Duration::nanoseconds((FIXED_TIME_STAMP - accumulator) as i64));
    }
}
<|endoftext|>


<commit_before><commit_msg>Write output to an image file PPM is a terrible format, but it's super easy to get started writing<commit_after>use std::io::{Write, BufWriter};
use std::fs::File;

fn main() {
  let nx = 300;
  let ny = 200;
  let data = format!("{}\n{} {}\n255\n", "P3", nx, ny);
  let f = File::create("target/image.ppm").expect("Unable to create file");
  let mut f = BufWriter::new(f);
  f.write_all(data.as_bytes()).expect("Unable to write data");

  for j in (0..ny).rev() {
    for i in 0..nx {
      let r : f32 = i as f32 / nx as f32;
      let g : f32 = j as f32 / ny as f32;
      let b : f32 = 0.2;
      let ir = (255.99*r) as i32;
      let ig = (255.99*g) as i32;
      let ib = (255.99*b) as i32;
      f.write_all(format!("{} {} {}\n", ir, ig, ib).as_bytes()).expect("Unable to write data");
    }
  }
}<|endoftext|>


<commit_before><commit_msg>added the ability to reset the gameboy.<commit_after><|endoftext|>


<commit_before><commit_msg>Create main.rs<commit_after>
<|endoftext|>


<commit_before><commit_msg>Add a test that 2 + 2 = 4.<commit_after><|endoftext|>


<commit_before>#![doc(html_root_url = "https://cobalt-org.github.io/liquid-rust/")]

// Deny warnings, except in dev mode
#![deny(warnings)]
// #![deny(missing_docs)]
#![cfg_attr(feature="dev", warn(warnings))]

// Allow zero pointers for lazy_static. Otherwise clippy will complain.
#![allow(unknown_lints)]
#![allow(zero_ptr)]

#[macro_use]
extern crate clap;
#[macro_use]
extern crate error_chain;
extern crate liquid;

#[cfg(feature = "serde_yaml")]
extern crate serde_yaml;
#[cfg(feature = "serde_json")]
extern crate serde_json;

use std::ffi;
use std::fs;
use std::io;
use std::io::Write;
use std::path;
use liquid::Renderable;

error_chain! {
    links {
    }

    foreign_links {
        Clap(clap::Error);
        Io(io::Error);
        Liquid(liquid::Error);
        Yaml(serde_yaml::Error) #[cfg(feature = "serde_yaml")];
        Json(serde_json::Error) #[cfg(feature = "serde_json")];
    }

    errors {
    }
}

fn option<'a>(name: &'a str, value: &'a str) -> clap::Arg<'a, 'a> {
    clap::Arg::with_name(name).long(name).value_name(value)
}

#[cfg(feature = "serde_yaml")]
fn load_yaml(path: &path::Path) -> Result<liquid::Value> {
    let f = fs::File::open(path)?;
    serde_yaml::from_reader(f).map_err(|e| e.into())
}

#[cfg(not(feature = "serde_yaml"))]
fn load_yaml(_path: &path::Path) -> Result<liquid::Value> {
    bail!("yaml is unsupported");
}

#[cfg(feature = "serde_json")]
fn load_json(path: &path::Path) -> Result<liquid::Value> {
    let f = fs::File::open(path)?;
    serde_json::from_reader(f).map_err(|e| e.into())
}

#[cfg(not(feature = "serde_json"))]
fn load_json(_path: &path::Path) -> Result<liquid::Value> {
    bail!("json is unsupported");
}

fn build_context(path: &path::Path) -> Result<liquid::Context> {
    let extension = path.extension().unwrap_or_else(|| ffi::OsStr::new(""));
    let value = if extension == ffi::OsStr::new("yaml") {
        load_yaml(path)
    } else if extension == ffi::OsStr::new("yaml") {
        load_json(path)
    } else {
        Err("Unsupported file type".into())
    }?;
    let value = match value {
        liquid::Value::Object(o) => Ok(o),
        _ => Err("File must be an object"),
    }?;
    let data = liquid::Context::with_values(value);

    Ok(data)
}

fn run() -> Result<()> {
    let matches = clap::App::new("liquidate")
        .version(crate_version!())
        .author(crate_authors!())
        .arg(option("input", "LIQUID").required(true))
        .arg(option("output", "TXT"))
        .arg(option("context", "TOML"))
        .arg(option("include-root", "PATH"))
        .get_matches_safe()?;

    let mut options = liquid::LiquidOptions::default();
    let root = matches
        .value_of("include-root")
        .map(path::PathBuf::from)
        .unwrap_or(Default::default());
    options.template_repository = Box::new(liquid::LocalTemplateRepository::new(root));

    let mut data = matches
        .value_of("context")
        .map(|s| {
                 let p = path::PathBuf::from(s);
                 build_context(p.as_path())
             })
        .map_or(Ok(None), |r| r.map(Some))?
        .unwrap_or_else(liquid::Context::new);

    let template_path = matches
        .value_of("input")
        .map(path::PathBuf::from)
        .expect("Parameter was required");
    let template = liquid::parse_file(template_path, options)?;
    let output = template
        .render(&mut data)?
        .unwrap_or_else(|| "".to_string());
    match matches.value_of("output") {
        Some(path) => {
            let mut out = fs::File::create(path::PathBuf::from(path))?;
            out.write_all(output.as_bytes())?;
        }
        None => {
            println!("{}", output);
        }
    }

    Ok(())
}

quick_main!(run);
<commit_msg>fix(liquid-dbg): address nightly warning<commit_after>#![doc(html_root_url = "https://cobalt-org.github.io/liquid-rust/")]

// Deny warnings, except in dev mode
#![deny(warnings)]
// #![deny(missing_docs)]
#![cfg_attr(feature="dev", warn(warnings))]

// Allow zero pointers for lazy_static. Otherwise clippy will complain.
#![allow(unknown_lints)]
#![allow(zero_ptr)]

#[macro_use]
extern crate clap;
#[macro_use]
extern crate error_chain;
extern crate liquid;

#[cfg(feature = "serde_yaml")]
extern crate serde_yaml;
#[cfg(feature = "serde_json")]
extern crate serde_json;

use std::ffi;
use std::fs;
use std::io;
use std::io::Write;
use std::path;
use liquid::Renderable;

error_chain! {
    links {
    }

    foreign_links {
        Clap(clap::Error);
        Io(io::Error);
        Liquid(liquid::Error);
        Yaml(serde_yaml::Error) #[cfg(feature = "serde_yaml")];
        Json(serde_json::Error) #[cfg(feature = "serde_json")];
    }

    errors {
    }
}

fn option<'a>(name: &'a str, value: &'a str) -> clap::Arg<'a, 'a> {
    clap::Arg::with_name(name).long(name).value_name(value)
}

#[cfg(feature = "serde_yaml")]
fn load_yaml(path: &path::Path) -> Result<liquid::Value> {
    let f = fs::File::open(path)?;
    serde_yaml::from_reader(f).map_err(|e| e.into())
}

#[cfg(not(feature = "serde_yaml"))]
fn load_yaml(_path: &path::Path) -> Result<liquid::Value> {
    bail!("yaml is unsupported");
}

#[cfg(feature = "serde_json")]
fn load_json(path: &path::Path) -> Result<liquid::Value> {
    let f = fs::File::open(path)?;
    serde_json::from_reader(f).map_err(|e| e.into())
}

#[cfg(not(feature = "serde_json"))]
fn load_json(_path: &path::Path) -> Result<liquid::Value> {
    bail!("json is unsupported");
}

fn build_context(path: &path::Path) -> Result<liquid::Context> {
    let extension = path.extension().unwrap_or_else(|| ffi::OsStr::new(""));
    let value = if extension == ffi::OsStr::new("yaml") {
        load_yaml(path)
    } else if extension == ffi::OsStr::new("yaml") {
        load_json(path)
    } else {
        Err("Unsupported file type".into())
    }?;
    let value = match value {
        liquid::Value::Object(o) => Ok(o),
        _ => Err("File must be an object"),
    }?;
    let data = liquid::Context::with_values(value);

    Ok(data)
}

fn run() -> Result<()> {
    let matches = clap::App::new("liquidate")
        .version(crate_version!())
        .author(crate_authors!())
        .arg(option("input", "LIQUID").required(true))
        .arg(option("output", "TXT"))
        .arg(option("context", "TOML"))
        .arg(option("include-root", "PATH"))
        .get_matches_safe()?;

    let mut options = liquid::LiquidOptions::default();
    let root = matches
        .value_of("include-root")
        .map(path::PathBuf::from)
        .unwrap_or_default();
    options.template_repository = Box::new(liquid::LocalTemplateRepository::new(root));

    let mut data = matches
        .value_of("context")
        .map(|s| {
                 let p = path::PathBuf::from(s);
                 build_context(p.as_path())
             })
        .map_or(Ok(None), |r| r.map(Some))?
        .unwrap_or_else(liquid::Context::new);

    let template_path = matches
        .value_of("input")
        .map(path::PathBuf::from)
        .expect("Parameter was required");
    let template = liquid::parse_file(template_path, options)?;
    let output = template
        .render(&mut data)?
        .unwrap_or_else(|| "".to_string());
    match matches.value_of("output") {
        Some(path) => {
            let mut out = fs::File::create(path::PathBuf::from(path))?;
            out.write_all(output.as_bytes())?;
        }
        None => {
            println!("{}", output);
        }
    }

    Ok(())
}

quick_main!(run);
<|endoftext|>


<commit_before><commit_msg>added simple window with menubar<commit_after><|endoftext|>


<commit_before><commit_msg>Initial commit<commit_after>use std::thread;
use std::net;

fn socket(listen_on: net::SocketAddr) -> net::UdpSocket {
  let attempt = net::UdpSocket::bind(listen_on);
  let mut socket;
  match attempt {
    Ok(sock) => {
      println!("Bound socket to {}", listen_on);
      socket = sock;
    },
    Err(err) => panic!("Could not bind: {}", err)
  }
  socket
}

fn read_message(socket: net::UdpSocket) -> Vec<u8> {
  let mut buf: [u8; 1] = [0; 1];
  println!("Reading data");
  let result = socket.recv_from(&mut buf);
  drop(socket);
  let mut data;
  match result {
    Ok((amt, src)) => {
      println!("Received data from {}", src);
      data = Vec::from(&buf[0..amt]);
    },
    Err(err) => panic!("Read error: {}", err)
  }
  data
}

pub fn send_message(send_addr: net::SocketAddr, target: net::SocketAddr, data: Vec<u8>) {
  let socket = socket(send_addr);
  println!("Sending data");
  let result = socket.send_to(&data, target);
  drop(socket);
  match result {
    Ok(amt) => println!("Sent {} bytes", amt),
    Err(err) => panic!("Write error: {}", err)
  }
}

pub fn listen(listen_on: net::SocketAddr) -> thread::JoinHandle<Vec<u8>> {
  let socket = socket(listen_on);
  let handle = thread::spawn(move || {
    read_message(socket)
  });
  handle
}

#[cfg(test)]
mod test {
  use std::net;
  use std::thread;
  use super::*;

  #[test]
  fn test_udp() {
    println!("UDP");
    let ip = net::Ipv4Addr::new(127, 0, 0, 1);
    let listen_addr = net::SocketAddrV4::new(ip, 8888);
    let send_addr = net::SocketAddrV4::new(ip, 8889);
    let future = listen(net::SocketAddr::V4(listen_addr));
    let message: Vec<u8> = vec![10];
 // give the thread 3s to open the socket
    thread::sleep_ms(3000);
    send_message(net::SocketAddr::V4(send_addr), net::SocketAddr::V4(listen_addr), message);
    println!("Waiting");
    let received = future.join().unwrap();
    println!("Got {} bytes", received.len());
    assert_eq!(1, received.len());
    assert_eq!(10, received[0]);
  }
}

fn main() {
    println!("UDP");
    let ip = net::Ipv4Addr::new(127, 0, 0, 1);
    let listen_addr = net::SocketAddrV4::new(ip, 1738);
    let send_addr = net::SocketAddrV4::new(ip, 8888);
    let s = "red".to_string();
    let mut message: Vec<u8> = Vec::new();
    message.extend(s.as_bytes().iter().cloned());
    thread::sleep_ms(1000);
    send_message(net::SocketAddr::V4(send_addr), net::SocketAddr::V4(listen_addr), message);
}

<|endoftext|>