<commit_before>extern crate winapi;
use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
use self::winapi::shared::ntdef::WCHAR;
use self::winapi::shared::winerror;
use self::winapi::um::{errhandlingapi, libloaderapi};

use util::{ensure_compatible_types, cstr_cow_from_bytes};

use std::ffi::{OsStr, OsString};
use std::{fmt, io, marker, mem, ptr};
use std::os::windows::ffi::{OsStrExt, OsStringExt};
use std::sync::atomic::{AtomicBool, Ordering};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(HMODULE);

unsafe impl Send for Library {}
// Now, this is sort-of-tricky. MSDN documentation does not really make any claims as to safety of
// the Win32 APIs. Sadly, whomever I asked, even current and former Microsoft employees, couldn’t
// say for sure, whether the Win32 APIs used to implement `Library` are thread-safe or not.
//
// My investigation ended up with a question about thread-safety properties of the API involved
// being sent to an internal (to MS) general question mailing-list. The conclusion of the mail is
// as such:
//
// * Nobody inside MS (at least out of all the people who have seen the question) knows for
//   sure either;
// * However, the general consensus between MS developers is that one can rely on the API being
//   thread-safe. In case it is not thread-safe it should be considered a bug on the Windows
//   part. (NB: bugs filled at https://connect.microsoft.com/ against Windows Server)
unsafe impl Sync for Library {}

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Corresponds to `LoadLibraryExW(filename, NULL, 0)` which is equivalent to `LoadLibraryW(filename)`
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
        Library::load_with_flags(filename, 0)
    }

    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryExW(filename, NULL, flags)`.
    pub fn load_with_flags<P: AsRef<OsStr>>(filename: P, flags: DWORD) -> Result<Library, crate::Error> {
        let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|source| crate::Error::LoadLibraryExW { source }, || {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { libloaderapi::LoadLibraryExW(wide_filename.as_ptr(), std::ptr::null_mut(), flags) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or(crate::Error::LoadLibraryExWUnknown));
        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
        // inside the closure by mistake. See comment inside the closure.
        ret
    }

    /// Get a pointer to function or static variable by symbol name.
    ///
    /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
    /// terminated `symbol` may avoid a string allocation in some cases.
    ///
    /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
    /// most likely invalid.
    ///
    /// ## Unsafety
    ///
    /// This function does not validate the type `T`. It is up to the user of this function to
    /// ensure that the loaded symbol is in fact a `T`. Using a value with a wrong type has no
    /// definied behaviour.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
        ensure_compatible_types::<T, FARPROC>()?;
        let symbol = cstr_cow_from_bytes(symbol)?;
        with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
            let symbol = libloaderapi::GetProcAddress(self.0, symbol.as_ptr());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or(crate::Error::GetProcAddressUnknown))
    }

    /// Get a pointer to function or static variable by ordinal number.
    ///
    /// ## Unsafety
    ///
    /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
    /// undefined.
    pub unsafe fn get_ordinal<T>(&self, ordinal: WORD) -> Result<Symbol<T>, crate::Error> {
        ensure_compatible_types::<T, FARPROC>()?;
        with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
            let ordinal = ordinal as usize as *mut _;
            let symbol = libloaderapi::GetProcAddress(self.0, ordinal);
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or(crate::Error::GetProcAddressUnknown))
    }

    /// Convert the `Library` to a raw handle.
    pub fn into_raw(self) -> HMODULE {
        let handle = self.0;
        mem::forget(self);
        handle
    }

    /// Convert a raw handle to a `Library`.
    ///
    /// ## Unsafety
    ///
    /// The handle shall be a result of a successful call of `LoadLibraryW` or a
    /// handle previously returned by the `Library::into_raw` call.
    pub unsafe fn from_raw(handle: HMODULE) -> Library {
        Library(handle)
    }

    /// Unload the library.
    pub fn close(self) -> Result<(), crate::Error> {
        with_get_last_error(|source| crate::Error::FreeLibrary { source }, || {
            if unsafe { libloaderapi::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).map_err(|e| e.unwrap_or(crate::Error::FreeLibraryUnknown))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        unsafe { libloaderapi::FreeLibrary(self.0); }
    }
}

impl fmt::Debug for Library {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            // FIXME: use Maybeuninit::uninit_array when stable
            let mut buf =
                mem::MaybeUninit::<[mem::MaybeUninit::<WCHAR>; 1024]>::uninit().assume_init();
            let len = libloaderapi::GetModuleFileNameW(self.0,
                (&mut buf[..]).as_mut_ptr().cast(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(
                    // FIXME: use Maybeuninit::slice_get_ref when stable
                    &*(&buf[..len] as *const [_] as *const [WCHAR])
                );
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
pub struct Symbol<T> {
    pointer: FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> Symbol<T> {
    /// Convert the loaded Symbol into a handle.
    pub fn into_raw(self) -> FARPROC {
        let pointer = self.pointer;
        mem::forget(self);
        pointer
    }
}

impl<T> Symbol<Option<T>> {
    /// Lift Option out of the symbol.
    pub fn lift_option(self) -> Option<Symbol<T>> {
        if self.pointer.is_null() {
            None
        } else {
            Some(Symbol {
                pointer: self.pointer,
                pd: marker::PhantomData,
            })
        }
    }
}

unsafe impl<T: Send> Send for Symbol<T> {}
unsafe impl<T: Sync> Sync for Symbol<T> {}

impl<T> Clone for Symbol<T> {
    fn clone(&self) -> Symbol<T> {
        Symbol { ..*self }
    }
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            // Additional reference level for a dereference on `deref` return value.
            mem::transmute(&self.pointer)
        }
    }
}

impl<T> fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = AtomicBool::new(false);
struct ErrorModeGuard(DWORD);

impl ErrorModeGuard {
    fn new() -> Option<ErrorModeGuard> {
        const SEM_FAILCE: DWORD = 1;
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Acquire) {
                let mut previous_mode = 0;
                let success = errhandlingapi::SetThreadErrorMode(SEM_FAILCE, &mut previous_mode) != 0;
                if !success && errhandlingapi::GetLastError() == winerror::ERROR_CALL_NOT_IMPLEMENTED {
                    USE_ERRORMODE.store(true, Ordering::Release);
                } else if !success {
                    // SetThreadErrorMode failed with some other error? How in the world is it
                    // possible for what is essentially a simple variable swap to fail?
                    // For now we just ignore the error -- the worst that can happen here is
                    // the previous mode staying on and user seeing a dialog error on older Windows
                    // machines.
                    return None;
                } else if previous_mode == SEM_FAILCE {
                    return None;
                } else {
                    return Some(ErrorModeGuard(previous_mode));
                }
            }
            match errhandlingapi::SetErrorMode(SEM_FAILCE) {
                SEM_FAILCE => {
                    // This is important to reduce racy-ness when this library is used on multiple
                    // threads. In particular this helps with following race condition:
                    //
                    // T1: SetErrorMode(SEM_FAILCE)
                    // T2: SetErrorMode(SEM_FAILCE)
                    // T1: SetErrorMode(old_mode) # not SEM_FAILCE
                    // T2: SetErrorMode(SEM_FAILCE) # restores to SEM_FAILCE on drop
                    //
                    // This is still somewhat racy in a sense that T1 might restore the error
                    // mode before T2 finishes loading the library, but that is less of a
                    // concern – it will only end up in end user seeing a dialog.
                    //
                    // Also, SetErrorMode itself is probably not an atomic operation.
                    None
                }
                a => Some(ErrorModeGuard(a))
            }
        }
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                errhandlingapi::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                errhandlingapi::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(wrap: fn(crate::error::WindowsError) -> crate::Error, closure: F)
-> Result<T, Option<crate::Error>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { errhandlingapi::GetLastError() };
        if error == 0 {
            None
        } else {
            Some(wrap(crate::error::WindowsError(io::Error::from_raw_os_error(error as i32))))
        }
    })
}

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

    #[test]
    fn works_getlasterror() {
        let lib = Library::new("kernel32.dll").unwrap();
        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
            lib.get(b"GetLastError").unwrap()
        };
        unsafe {
            errhandlingapi::SetLastError(42);
            assert_eq!(errhandlingapi::GetLastError(), gle())
        }
    }

    #[test]
    fn works_getlasterror0() {
        let lib = Library::new("kernel32.dll").unwrap();
        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
            lib.get(b"GetLastError\0").unwrap()
        };
        unsafe {
            errhandlingapi::SetLastError(42);
            assert_eq!(errhandlingapi::GetLastError(), gle())
        }
    }
}
<commit_msg>[Windows]: LoadLibraryExW - document the reserved parameter<commit_after>extern crate winapi;
use self::winapi::shared::minwindef::{WORD, DWORD, HMODULE, FARPROC};
use self::winapi::shared::ntdef::WCHAR;
use self::winapi::shared::winerror;
use self::winapi::um::{errhandlingapi, libloaderapi};

use util::{ensure_compatible_types, cstr_cow_from_bytes};

use std::ffi::{OsStr, OsString};
use std::{fmt, io, marker, mem, ptr};
use std::os::windows::ffi::{OsStrExt, OsStringExt};
use std::sync::atomic::{AtomicBool, Ordering};

/// A platform-specific equivalent of the cross-platform `Library`.
pub struct Library(HMODULE);

unsafe impl Send for Library {}
// Now, this is sort-of-tricky. MSDN documentation does not really make any claims as to safety of
// the Win32 APIs. Sadly, whomever I asked, even current and former Microsoft employees, couldn’t
// say for sure, whether the Win32 APIs used to implement `Library` are thread-safe or not.
//
// My investigation ended up with a question about thread-safety properties of the API involved
// being sent to an internal (to MS) general question mailing-list. The conclusion of the mail is
// as such:
//
// * Nobody inside MS (at least out of all the people who have seen the question) knows for
//   sure either;
// * However, the general consensus between MS developers is that one can rely on the API being
//   thread-safe. In case it is not thread-safe it should be considered a bug on the Windows
//   part. (NB: bugs filled at https://connect.microsoft.com/ against Windows Server)
unsafe impl Sync for Library {}

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Corresponds to `LoadLibraryExW(filename, reserved: NULL, flags: 0)` which is equivalent to `LoadLibraryW(filename)`
    #[inline]
    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library, crate::Error> {
        Library::load_with_flags(filename, 0)
    }

    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// Corresponds to `LoadLibraryExW(filename, reserved: NULL, flags)`.
    pub fn load_with_flags<P: AsRef<OsStr>>(filename: P, flags: DWORD) -> Result<Library, crate::Error> {
        let wide_filename: Vec<u16> = filename.as_ref().encode_wide().chain(Some(0)).collect();
        let _guard = ErrorModeGuard::new();

        let ret = with_get_last_error(|source| crate::Error::LoadLibraryExW { source }, || {
            // Make sure no winapi calls as a result of drop happen inside this closure, because
            // otherwise that might change the return value of the GetLastError.
            let handle = unsafe { libloaderapi::LoadLibraryExW(wide_filename.as_ptr(), std::ptr::null_mut(), flags) };
            if handle.is_null()  {
                None
            } else {
                Some(Library(handle))
            }
        }).map_err(|e| e.unwrap_or(crate::Error::LoadLibraryExWUnknown));
        drop(wide_filename); // Drop wide_filename here to ensure it doesn’t get moved and dropped
        // inside the closure by mistake. See comment inside the closure.
        ret
    }

    /// Get a pointer to function or static variable by symbol name.
    ///
    /// The `symbol` may not contain any null bytes, with an exception of last byte. A null
    /// terminated `symbol` may avoid a string allocation in some cases.
    ///
    /// Symbol is interpreted as-is; no mangling is done. This means that symbols like `x::y` are
    /// most likely invalid.
    ///
    /// ## Unsafety
    ///
    /// This function does not validate the type `T`. It is up to the user of this function to
    /// ensure that the loaded symbol is in fact a `T`. Using a value with a wrong type has no
    /// definied behaviour.
    pub unsafe fn get<T>(&self, symbol: &[u8]) -> Result<Symbol<T>, crate::Error> {
        ensure_compatible_types::<T, FARPROC>()?;
        let symbol = cstr_cow_from_bytes(symbol)?;
        with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
            let symbol = libloaderapi::GetProcAddress(self.0, symbol.as_ptr());
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or(crate::Error::GetProcAddressUnknown))
    }

    /// Get a pointer to function or static variable by ordinal number.
    ///
    /// ## Unsafety
    ///
    /// Pointer to a value of arbitrary type is returned. Using a value with wrong type is
    /// undefined.
    pub unsafe fn get_ordinal<T>(&self, ordinal: WORD) -> Result<Symbol<T>, crate::Error> {
        ensure_compatible_types::<T, FARPROC>()?;
        with_get_last_error(|source| crate::Error::GetProcAddress { source }, || {
            let ordinal = ordinal as usize as *mut _;
            let symbol = libloaderapi::GetProcAddress(self.0, ordinal);
            if symbol.is_null() {
                None
            } else {
                Some(Symbol {
                    pointer: symbol,
                    pd: marker::PhantomData
                })
            }
        }).map_err(|e| e.unwrap_or(crate::Error::GetProcAddressUnknown))
    }

    /// Convert the `Library` to a raw handle.
    pub fn into_raw(self) -> HMODULE {
        let handle = self.0;
        mem::forget(self);
        handle
    }

    /// Convert a raw handle to a `Library`.
    ///
    /// ## Unsafety
    ///
    /// The handle shall be a result of a successful call of `LoadLibraryW` or a
    /// handle previously returned by the `Library::into_raw` call.
    pub unsafe fn from_raw(handle: HMODULE) -> Library {
        Library(handle)
    }

    /// Unload the library.
    pub fn close(self) -> Result<(), crate::Error> {
        with_get_last_error(|source| crate::Error::FreeLibrary { source }, || {
            if unsafe { libloaderapi::FreeLibrary(self.0) == 0 } {
                None
            } else {
                Some(())
            }
        }).map_err(|e| e.unwrap_or(crate::Error::FreeLibraryUnknown))
    }
}

impl Drop for Library {
    fn drop(&mut self) {
        unsafe { libloaderapi::FreeLibrary(self.0); }
    }
}

impl fmt::Debug for Library {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            // FIXME: use Maybeuninit::uninit_array when stable
            let mut buf =
                mem::MaybeUninit::<[mem::MaybeUninit::<WCHAR>; 1024]>::uninit().assume_init();
            let len = libloaderapi::GetModuleFileNameW(self.0,
                (&mut buf[..]).as_mut_ptr().cast(), 1024) as usize;
            if len == 0 {
                f.write_str(&format!("Library@{:p}", self.0))
            } else {
                let string: OsString = OsString::from_wide(
                    // FIXME: use Maybeuninit::slice_get_ref when stable
                    &*(&buf[..len] as *const [_] as *const [WCHAR])
                );
                f.write_str(&format!("Library@{:p} from {:?}", self.0, string))
            }
        }
    }
}

/// Symbol from a library.
///
/// A major difference compared to the cross-platform `Symbol` is that this does not ensure the
/// `Symbol` does not outlive `Library` it comes from.
pub struct Symbol<T> {
    pointer: FARPROC,
    pd: marker::PhantomData<T>
}

impl<T> Symbol<T> {
    /// Convert the loaded Symbol into a handle.
    pub fn into_raw(self) -> FARPROC {
        let pointer = self.pointer;
        mem::forget(self);
        pointer
    }
}

impl<T> Symbol<Option<T>> {
    /// Lift Option out of the symbol.
    pub fn lift_option(self) -> Option<Symbol<T>> {
        if self.pointer.is_null() {
            None
        } else {
            Some(Symbol {
                pointer: self.pointer,
                pd: marker::PhantomData,
            })
        }
    }
}

unsafe impl<T: Send> Send for Symbol<T> {}
unsafe impl<T: Sync> Sync for Symbol<T> {}

impl<T> Clone for Symbol<T> {
    fn clone(&self) -> Symbol<T> {
        Symbol { ..*self }
    }
}

impl<T> ::std::ops::Deref for Symbol<T> {
    type Target = T;
    fn deref(&self) -> &T {
        unsafe {
            // Additional reference level for a dereference on `deref` return value.
            mem::transmute(&self.pointer)
        }
    }
}

impl<T> fmt::Debug for Symbol<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&format!("Symbol@{:p}", self.pointer))
    }
}

static USE_ERRORMODE: AtomicBool = AtomicBool::new(false);
struct ErrorModeGuard(DWORD);

impl ErrorModeGuard {
    fn new() -> Option<ErrorModeGuard> {
        const SEM_FAILCE: DWORD = 1;
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Acquire) {
                let mut previous_mode = 0;
                let success = errhandlingapi::SetThreadErrorMode(SEM_FAILCE, &mut previous_mode) != 0;
                if !success && errhandlingapi::GetLastError() == winerror::ERROR_CALL_NOT_IMPLEMENTED {
                    USE_ERRORMODE.store(true, Ordering::Release);
                } else if !success {
                    // SetThreadErrorMode failed with some other error? How in the world is it
                    // possible for what is essentially a simple variable swap to fail?
                    // For now we just ignore the error -- the worst that can happen here is
                    // the previous mode staying on and user seeing a dialog error on older Windows
                    // machines.
                    return None;
                } else if previous_mode == SEM_FAILCE {
                    return None;
                } else {
                    return Some(ErrorModeGuard(previous_mode));
                }
            }
            match errhandlingapi::SetErrorMode(SEM_FAILCE) {
                SEM_FAILCE => {
                    // This is important to reduce racy-ness when this library is used on multiple
                    // threads. In particular this helps with following race condition:
                    //
                    // T1: SetErrorMode(SEM_FAILCE)
                    // T2: SetErrorMode(SEM_FAILCE)
                    // T1: SetErrorMode(old_mode) # not SEM_FAILCE
                    // T2: SetErrorMode(SEM_FAILCE) # restores to SEM_FAILCE on drop
                    //
                    // This is still somewhat racy in a sense that T1 might restore the error
                    // mode before T2 finishes loading the library, but that is less of a
                    // concern – it will only end up in end user seeing a dialog.
                    //
                    // Also, SetErrorMode itself is probably not an atomic operation.
                    None
                }
                a => Some(ErrorModeGuard(a))
            }
        }
    }
}

impl Drop for ErrorModeGuard {
    fn drop(&mut self) {
        unsafe {
            if !USE_ERRORMODE.load(Ordering::Relaxed) {
                errhandlingapi::SetThreadErrorMode(self.0, ptr::null_mut());
            } else {
                errhandlingapi::SetErrorMode(self.0);
            }
        }
    }
}

fn with_get_last_error<T, F>(wrap: fn(crate::error::WindowsError) -> crate::Error, closure: F)
-> Result<T, Option<crate::Error>>
where F: FnOnce() -> Option<T> {
    closure().ok_or_else(|| {
        let error = unsafe { errhandlingapi::GetLastError() };
        if error == 0 {
            None
        } else {
            Some(wrap(crate::error::WindowsError(io::Error::from_raw_os_error(error as i32))))
        }
    })
}

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

    #[test]
    fn works_getlasterror() {
        let lib = Library::new("kernel32.dll").unwrap();
        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
            lib.get(b"GetLastError").unwrap()
        };
        unsafe {
            errhandlingapi::SetLastError(42);
            assert_eq!(errhandlingapi::GetLastError(), gle())
        }
    }

    #[test]
    fn works_getlasterror0() {
        let lib = Library::new("kernel32.dll").unwrap();
        let gle: Symbol<unsafe extern "system" fn() -> DWORD> = unsafe {
            lib.get(b"GetLastError\0").unwrap()
        };
        unsafe {
            errhandlingapi::SetLastError(42);
            assert_eq!(errhandlingapi::GetLastError(), gle())
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate mimir;
extern crate osmpbfreader;

use ::admin_geofinder::AdminGeoFinder;
use ::boundaries::{build_boundary, make_centroid};
use std::collections::{BTreeSet, BTreeMap};
use super::utils::*;
use super::OsmPbfReader;

pub type PoiTypes = BTreeMap<String, BTreeSet<String>>;
pub type PoisVec = Vec<mimir::Poi>;

#[derive(Debug)]
struct PoiMatcher {
    poi_types: PoiTypes,
}

impl PoiMatcher {
    pub fn new(types: PoiTypes) -> PoiMatcher {
        PoiMatcher { poi_types: types }
    }

    pub fn is_poi(&self, obj: &osmpbfreader::OsmObj) -> bool {
        self.poi_types.iter().any(|(poi_tag, poi_types)| {
            obj.tags().get(poi_tag).map_or(false, |poi_type| poi_types.contains(poi_type))
        })
    }
}

pub fn default_amenity_types() -> BTreeSet<String> {
    ["university",
     "hospital",
     "post_office",
     "bicycle_rental",
     "bicycle_parking",
     "parking",
     "police",
     "townhall"]
        .iter()
        .map(|&k| k.to_string())
        .collect()
}

pub fn default_leisure_types() -> BTreeSet<String> {
    ["garden", "park"]
        .iter()
        .map(|&k| k.to_string())
        .collect()
}

fn parse_poi(osmobj: &osmpbfreader::OsmObj,
             obj_map: &BTreeMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>,
             admins_geofinder: &AdminGeoFinder,
             city_level: u32)
             -> Option<mimir::Poi> {
    let (id, coord) = match *osmobj {
        osmpbfreader::OsmObj::Node(ref node) => {
            (format_poi_id("node", node.id), mimir::Coord::new(node.lat, node.lon))
        }
        osmpbfreader::OsmObj::Way(ref way) => {
            (format_poi_id("way", way.id), get_way_coord(obj_map, way))
        }
        osmpbfreader::OsmObj::Relation(ref relation) => {
            (format_poi_id("relation", relation.id),
             make_centroid(&build_boundary(&relation, &obj_map)))
        }
    };

    let name = osmobj.tags().get("name").map_or("", |name| name);
    let adms = admins_geofinder.get(&coord);
    let zip_codes = match osmobj.tags().get("addr:postcode") {
        Some(val) if !val.is_empty() => vec![val.clone()],
        _ => get_zip_codes_from_admins(&adms),
    };
    Some(mimir::Poi {
        id: id,
        name: name.to_string(),
        label: format_label(&adms, city_level, name),
        coord: coord,
        zip_codes: zip_codes,
        administrative_regions: adms,
        weight: 1,
    })
}

fn format_poi_id(_type: &str, id: i64) -> String {
    format!("poi:osm:{}:{}", _type, id)
}

pub fn pois(pbf: &mut OsmPbfReader,
            poi_types: PoiTypes,
            admins_geofinder: &AdminGeoFinder,
            city_level: u32)
            -> PoisVec {
    let matcher = PoiMatcher::new(poi_types);
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_poi(o)).unwrap();
    objects.iter()
        .filter(|&(_, obj)| matcher.is_poi(&obj))
        .map(|(_, obj)| parse_poi(obj, &objects, admins_geofinder, city_level))
        .filter(|o| o.is_some())
        .map(|o| o.unwrap())
        .collect()
}

pub fn compute_poi_weight(pois_vec: &mut PoisVec, city_level: u32) {
    for poi in pois_vec {
        for admin in &mut poi.administrative_regions {
            if admin.level == city_level {
                poi.weight = admin.weight.get();
                break;
            }
        }
    }
}
<commit_msg>ignore poi without coordinates or name<commit_after>// Copyright © 2016, Canal TP and/or its affiliates. All rights reserved.
//
// This file is part of Navitia,
//     the software to build cool stuff with public transport.
//
// Hope you'll enjoy and contribute to this project,
//     powered by Canal TP (www.canaltp.fr).
// Help us simplify mobility and open public transport:
//     a non ending quest to the responsive locomotion way of traveling!
//
// LICENCE: This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU Affero General Public
// License as published by the Free Software Foundation, either
// version 3 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program. If not, see
// <http://www.gnu.org/licenses/>.
//
// Stay tuned using
// twitter @navitia
// IRC #navitia on freenode
// https://groups.google.com/d/forum/navitia
// www.navitia.io

extern crate mimir;
extern crate osmpbfreader;

use ::admin_geofinder::AdminGeoFinder;
use ::boundaries::{build_boundary, make_centroid};
use std::collections::{BTreeSet, BTreeMap};
use super::utils::*;
use super::OsmPbfReader;

pub type PoiTypes = BTreeMap<String, BTreeSet<String>>;
pub type PoisVec = Vec<mimir::Poi>;

#[derive(Debug)]
struct PoiMatcher {
    poi_types: PoiTypes,
}

impl PoiMatcher {
    pub fn new(types: PoiTypes) -> PoiMatcher {
        PoiMatcher { poi_types: types }
    }

    pub fn is_poi(&self, obj: &osmpbfreader::OsmObj) -> bool {
        self.poi_types.iter().any(|(poi_tag, poi_types)| {
            obj.tags().get(poi_tag).map_or(false, |poi_type| poi_types.contains(poi_type))
        })
    }
}

pub fn default_amenity_types() -> BTreeSet<String> {
    ["university",
     "hospital",
     "post_office",
     "bicycle_rental",
     "bicycle_parking",
     "parking",
     "police",
     "townhall"]
        .iter()
        .map(|&k| k.to_string())
        .collect()
}

pub fn default_leisure_types() -> BTreeSet<String> {
    ["garden", "park"]
        .iter()
        .map(|&k| k.to_string())
        .collect()
}

fn parse_poi(osmobj: &osmpbfreader::OsmObj,
             obj_map: &BTreeMap<osmpbfreader::OsmId, osmpbfreader::OsmObj>,
             admins_geofinder: &AdminGeoFinder,
             city_level: u32)
             -> Option<mimir::Poi> {
    let (id, coord) = match *osmobj {
        osmpbfreader::OsmObj::Node(ref node) => {
            (format_poi_id("node", node.id), mimir::Coord::new(node.lat, node.lon))
        }
        osmpbfreader::OsmObj::Way(ref way) => {
            (format_poi_id("way", way.id), get_way_coord(obj_map, way))
        }
        osmpbfreader::OsmObj::Relation(ref relation) => {
            (format_poi_id("relation", relation.id),
             make_centroid(&build_boundary(&relation, &obj_map)))
        }
    };

    let name = osmobj.tags().get("name").map_or("", |name| name);

    if coord.is_default() {
        warn!("The poi {} is rejected, cause: without coordinates.", id);
        return None;
    }

    if name == "" {
        warn!("The poi {} is rejected, cause: without name.", id);
        return None;
    }

    let adms = admins_geofinder.get(&coord);
    let zip_codes = match osmobj.tags().get("addr:postcode") {
        Some(val) if !val.is_empty() => vec![val.clone()],
        _ => get_zip_codes_from_admins(&adms),
    };
    Some(mimir::Poi {
        id: id,
        name: name.to_string(),
        label: format_label(&adms, city_level, name),
        coord: coord,
        zip_codes: zip_codes,
        administrative_regions: adms,
        weight: 1,
    })
}

fn format_poi_id(_type: &str, id: i64) -> String {
    format!("poi:osm:{}:{}", _type, id)
}

pub fn pois(pbf: &mut OsmPbfReader,
            poi_types: PoiTypes,
            admins_geofinder: &AdminGeoFinder,
            city_level: u32)
            -> PoisVec {
    let matcher = PoiMatcher::new(poi_types);
    let objects = osmpbfreader::get_objs_and_deps(pbf, |o| matcher.is_poi(o)).unwrap();
    objects.iter()
        .filter(|&(_, obj)| matcher.is_poi(&obj))
        .map(|(_, obj)| parse_poi(obj, &objects, admins_geofinder, city_level))
        .filter(|o| o.is_some())
        .map(|o| o.unwrap())
        .collect()
}

pub fn compute_poi_weight(pois_vec: &mut PoisVec, city_level: u32) {
    for poi in pois_vec {
        for admin in &mut poi.administrative_regions {
            if admin.level == city_level {
                poi.weight = admin.weight.get();
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::str::SplitWhitespace;
use std::fs::File;

use agb_core::gameboy::Gameboy;
use agb_core::gameboy::debugger::{Breakpoint, DebuggerInterface, AccessType};
use super::{parse_u16, parse_u8, parse_usize};

use image;

pub fn debug(input: String, gameboy: &mut Gameboy, paused: &mut bool) {
	let mut command = input.trim().split_whitespace();
	if let Some(next) = command.next() {
		match next {
			"breakpoint" => breakpoint(&mut command, gameboy),
			"step" => {
				gameboy.debug_step();
			},
			"continue" | "resume" => {
				*paused = false;
				gameboy.debug_step();  //if paused on a breakpoint, need to step over it
			},
			"pause" | "break" => {
				*paused = true;
			},
			"registers" => {
				println!("{:#?}", gameboy.get_registers());
			},
			"memory" => memory(&mut command, gameboy),
			"assembly" => assembly(gameboy),
			"dump_tiles" => dump_tiles(&mut command, gameboy),
			"dump_bg" => dump_bg(&mut command, gameboy),
			"reset" => {
				gameboy.reset();
			},
			"help" => {
				println!("available commands are:\n\
				breakpoint add <type> <address>  - add a breakpoint at <address>, valid types are {{ execute, jump, read, write }}\n\
				breakpoint list           - get a list of breakpoints\n\
				breakpoint remove <index> - remove the breakpoint with index <index> (from list)\n\
				step                      - step forward 1 instruction\n\
				continue | resume         - continue execution\n\
				pause | break             - pause execution\n\
				registers                 - print out the contents of the registers\n\
				memory read <address>     - read the byte at <address>\n\
				memory write <address> <value> - write <value> at <address>\n\
				assembly                  - print out the dissasembly of the current pc\n\
				reset                     - reset the gameboy (keeps breakpoints and any rom/ram patches)\n\
				dump_tiles <filename>     - dumps the tiles in vram as an image named <filename>.png (or tiles.png if no filename is provided)\n\
				dump_bg <filename>        - dumps the background as an image to <filename>.png (or bg.png if no filename is provided)
				quit | exit               - terminate the emulator");
			},
			_ => { println!("invalid command (try typing 'help')"); }
		};
	}
}

pub fn breakpoint(command: &mut SplitWhitespace, gameboy: &mut Gameboy) {
	match command.next() {
		Some(subcommand) => {
			match subcommand {
				"add" => {
					let access_type: Option<AccessType> = match command.next() {
						Some("execute") => Some(AccessType::Execute),
						Some("read") => Some(AccessType::Read),
						Some("write") => Some(AccessType::Write),
						Some("jump") => Some(AccessType::Jump),
						Some(_) => {
							println!("invalid access type");
							None
						},
						None => {
							println!("missing access type");
							None
						}
					};
					let address: Option<u16> = match command.next() {
						Some(address_literal) => {
							match parse_u16(address_literal) {
								//TODO: other access types
								Ok(address) => Some(address),
								Err(_) => {
									println!("invalid address");
									None
								},
							}
						},
						None => {
							println!("missing address");
							None
						},
					};
					if let (Some(access_type), Some(address)) = (access_type, address) {
						let breakpoint = Breakpoint::new(address, access_type);
						gameboy.add_breakpoint(breakpoint);
					}

				},
				"list" => {
					let breakpoints = gameboy.get_breakpoints();
					if breakpoints.len() == 0 {
						println!("no breakpoints");
					}
					for (number, breakpoint) in breakpoints.iter().enumerate() {
						println!("{}: address: 0x{:x}, access_type: {:?}", number, breakpoint.address, breakpoint.access_type);
					}
				},
				"remove" => {
					match command.next() {
						Some(parameter) => {
							match parse_usize(parameter) {
								Ok(index) => {
									match gameboy.remove_breakpoint(index) {
										Ok(breakpoint) => {
											println!("removed breakpoint {{ address: 0x{:x}, access_type: {:?} }}", breakpoint.address, breakpoint.access_type);
										},
										Err(_) => {
											println!("the breakpoint you are trying to remove doesn't exist");
										}
									}
								},
								Err(_) => {
									println!("invalid argument: must be an integer");
								}
							};
						},
						None => {
							println!("invalid usage: specify which interrupt to remove (use the number you got from breakpoint list)");
						}
					}
				}
				_ => { println!("invalid usage: subcommands of breakpoint are {{ add, list, remove }}"); },
			};
		},
		None => println!("invalid usage: missing subcommand"),
	};
}

pub fn memory(command: &mut SplitWhitespace, gameboy: &mut Gameboy) {
	match command.next() {
		Some(subcommand) => {
			match subcommand {
				"read" =>  {
					match command.next() {
						Some(address_literal) => {
							match parse_u16(address_literal) {
								Ok(address) => {
									let value = gameboy.read_memory(address);
									println!("[0x{:x}] = 0x{:x}", address, value);
								}
								Err(_) => {
									println!("invalid address");
								}
							}
						}
						None => {
							println!("you need to specify an address");
						}
					};
				},
				"write" => {
					match command.next() {
						Some(address_literal) => {
							match command.next() {
								Some(value_literal) => {
									let address = parse_u16(address_literal);
									let value = parse_u8(value_literal);
									match (address, value) {
										(Ok(address), Ok(value)) => {
											gameboy.write_memory(address, value);
										},
										(address, value) => {
											if address.is_err() { println!("invalid address"); }
											if value.is_err() { println!("invalid value"); }
										}
									};
								},
								None => {
									println!("invalid usage: specify a value to write")
								}
							}
						}
						None => {
							println!("invalid usage: specify an address");
						}
					};
				},
				_ => {},
			};
		},
		None => {}
	};
}

pub fn dump_tiles(command: &mut SplitWhitespace, gameboy: &mut Gameboy) {
	let path = match command.next() {
		Some(arg) => {
			let mut path = String::from(arg);
			if !path.ends_with(".png") {
				path.push_str(".png");
			}
			path
		},
		None => String::from("tiles.png")
	};
	let raw = gameboy.dump_tiles();
	let file = File::create(path);
	match file {
		Ok(file) => {
			//Convert the u32 pixels into rgba structs for the image library
			let mut buffer: Vec<u8> = Vec::with_capacity(raw.data.len() * 4);
			for val in raw.data.iter() {
				buffer.push((val >> 24) as u8);
				buffer.push((val >> 16) as u8);
				buffer.push((val >> 8) as u8);
				buffer.push((val & 0xFF) as u8);
			}
			let encoder = image::png::PNGEncoder::new(file);
			match encoder.encode(buffer.as_slice(), raw.width as u32, raw.height as u32, image::ColorType::RGBA(8)) {
				Ok(_) => {},
				Err(_) => println!("failed to save tile data to disk")
			};
		},
		Err(e) => println!("{}", e),
	};
}

pub fn dump_bg(command: &mut SplitWhitespace, gameboy: &mut Gameboy) {
	let path = match command.next() {
		Some(arg) => {
			let mut path = String::from(arg);
			if !path.ends_with(".png") {
				path.push_str(".png");
			}
			path
		},
		None => String::from("bg.png"),
	};
	let raw = gameboy.dump_bg();
	let file = File::create(path);
	match file {
		Ok(file) => {
			//Convert the u32 pixels into rgba structs for the image library
			let mut buffer: Vec<u8> = Vec::with_capacity(raw.data.len() * 4);
			for val in raw.data.iter() {
				buffer.push((val >> 24) as u8);
				buffer.push((val >> 16) as u8);
				buffer.push((val >> 8) as u8);
				buffer.push((val & 0xFF) as u8);
			}
			let encoder = image::png::PNGEncoder::new(file);
			match encoder.encode(buffer.as_slice(), raw.width as u32, raw.height as u32, image::ColorType::RGBA(8)) {
				Ok(_) => {},
				Err(_) => println!("failed to save tile data to disk")
			};
		},
		Err(e) => println!("{}", e),
	};
}

pub fn assembly(gameboy: &mut Gameboy) {
	use std::cmp::{max,min};

	let pc = gameboy.get_registers().pc;
	let start:usize = min((pc as usize) - 5, (pc as usize));
	let end = min(start + 5, 0xFFFF);
	let data = gameboy.read_range(start as u16, end as u16).unwrap(); //largest opcode is 3 bytes
	let before = gameboy.get_assembly(&data);

	let start = pc as usize;
	let end = max(start + 5, start);
	let data = gameboy.read_range(start as u16, end as u16).unwrap();
	let after = gameboy.get_assembly(&data);

	for op in before {
		println!("{}", op);
	}
	for (line,op) in after.iter().enumerate() {
		match line {
			0 => { println!("{} <---", op); },
			_ => { println!("{}", op); },
		};
	}
}
<commit_msg>Output addresses for each dissasembled instruction.<commit_after>use std::str::SplitWhitespace;
use std::fs::File;

use agb_core::gameboy::Gameboy;
use agb_core::gameboy::assembly;
use agb_core::gameboy::debugger::{Breakpoint, DebuggerInterface, AccessType};
use super::{parse_u16, parse_u8, parse_usize};

use image;

pub fn debug(input: String, gameboy: &mut Gameboy, paused: &mut bool) {
	let mut command = input.trim().split_whitespace();
	if let Some(next) = command.next() {
		match next {
			"breakpoint" => breakpoint(&mut command, gameboy),
			"step" => {
				gameboy.debug_step();
			},
			"continue" | "resume" => {
				*paused = false;
				gameboy.debug_step();  //if paused on a breakpoint, need to step over it
			},
			"pause" | "break" => {
				*paused = true;
			},
			"registers" => {
				println!("{:#?}", gameboy.get_registers());
			},
			"memory" => memory(&mut command, gameboy),
			"assembly" => assembly(gameboy),
			"dump_tiles" => dump_tiles(&mut command, gameboy),
			"dump_bg" => dump_bg(&mut command, gameboy),
			"reset" => {
				gameboy.reset();
			},
			"help" => {
				println!("available commands are:\n\
				breakpoint add <type> <address>  - add a breakpoint at <address>, valid types are {{ execute, jump, read, write }}\n\
				breakpoint list           - get a list of breakpoints\n\
				breakpoint remove <index> - remove the breakpoint with index <index> (from list)\n\
				step                      - step forward 1 instruction\n\
				continue | resume         - continue execution\n\
				pause | break             - pause execution\n\
				registers                 - print out the contents of the registers\n\
				memory read <address>     - read the byte at <address>\n\
				memory write <address> <value> - write <value> at <address>\n\
				assembly                  - print out the dissasembly of the current pc\n\
				reset                     - reset the gameboy (keeps breakpoints and any rom/ram patches)\n\
				dump_tiles <filename>     - dumps the tiles in vram as an image named <filename>.png (or tiles.png if no filename is provided)\n\
				dump_bg <filename>        - dumps the background as an image to <filename>.png (or bg.png if no filename is provided)
				quit | exit               - terminate the emulator");
			},
			_ => { println!("invalid command (try typing 'help')"); }
		};
	}
}

pub fn breakpoint(command: &mut SplitWhitespace, gameboy: &mut Gameboy) {
	match command.next() {
		Some(subcommand) => {
			match subcommand {
				"add" => {
					let access_type: Option<AccessType> = match command.next() {
						Some("execute") => Some(AccessType::Execute),
						Some("read") => Some(AccessType::Read),
						Some("write") => Some(AccessType::Write),
						Some("jump") => Some(AccessType::Jump),
						Some(_) => {
							println!("invalid access type");
							None
						},
						None => {
							println!("missing access type");
							None
						}
					};
					let address: Option<u16> = match command.next() {
						Some(address_literal) => {
							match parse_u16(address_literal) {
								//TODO: other access types
								Ok(address) => Some(address),
								Err(_) => {
									println!("invalid address");
									None
								},
							}
						},
						None => {
							println!("missing address");
							None
						},
					};
					if let (Some(access_type), Some(address)) = (access_type, address) {
						let breakpoint = Breakpoint::new(address, access_type);
						gameboy.add_breakpoint(breakpoint);
					}

				},
				"list" => {
					let breakpoints = gameboy.get_breakpoints();
					if breakpoints.len() == 0 {
						println!("no breakpoints");
					}
					for (number, breakpoint) in breakpoints.iter().enumerate() {
						println!("{}: address: 0x{:x}, access_type: {:?}", number, breakpoint.address, breakpoint.access_type);
					}
				},
				"remove" => {
					match command.next() {
						Some(parameter) => {
							match parse_usize(parameter) {
								Ok(index) => {
									match gameboy.remove_breakpoint(index) {
										Ok(breakpoint) => {
											println!("removed breakpoint {{ address: 0x{:x}, access_type: {:?} }}", breakpoint.address, breakpoint.access_type);
										},
										Err(_) => {
											println!("the breakpoint you are trying to remove doesn't exist");
										}
									}
								},
								Err(_) => {
									println!("invalid argument: must be an integer");
								}
							};
						},
						None => {
							println!("invalid usage: specify which interrupt to remove (use the number you got from breakpoint list)");
						}
					}
				}
				_ => { println!("invalid usage: subcommands of breakpoint are {{ add, list, remove }}"); },
			};
		},
		None => println!("invalid usage: missing subcommand"),
	};
}

pub fn memory(command: &mut SplitWhitespace, gameboy: &mut Gameboy) {
	match command.next() {
		Some(subcommand) => {
			match subcommand {
				"read" =>  {
					match command.next() {
						Some(address_literal) => {
							match parse_u16(address_literal) {
								Ok(address) => {
									let value = gameboy.read_memory(address);
									println!("[0x{:x}] = 0x{:x}", address, value);
								}
								Err(_) => {
									println!("invalid address");
								}
							}
						}
						None => {
							println!("you need to specify an address");
						}
					};
				},
				"write" => {
					match command.next() {
						Some(address_literal) => {
							match command.next() {
								Some(value_literal) => {
									let address = parse_u16(address_literal);
									let value = parse_u8(value_literal);
									match (address, value) {
										(Ok(address), Ok(value)) => {
											gameboy.write_memory(address, value);
										},
										(address, value) => {
											if address.is_err() { println!("invalid address"); }
											if value.is_err() { println!("invalid value"); }
										}
									};
								},
								None => {
									println!("invalid usage: specify a value to write")
								}
							}
						}
						None => {
							println!("invalid usage: specify an address");
						}
					};
				},
				_ => {},
			};
		},
		None => {}
	};
}

pub fn dump_tiles(command: &mut SplitWhitespace, gameboy: &mut Gameboy) {
	let path = match command.next() {
		Some(arg) => {
			let mut path = String::from(arg);
			if !path.ends_with(".png") {
				path.push_str(".png");
			}
			path
		},
		None => String::from("tiles.png")
	};
	let raw = gameboy.dump_tiles();
	let file = File::create(path);
	match file {
		Ok(file) => {
			//Convert the u32 pixels into rgba structs for the image library
			let mut buffer: Vec<u8> = Vec::with_capacity(raw.data.len() * 4);
			for val in raw.data.iter() {
				buffer.push((val >> 24) as u8);
				buffer.push((val >> 16) as u8);
				buffer.push((val >> 8) as u8);
				buffer.push((val & 0xFF) as u8);
			}
			let encoder = image::png::PNGEncoder::new(file);
			match encoder.encode(buffer.as_slice(), raw.width as u32, raw.height as u32, image::ColorType::RGBA(8)) {
				Ok(_) => {},
				Err(_) => println!("failed to save tile data to disk")
			};
		},
		Err(e) => println!("{}", e),
	};
}

pub fn dump_bg(command: &mut SplitWhitespace, gameboy: &mut Gameboy) {
	let path = match command.next() {
		Some(arg) => {
			let mut path = String::from(arg);
			if !path.ends_with(".png") {
				path.push_str(".png");
			}
			path
		},
		None => String::from("bg.png"),
	};
	let raw = gameboy.dump_bg();
	let file = File::create(path);
	match file {
		Ok(file) => {
			//Convert the u32 pixels into rgba structs for the image library
			let mut buffer: Vec<u8> = Vec::with_capacity(raw.data.len() * 4);
			for val in raw.data.iter() {
				buffer.push((val >> 24) as u8);
				buffer.push((val >> 16) as u8);
				buffer.push((val >> 8) as u8);
				buffer.push((val & 0xFF) as u8);
			}
			let encoder = image::png::PNGEncoder::new(file);
			match encoder.encode(buffer.as_slice(), raw.width as u32, raw.height as u32, image::ColorType::RGBA(8)) {
				Ok(_) => {},
				Err(_) => println!("failed to save tile data to disk")
			};
		},
		Err(e) => println!("{}", e),
	};
}

pub fn assembly(gameboy: &mut Gameboy) {
	use std::cmp::min;

	let pc = gameboy.get_registers().pc;
	let start:usize = pc as usize;
	let end = min(start + 5, 0xFFFF);
	let data = gameboy.read_range(start as u16, end as u16).unwrap(); //largest opcode is 3 bytes
	let after = gameboy.get_assembly(&data);

	let mut offset: usize = 0;
	for (line,op) in after.iter().enumerate() {
		match line {
			0 => { println!("{:04X}: {} <---", (offset + start) as u16, op); },
			_ => { println!("{:04X}: {}", (offset + start) as u16, op); },
		};
		offset += assembly::INSTRUCTION_LENGTH[data[offset] as usize];
	}
}
<|endoftext|>


<commit_before>//! Common HTTP functionality for the Teepee project.
//!
//! Anything shared between both client and server belongs in here, but this crate is not expected
//! to be used directly.
//!
//! Any crate using types from this crate should re‐export them. For example, the ``status`` module
//! should be exported in the root of the HTTP client crate ``httpc`` so that people can write
//! ``httpc::status`` instead of ``httpcommon::status``.

#![crate_name = "httpcommon"]
#![comment = "Common HTTP functionality for the Teepee project"]
#![license = "MIT/ASL2"]
#![crate_type = "lib"]

#![doc(html_logo_url = "http://teepee.rs/logo.100.png",
       html_root_url = "http://www.rust-ci.org/teepee/teepee/doc/")]

#![feature(globs, macro_rules, phase, slicing_syntax)]

#![warn(unused_qualifications, non_upper_case_globals, unused_typecasts, missing_docs,
        unused_results)]
//#![warn(unstable)]

#[phase(plugin)]
extern crate phf_mac;
extern crate phf;

pub mod method;
pub mod status;
pub mod headers;
pub mod grammar;
<commit_msg>unused_qualifications is a bit noisy just at present!<commit_after>//! Common HTTP functionality for the Teepee project.
//!
//! Anything shared between both client and server belongs in here, but this crate is not expected
//! to be used directly.
//!
//! Any crate using types from this crate should re‐export them. For example, the ``status`` module
//! should be exported in the root of the HTTP client crate ``httpc`` so that people can write
//! ``httpc::status`` instead of ``httpcommon::status``.

#![crate_name = "httpcommon"]
#![comment = "Common HTTP functionality for the Teepee project"]
#![license = "MIT/ASL2"]
#![crate_type = "lib"]

#![doc(html_logo_url = "http://teepee.rs/logo.100.png",
       html_root_url = "http://www.rust-ci.org/teepee/teepee/doc/")]

#![feature(globs, macro_rules, phase, slicing_syntax)]

#![warn(non_upper_case_globals, unused_typecasts, missing_docs, unused_results)]
//#![warn(unstable)]

#[phase(plugin)]
extern crate phf_mac;
extern crate phf;

pub mod method;
pub mod status;
pub mod headers;
pub mod grammar;
<|endoftext|>


<commit_before>pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = c_long;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type suseconds_t = i64;

s! {
    pub struct timeval {
        pub tv_sec: time_t,
        pub tv_usec: suseconds_t,
    }

    pub struct timespec {
        pub tv_sec: time_t,
        pub tv_nsec: c_long,
    }
}

pub const STDIN_FILENO: ::c_int = 0;
pub const STDOUT_FILENO: ::c_int = 1;
pub const STDERR_FILENO: ::c_int = 2;

pub const EXIT_FAILURE: ::c_int = 1;
pub const EXIT_SUCCESS: ::c_int = 0;

pub const S_ISUID: ::c_int = 0x800;
pub const S_ISGID: ::c_int = 0x400;
pub const S_ISVTX: ::c_int = 0x200;

pub const S_IFIFO: mode_t = 0x1000;
pub const S_IFCHR: mode_t = 0x2000;
pub const S_IFBLK: mode_t = 0x6000;
pub const S_IFDIR: mode_t = 0x4000;
pub const S_IFREG: mode_t = 0x8000;
pub const S_IFLNK: mode_t = 0xA000;
pub const S_IFSOCK: mode_t = 0xC000;
pub const S_IFMT: mode_t = 0xF000;
pub const S_IEXEC: mode_t = 0x40;
pub const S_IWRITE: mode_t = 0x80;
pub const S_IREAD: mode_t = 0x100;
pub const S_IRWXU: mode_t = 0x1C0;
pub const S_IXUSR: mode_t = 0x40;
pub const S_IWUSR: mode_t = 0x80;
pub const S_IRUSR: mode_t = 0x100;
pub const S_IRWXG: mode_t = 0x38;
pub const S_IXGRP: mode_t = 0x8;
pub const S_IWGRP: mode_t = 0x10;
pub const S_IRGRP: mode_t = 0x20;
pub const S_IRWXO: mode_t = 0x7;
pub const S_IXOTH: mode_t = 0x1;
pub const S_IWOTH: mode_t = 0x2;
pub const S_IROTH: mode_t = 0x4;

pub const F_DUPFD: ::c_int = 0;
pub const F_GETFD: ::c_int = 1;
pub const F_SETFD: ::c_int = 2;
pub const F_GETFL: ::c_int = 3;
pub const F_SETFL: ::c_int = 4;

pub const O_RDONLY: ::c_int =     0x0001_0000;
pub const O_WRONLY: ::c_int =     0x0002_0000;
pub const O_RDWR: ::c_int =       0x0003_0000;
pub const O_NONBLOCK: ::c_int =   0x0004_0000;
pub const O_APPEND: ::c_int =     0x0008_0000;
pub const O_SHLOCK: ::c_int =     0x0010_0000;
pub const O_EXLOCK: ::c_int =     0x0020_0000;
pub const O_ASYNC: ::c_int =      0x0040_0000;
pub const O_FSYNC: ::c_int =      0x0080_0000;
pub const O_CLOEXEC: ::c_int =    0x0100_0000;
pub const O_CREAT: ::c_int =      0x0200_0000;
pub const O_TRUNC: ::c_int =      0x0400_0000;
pub const O_EXCL: ::c_int =       0x0800_0000;
pub const O_DIRECTORY: ::c_int =  0x1000_0000;
pub const O_STAT: ::c_int =       0x2000_0000;
pub const O_SYMLINK: ::c_int =    0x4000_0000;
pub const O_NOFOLLOW: ::c_int =   0x8000_0000;
pub const O_ACCMODE: ::c_int =    O_RDONLY | O_WRONLY | O_RDWR;

pub const SIGHUP:    ::c_int = 1;
pub const SIGINT:    ::c_int = 2;
pub const SIGQUIT:   ::c_int = 3;
pub const SIGILL:    ::c_int = 4;
pub const SIGTRAP:   ::c_int = 5;
pub const SIGABRT:   ::c_int = 6;
pub const SIGBUS:    ::c_int = 7;
pub const SIGFPE:    ::c_int = 8;
pub const SIGKILL:   ::c_int = 9;
pub const SIGUSR1:   ::c_int = 10;
pub const SIGSEGV:   ::c_int = 11;
pub const SIGUSR2:   ::c_int = 12;
pub const SIGPIPE:   ::c_int = 13;
pub const SIGALRM:   ::c_int = 14;
pub const SIGTERM:   ::c_int = 15;
pub const SIGSTKFLT: ::c_int = 16;
pub const SIGCHLD:   ::c_int = 17;
pub const SIGCONT:   ::c_int = 18;
pub const SIGSTOP:   ::c_int = 19;
pub const SIGTSTP:   ::c_int = 20;
pub const SIGTTIN:   ::c_int = 21;
pub const SIGTTOU:   ::c_int = 22;
pub const SIGURG:    ::c_int = 23;
pub const SIGXCPU:   ::c_int = 24;
pub const SIGXFSZ:   ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF:   ::c_int = 27;
pub const SIGWINCH:  ::c_int = 28;
pub const SIGIO:     ::c_int = 29;
pub const SIGPWR:    ::c_int = 30;
pub const SIGSYS:    ::c_int = 31;

extern {
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
                -> ::ssize_t;
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
                 -> ::ssize_t;
    pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
    pub fn close(fd: ::c_int) -> ::c_int;
}

#[link(name = "c")]
#[link(name = "m")]
extern {}

pub use self::net::*;

mod net;
<commit_msg>Auto merge of #1008 - stratact:master, r=alexcrichton<commit_after>pub type c_char = i8;
pub type c_long = i64;
pub type c_ulong = u64;

pub type wchar_t = i16;

pub type off_t = c_long;
pub type mode_t = u16;
pub type time_t = i64;
pub type pid_t = usize;
pub type gid_t = usize;
pub type uid_t = usize;

pub type suseconds_t = i64;

s! {
    pub struct timeval {
        pub tv_sec: time_t,
        pub tv_usec: suseconds_t,
    }

    pub struct timespec {
        pub tv_sec: time_t,
        pub tv_nsec: c_long,
    }
}

pub const STDIN_FILENO: ::c_int = 0;
pub const STDOUT_FILENO: ::c_int = 1;
pub const STDERR_FILENO: ::c_int = 2;

pub const EXIT_FAILURE: ::c_int = 1;
pub const EXIT_SUCCESS: ::c_int = 0;

pub const S_ISUID: ::c_int = 0x800;
pub const S_ISGID: ::c_int = 0x400;
pub const S_ISVTX: ::c_int = 0x200;

pub const S_IFIFO: mode_t = 0x1000;
pub const S_IFCHR: mode_t = 0x2000;
pub const S_IFBLK: mode_t = 0x6000;
pub const S_IFDIR: mode_t = 0x4000;
pub const S_IFREG: mode_t = 0x8000;
pub const S_IFLNK: mode_t = 0xA000;
pub const S_IFSOCK: mode_t = 0xC000;
pub const S_IFMT: mode_t = 0xF000;
pub const S_IEXEC: mode_t = 0x40;
pub const S_IWRITE: mode_t = 0x80;
pub const S_IREAD: mode_t = 0x100;
pub const S_IRWXU: mode_t = 0x1C0;
pub const S_IXUSR: mode_t = 0x40;
pub const S_IWUSR: mode_t = 0x80;
pub const S_IRUSR: mode_t = 0x100;
pub const S_IRWXG: mode_t = 0x38;
pub const S_IXGRP: mode_t = 0x8;
pub const S_IWGRP: mode_t = 0x10;
pub const S_IRGRP: mode_t = 0x20;
pub const S_IRWXO: mode_t = 0x7;
pub const S_IXOTH: mode_t = 0x1;
pub const S_IWOTH: mode_t = 0x2;
pub const S_IROTH: mode_t = 0x4;

pub const F_DUPFD: ::c_int = 0;
pub const F_GETFD: ::c_int = 1;
pub const F_SETFD: ::c_int = 2;
pub const F_GETFL: ::c_int = 3;
pub const F_SETFL: ::c_int = 4;

pub const O_RDONLY: ::c_int =     0x0001_0000;
pub const O_WRONLY: ::c_int =     0x0002_0000;
pub const O_RDWR: ::c_int =       0x0003_0000;
pub const O_NONBLOCK: ::c_int =   0x0004_0000;
pub const O_APPEND: ::c_int =     0x0008_0000;
pub const O_SHLOCK: ::c_int =     0x0010_0000;
pub const O_EXLOCK: ::c_int =     0x0020_0000;
pub const O_ASYNC: ::c_int =      0x0040_0000;
pub const O_FSYNC: ::c_int =      0x0080_0000;
pub const O_CLOEXEC: ::c_int =    0x0100_0000;
pub const O_CREAT: ::c_int =      0x0200_0000;
pub const O_TRUNC: ::c_int =      0x0400_0000;
pub const O_EXCL: ::c_int =       0x0800_0000;
pub const O_DIRECTORY: ::c_int =  0x1000_0000;
pub const O_STAT: ::c_int =       0x2000_0000;
pub const O_SYMLINK: ::c_int =    0x4000_0000;
pub const O_NOFOLLOW: ::c_int =   0x8000_0000;
pub const O_ACCMODE: ::c_int =    O_RDONLY | O_WRONLY | O_RDWR;

pub const SIGHUP:    ::c_int = 1;
pub const SIGINT:    ::c_int = 2;
pub const SIGQUIT:   ::c_int = 3;
pub const SIGILL:    ::c_int = 4;
pub const SIGTRAP:   ::c_int = 5;
pub const SIGABRT:   ::c_int = 6;
pub const SIGBUS:    ::c_int = 7;
pub const SIGFPE:    ::c_int = 8;
pub const SIGKILL:   ::c_int = 9;
pub const SIGUSR1:   ::c_int = 10;
pub const SIGSEGV:   ::c_int = 11;
pub const SIGUSR2:   ::c_int = 12;
pub const SIGPIPE:   ::c_int = 13;
pub const SIGALRM:   ::c_int = 14;
pub const SIGTERM:   ::c_int = 15;
pub const SIGSTKFLT: ::c_int = 16;
pub const SIGCHLD:   ::c_int = 17;
pub const SIGCONT:   ::c_int = 18;
pub const SIGSTOP:   ::c_int = 19;
pub const SIGTSTP:   ::c_int = 20;
pub const SIGTTIN:   ::c_int = 21;
pub const SIGTTOU:   ::c_int = 22;
pub const SIGURG:    ::c_int = 23;
pub const SIGXCPU:   ::c_int = 24;
pub const SIGXFSZ:   ::c_int = 25;
pub const SIGVTALRM: ::c_int = 26;
pub const SIGPROF:   ::c_int = 27;
pub const SIGWINCH:  ::c_int = 28;
pub const SIGIO:     ::c_int = 29;
pub const SIGPWR:    ::c_int = 30;
pub const SIGSYS:    ::c_int = 31;

extern {
    pub fn gethostname(name: *mut ::c_char, len: ::size_t) -> ::c_int;
    pub fn memalign(align: ::size_t, size: ::size_t) -> *mut ::c_void;
    pub fn read(fd: ::c_int, buf: *mut ::c_void, count: ::size_t)
                -> ::ssize_t;
    pub fn write(fd: ::c_int, buf: *const ::c_void, count: ::size_t)
                 -> ::ssize_t;
    pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int;
    pub fn close(fd: ::c_int) -> ::c_int;
}

#[link(name = "c")]
#[link(name = "m")]
extern {}

pub use self::net::*;

mod net;
<|endoftext|>


<commit_before>use tcod::console::Console;
use tcod::Color;
use tcod::colors;

use traits::{Position, Renderable};
use units::Unit;
use {SCREEN_HEIGHT, SCREEN_WIDTH, PANEL_HEIGHT};

use point::Point;

const MAP_WIDTH: i8 = SCREEN_WIDTH;
const MAP_HEIGHT: i8 = SCREEN_HEIGHT - PANEL_HEIGHT;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TileType {
    Floor,
    Wall,
}

impl TileType {
    fn get_color(self) -> Color {
        match self {
            TileType::Floor => Color::new(50, 50, 150),
            TileType::Wall => Color::new(0, 0, 100),
        }
    }

    fn get_glyph(self) -> char {
        match self {
            TileType::Floor => '.',
            TileType::Wall => '#',
        }
    }

    pub fn blocks_move(self) -> bool {
        match self {
            TileType::Floor => false,
            TileType::Wall => true,
        }
    }

    pub fn blocks_sight(self) -> bool {
        match self {
            TileType::Floor => false,
            TileType::Wall => true,
        }
    }
}

#[derive(Debug)]
pub struct Tile {
    position: Point<i8>,
    tile_type: TileType,
}

impl Position for Tile {
    fn get_x(&self) -> i8 {
        self.position.x
    }

    fn get_y(&self) -> i8 {
        self.position.y
    }
}

impl Renderable for Tile {
    fn get_color(&self) -> Color {
        self.tile_type.get_color()
    }
    fn get_glyph(&self) -> char {
        self.tile_type.get_glyph()
    }
}

impl Tile {
    pub fn new(pos: Point<i8>, tile_type: TileType) -> Tile {
        Tile{
            position: pos,
            tile_type: tile_type
        }
    }
}

#[derive(Debug)]
pub struct Map {
    tile_map: Vec<Tile>,
    npcs: Vec<Unit>,
}

impl Map {
    pub fn init() -> Map {
        let mut map = vec![];
        for y in 0..MAP_HEIGHT {
            for x in 0..MAP_WIDTH {
                map.push( Tile::new(Point{x: x, y: y}, TileType::Floor) );
            }
        }

        Map {
            tile_map: map,
            npcs: vec![Unit::new(Point{x: 5, y: 5}, '@', colors::YELLOW)],
        }
    }

    pub fn render_map<T: Console>(&self, cons: &mut T) {
        for tile in self.tile_map.iter() {
            tile.render(cons);
        }
    }

    pub fn render_npcs<T: Console>(&self, cons: &mut T) {
        for unit in self.npcs.iter() {
            unit.render(cons);
        }
    }

    pub fn point_in_map(&self, Point{x,y}: Point<i8>) -> bool {
        x >= 0 && x < MAP_WIDTH && y >= 0 && y < MAP_HEIGHT
    }

    pub fn get_tile_type(&self, pos: Point<i8>) -> Result<TileType,()> {
        if !self.point_in_map(pos) {
            Err(())
        } else {
            let Point{x, y} = pos;
            Ok(self.tile_map[y as usize * MAP_HEIGHT as usize + x as usize].tile_type)
        }
    }
}<commit_msg>Added function to set a tile type. Added test wall. Changed wall colour.<commit_after>use tcod::console::Console;
use tcod::Color;
use tcod::colors;

use traits::{Position, Renderable};
use units::Unit;
use {SCREEN_HEIGHT, SCREEN_WIDTH, PANEL_HEIGHT};

use point::Point;

const MAP_WIDTH: i8 = SCREEN_WIDTH;
const MAP_HEIGHT: i8 = SCREEN_HEIGHT - PANEL_HEIGHT;

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TileType {
    Floor,
    Wall,
}

impl TileType {
    fn get_color(self) -> Color {
        match self {
            TileType::Floor => Color::new(50, 50, 150),
            TileType::Wall => Color::new(240, 240, 240),
        }
    }

    fn get_glyph(self) -> char {
        match self {
            TileType::Floor => '.',
            TileType::Wall => '#',
        }
    }

    pub fn blocks_move(self) -> bool {
        match self {
            TileType::Floor => false,
            TileType::Wall => true,
        }
    }

    pub fn blocks_sight(self) -> bool {
        match self {
            TileType::Floor => false,
            TileType::Wall => true,
        }
    }
}

#[derive(Debug)]
pub struct Tile {
    position: Point<i8>,
    tile_type: TileType,
}

impl Position for Tile {
    fn get_x(&self) -> i8 {
        self.position.x
    }

    fn get_y(&self) -> i8 {
        self.position.y
    }
}

impl Renderable for Tile {
    fn get_color(&self) -> Color {
        self.tile_type.get_color()
    }
    fn get_glyph(&self) -> char {
        self.tile_type.get_glyph()
    }
}

impl Tile {
    pub fn new(pos: Point<i8>, tile_type: TileType) -> Tile {
        Tile{
            position: pos,
            tile_type: tile_type
        }
    }
}

#[derive(Debug)]
pub struct Map {
    tile_map: Vec<Tile>,
    npcs: Vec<Unit>,
}

impl Map {
    pub fn init() -> Map {
        let mut map = vec![];
        for y in 0..MAP_HEIGHT {
            for x in 0..MAP_WIDTH {
                map.push( Tile::new(Point{x: x, y: y}, TileType::Floor) );
            }
        }

        let mut map = Map {
            tile_map: map,
            npcs: vec![Unit::new(Point{x: 5, y: 5}, '@', colors::YELLOW)],
        };

        map.set_tile_type(Point{x: 5, y: 3}, TileType::Wall).expect("Failed to set tile.");

        map
    }

    pub fn render_map<T: Console>(&self, cons: &mut T) {
        for tile in self.tile_map.iter() {
            tile.render(cons);
        }
    }

    pub fn render_npcs<T: Console>(&self, cons: &mut T) {
        for unit in self.npcs.iter() {
            unit.render(cons);
        }
    }

    pub fn point_in_map(&self, Point{x,y}: Point<i8>) -> bool {
        x >= 0 && x < MAP_WIDTH && y >= 0 && y < MAP_HEIGHT
    }

    pub fn get_tile_type(&self, pos: Point<i8>) -> Result<TileType,()> {
        if !self.point_in_map(pos) {
            Err(())
        } else {
            let Point{x, y} = pos;
            Ok(self.tile_map[y as usize * MAP_HEIGHT as usize + x as usize].tile_type)
        }
    }

    fn set_tile_type(&mut self, pos: Point<i8>, new_tile: TileType) -> Result<(),()> {
        if !self.point_in_map(pos) {
            Err(())
        } else {
            let Point{x,y} = pos;
            self.tile_map[y as usize * MAP_HEIGHT as usize + x as usize].tile_type = new_tile;

            Ok(())
        }
    }
}<|endoftext|>


<commit_before>use super::internal::*;
use super::*;
use std::cmp::min;
use std::iter;

pub struct ChainIter<A, B>
    where A: ParallelIterator,
          B: ParallelIterator<Item = A::Item>
{
    a: A,
    b: B,
}

impl<A, B> ChainIter<A, B>
    where A: ParallelIterator,
          B: ParallelIterator<Item = A::Item>
{
    pub fn new(a: A, b: B) -> ChainIter<A, B> {
        ChainIter { a: a, b: b }
    }
}

impl<A, B> ParallelIterator for ChainIter<A, B>
    where A: ParallelIterator,
          B: ParallelIterator<Item = A::Item>
{
    type Item = A::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let reducer = consumer.to_reducer();
        let a = self.a.drive_unindexed(consumer.split_off_left());
        let b = self.b.drive_unindexed(consumer);
        reducer.reduce(a, b)
    }

    fn opt_len(&mut self) -> Option<usize> {
        // NB: Even though we could compute the indexed length as below,
        // we can't support collect's faux `UnindexedConsumer` in our
        // `drive_unindexed`, so we must leave this un-"specialized".
        //
        // match (self.a.opt_len(), self.b.opt_len()) {
        //     (Some(a_len), Some(b_len)) => a_len.checked_add(b_len),
        //     _ => None,
        // }
        None
    }
}

impl<A, B> BoundedParallelIterator for ChainIter<A, B>
    where A: BoundedParallelIterator,
          B: BoundedParallelIterator<Item = A::Item>
{
    fn upper_bound(&mut self) -> usize {
        self.a.upper_bound().checked_add(self.b.upper_bound()).expect("overflow")
    }

    fn drive<C>(mut self, consumer: C) -> C::Result
        where C: Consumer<Self::Item>
    {
        let (left, right, reducer) = consumer.split_at(self.a.upper_bound());
        let a = self.a.drive(left);
        let b = self.b.drive(right);
        reducer.reduce(a, b)
    }
}

impl<A, B> ExactParallelIterator for ChainIter<A, B>
    where A: ExactParallelIterator,
          B: ExactParallelIterator<Item = A::Item>
{
    fn len(&mut self) -> usize {
        self.a.len().checked_add(self.b.len()).expect("overflow")
    }
}

impl<A, B> IndexedParallelIterator for ChainIter<A, B>
    where A: IndexedParallelIterator,
          B: IndexedParallelIterator<Item = A::Item>
{
    fn with_producer<CB>(mut self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        let a_len = self.a.len();
        return self.a.with_producer(CallbackA {
            callback: callback,
            a_len: a_len,
            b: self.b,
        });

        struct CallbackA<CB, B> {
            callback: CB,
            a_len: usize,
            b: B,
        }

        impl<CB, B> ProducerCallback<B::Item> for CallbackA<CB, B>
            where B: IndexedParallelIterator,
                  CB: ProducerCallback<B::Item>
        {
            type Output = CB::Output;

            fn callback<A>(self, a_producer: A) -> Self::Output
                where A: Producer<Item = B::Item>
            {
                return self.b.with_producer(CallbackB {
                    callback: self.callback,
                    a_len: self.a_len,
                    a_producer: a_producer,
                });
            }
        }

        struct CallbackB<CB, A> {
            callback: CB,
            a_len: usize,
            a_producer: A,
        }

        impl<CB, A> ProducerCallback<A::Item> for CallbackB<CB, A>
            where A: Producer,
                  CB: ProducerCallback<A::Item>
        {
            type Output = CB::Output;

            fn callback<B>(self, b_producer: B) -> Self::Output
                where B: Producer<Item = A::Item>
            {
                let producer = ChainProducer::new(self.a_len, self.a_producer, b_producer);
                self.callback.callback(producer)
            }
        }

    }
}

/// ////////////////////////////////////////////////////////////////////////

pub struct ChainProducer<A, B>
    where A: Producer,
          B: Producer<Item = A::Item>
{
    a_len: usize,
    a: A,
    b: B,
}

impl<A, B> ChainProducer<A, B>
    where A: Producer,
          B: Producer<Item = A::Item>
{
    fn new(a_len: usize, a: A, b: B) -> Self {
        ChainProducer {
            a_len: a_len,
            a: a,
            b: b,
        }
    }
}

impl<A, B> Producer for ChainProducer<A, B>
    where A: Producer,
          B: Producer<Item = A::Item>
{
    type Item = A::Item;
    type IntoIter = Chain<A::IntoIter, B::IntoIter>;

    fn into_iter(self) -> Self::IntoIter {
        Chain::new(self.a.into_iter(), self.b.into_iter())
    }

    fn weighted(&self) -> bool {
        self.a.weighted() || self.b.weighted()
    }

    fn cost(&mut self, len: usize) -> f64 {
        let a_len = min(self.a_len, len);
        let b_len = len - a_len;
        self.a.cost(a_len) + self.b.cost(b_len)
    }

    fn split_at(self, index: usize) -> (Self, Self) {
        if index <= self.a_len {
            let a_rem = self.a_len - index;
            let (a_left, a_right) = self.a.split_at(index);
            let (b_left, b_right) = self.b.split_at(0);
            (ChainProducer::new(index, a_left, b_left), ChainProducer::new(a_rem, a_right, b_right))
        } else {
            let (a_left, a_right) = self.a.split_at(self.a_len);
            let (b_left, b_right) = self.b.split_at(index - self.a_len);
            (ChainProducer::new(self.a_len, a_left, b_left),
             ChainProducer::new(0, a_right, b_right))
        }
    }

    fn fold_with<F>(self, mut folder: F) -> F
        where F: Folder<A::Item>,
    {
        folder = self.a.fold_with(folder);
        if folder.full() {
            folder
        } else {
            self.b.fold_with(folder)
        }
    }
}

/// ////////////////////////////////////////////////////////////////////////
/// Wrapper for Chain to implement ExactSizeIterator

pub struct Chain<A, B> {
    chain: iter::Chain<A, B>,
    len: usize,
}

impl<A, B> Chain<A, B> {
    fn new(a: A, b: B) -> Chain<A, B>
        where A: ExactSizeIterator,
              B: ExactSizeIterator<Item=A::Item>
    {
        let len = a.len().checked_add(b.len()).expect("overflow");
        Chain {
            chain: a.chain(b),
            len: len,
        }
    }
}

impl<A, B> Iterator for Chain<A, B> // parameterized over the iterator types
    where A: Iterator,
          B: Iterator<Item=A::Item>
{
    type Item = A::Item;

    fn next(&mut self) -> Option<Self::Item> {
        if self.len != 0 {
            self.len -= 1;
        }
        self.chain.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.len, Some(self.len))
    }
}

impl<A, B> ExactSizeIterator for Chain<A, B>
    where A: ExactSizeIterator,
          B: ExactSizeIterator<Item=A::Item>
{
    fn len(&self) -> usize {
        self.len
    }
}

impl<A, B> DoubleEndedIterator for Chain<A, B>
    where A: DoubleEndedIterator,
          B: DoubleEndedIterator<Item=A::Item>
{
    fn next_back(&mut self) -> Option<Self::Item> {
        if self.len != 0 {
            self.len -= 1;
        }
        self.chain.next_back()
    }
}
<commit_msg>Let Chain wrapper defer its length computation to std::iter::Chain<commit_after>use super::internal::*;
use super::*;
use std::cmp::min;
use std::iter;

pub struct ChainIter<A, B>
    where A: ParallelIterator,
          B: ParallelIterator<Item = A::Item>
{
    a: A,
    b: B,
}

impl<A, B> ChainIter<A, B>
    where A: ParallelIterator,
          B: ParallelIterator<Item = A::Item>
{
    pub fn new(a: A, b: B) -> ChainIter<A, B> {
        ChainIter { a: a, b: b }
    }
}

impl<A, B> ParallelIterator for ChainIter<A, B>
    where A: ParallelIterator,
          B: ParallelIterator<Item = A::Item>
{
    type Item = A::Item;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        let reducer = consumer.to_reducer();
        let a = self.a.drive_unindexed(consumer.split_off_left());
        let b = self.b.drive_unindexed(consumer);
        reducer.reduce(a, b)
    }

    fn opt_len(&mut self) -> Option<usize> {
        // NB: Even though we could compute the indexed length as below,
        // we can't support collect's faux `UnindexedConsumer` in our
        // `drive_unindexed`, so we must leave this un-"specialized".
        //
        // match (self.a.opt_len(), self.b.opt_len()) {
        //     (Some(a_len), Some(b_len)) => a_len.checked_add(b_len),
        //     _ => None,
        // }
        None
    }
}

impl<A, B> BoundedParallelIterator for ChainIter<A, B>
    where A: BoundedParallelIterator,
          B: BoundedParallelIterator<Item = A::Item>
{
    fn upper_bound(&mut self) -> usize {
        self.a.upper_bound().checked_add(self.b.upper_bound()).expect("overflow")
    }

    fn drive<C>(mut self, consumer: C) -> C::Result
        where C: Consumer<Self::Item>
    {
        let (left, right, reducer) = consumer.split_at(self.a.upper_bound());
        let a = self.a.drive(left);
        let b = self.b.drive(right);
        reducer.reduce(a, b)
    }
}

impl<A, B> ExactParallelIterator for ChainIter<A, B>
    where A: ExactParallelIterator,
          B: ExactParallelIterator<Item = A::Item>
{
    fn len(&mut self) -> usize {
        self.a.len().checked_add(self.b.len()).expect("overflow")
    }
}

impl<A, B> IndexedParallelIterator for ChainIter<A, B>
    where A: IndexedParallelIterator,
          B: IndexedParallelIterator<Item = A::Item>
{
    fn with_producer<CB>(mut self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        let a_len = self.a.len();
        return self.a.with_producer(CallbackA {
            callback: callback,
            a_len: a_len,
            b: self.b,
        });

        struct CallbackA<CB, B> {
            callback: CB,
            a_len: usize,
            b: B,
        }

        impl<CB, B> ProducerCallback<B::Item> for CallbackA<CB, B>
            where B: IndexedParallelIterator,
                  CB: ProducerCallback<B::Item>
        {
            type Output = CB::Output;

            fn callback<A>(self, a_producer: A) -> Self::Output
                where A: Producer<Item = B::Item>
            {
                return self.b.with_producer(CallbackB {
                    callback: self.callback,
                    a_len: self.a_len,
                    a_producer: a_producer,
                });
            }
        }

        struct CallbackB<CB, A> {
            callback: CB,
            a_len: usize,
            a_producer: A,
        }

        impl<CB, A> ProducerCallback<A::Item> for CallbackB<CB, A>
            where A: Producer,
                  CB: ProducerCallback<A::Item>
        {
            type Output = CB::Output;

            fn callback<B>(self, b_producer: B) -> Self::Output
                where B: Producer<Item = A::Item>
            {
                let producer = ChainProducer::new(self.a_len, self.a_producer, b_producer);
                self.callback.callback(producer)
            }
        }

    }
}

/// ////////////////////////////////////////////////////////////////////////

pub struct ChainProducer<A, B>
    where A: Producer,
          B: Producer<Item = A::Item>
{
    a_len: usize,
    a: A,
    b: B,
}

impl<A, B> ChainProducer<A, B>
    where A: Producer,
          B: Producer<Item = A::Item>
{
    fn new(a_len: usize, a: A, b: B) -> Self {
        ChainProducer {
            a_len: a_len,
            a: a,
            b: b,
        }
    }
}

impl<A, B> Producer for ChainProducer<A, B>
    where A: Producer,
          B: Producer<Item = A::Item>
{
    type Item = A::Item;
    type IntoIter = Chain<A::IntoIter, B::IntoIter>;

    fn into_iter(self) -> Self::IntoIter {
        Chain::new(self.a.into_iter(), self.b.into_iter())
    }

    fn weighted(&self) -> bool {
        self.a.weighted() || self.b.weighted()
    }

    fn cost(&mut self, len: usize) -> f64 {
        let a_len = min(self.a_len, len);
        let b_len = len - a_len;
        self.a.cost(a_len) + self.b.cost(b_len)
    }

    fn split_at(self, index: usize) -> (Self, Self) {
        if index <= self.a_len {
            let a_rem = self.a_len - index;
            let (a_left, a_right) = self.a.split_at(index);
            let (b_left, b_right) = self.b.split_at(0);
            (ChainProducer::new(index, a_left, b_left), ChainProducer::new(a_rem, a_right, b_right))
        } else {
            let (a_left, a_right) = self.a.split_at(self.a_len);
            let (b_left, b_right) = self.b.split_at(index - self.a_len);
            (ChainProducer::new(self.a_len, a_left, b_left),
             ChainProducer::new(0, a_right, b_right))
        }
    }

    fn fold_with<F>(self, mut folder: F) -> F
        where F: Folder<A::Item>,
    {
        folder = self.a.fold_with(folder);
        if folder.full() {
            folder
        } else {
            self.b.fold_with(folder)
        }
    }
}

/// ////////////////////////////////////////////////////////////////////////
/// Wrapper for Chain to implement ExactSizeIterator

pub struct Chain<A, B> {
    chain: iter::Chain<A, B>,
}

impl<A, B> Chain<A, B> {
    fn new(a: A, b: B) -> Chain<A, B>
        where A: ExactSizeIterator,
              B: ExactSizeIterator<Item=A::Item>
    {
        Chain {
            chain: a.chain(b),
        }
    }
}

impl<A, B> Iterator for Chain<A, B> // parameterized over the iterator types
    where A: Iterator,
          B: Iterator<Item=A::Item>
{
    type Item = A::Item;

    fn next(&mut self) -> Option<Self::Item> {
        self.chain.next()
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        self.chain.size_hint()
    }
}

impl<A, B> ExactSizeIterator for Chain<A, B>
    where A: ExactSizeIterator,
          B: ExactSizeIterator<Item=A::Item>
{
}

impl<A, B> DoubleEndedIterator for Chain<A, B>
    where A: DoubleEndedIterator,
          B: DoubleEndedIterator<Item=A::Item>
{
    fn next_back(&mut self) -> Option<Self::Item> {
        self.chain.next_back()
    }
}
<|endoftext|>


<commit_before>//! Render to a window created by Glutin, using Glium's OpenGL functions

use ppu::{SCREEN_WIDTH, SCREEN_HEIGHT};

use glium::{DisplayBuild, Surface};
use glium::backend::glutin_backend::GlutinFacade;
use glium::index::{NoIndices, PrimitiveType};
use glium::glutin::WindowBuilder;
use glium::program::Program;
use glium::uniforms;
use glium::vertex::VertexBuffer;

use std::process;

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
}

impl Vertex {
    fn new(x: f32, y: f32) -> Self { Vertex { position: [x, y] } }
}

implement_vertex!(Vertex, position);

const VERTEX_SHADER_SRC: &'static str = r#"
    #version 140

    in vec2 position;

    void main() {
        gl_Position = vec4(position, 0.0, 1.0);
    }
"#;

const FRAGMENT_SHADER_SRC: &'static str = r#"
    #version 140

    out vec4 color;

    void main() {
        color = vec4(1.0, 0.0, 0.0, 1.0);
    }
"#;

pub struct GliumRenderer {
    display: GlutinFacade,
    vbuf: VertexBuffer<Vertex>,
    indices: NoIndices,
    program: Program,
}

impl Default for GliumRenderer {
    fn default() -> Self {
        let display = WindowBuilder::new()
            .with_dimensions(SCREEN_WIDTH as u32 * 3, SCREEN_HEIGHT as u32 * 3)
            .with_title("sneeze".to_owned())
            .build_glium().unwrap();
        let shape = [
            Vertex::new(-1.0, 1.0),
            Vertex::new(1.0, 1.0),
            Vertex::new(-1.0, -1.0),
            Vertex::new(1.0, -1.0),
        ];
        let program = Program::from_source(
            &display,
            VERTEX_SHADER_SRC,
            FRAGMENT_SHADER_SRC,
            None).unwrap();

        GliumRenderer {
            vbuf: VertexBuffer::new(&display, &shape).unwrap(),
            indices: NoIndices(PrimitiveType::TriangleStrip),
            display: display,
            program: program,
        }
    }
}

impl GliumRenderer {
    fn handle_events(&mut self) {
        use glium::glutin::Event::*;

        for ev in self.display.poll_events() {
            match ev {
                Closed => {
                    info!("quit event -> exiting");
                    process::exit(0);
                }
                _ => ()
            }
        }
    }
}

impl super::Renderer for GliumRenderer {
    fn render(&mut self, frame_data: &[u8]) {
        let mut target = self.display.draw();
        target.draw(&self.vbuf, &self.indices, &self.program, &uniforms::EmptyUniforms,
            &Default::default()).unwrap();
        target.finish().unwrap();

        self.handle_events();
    }
}
<commit_msg>Glium blurp<commit_after>//! Render to a window created by Glutin, using Glium's OpenGL functions

use ppu::{SCREEN_WIDTH, SCREEN_HEIGHT};

use glium::{DisplayBuild, Surface};
use glium::backend::glutin_backend::GlutinFacade;
use glium::index::{NoIndices, PrimitiveType};
use glium::glutin::WindowBuilder;
use glium::program::Program;
use glium::uniforms;
use glium::vertex::VertexBuffer;

use std::process;

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 2],
}

impl Vertex {
    fn new(x: f32, y: f32) -> Self { Vertex { position: [x, y] } }
}

implement_vertex!(Vertex, position);

const VERTEX_SHADER_SRC: &'static str = r#"
    #version 140

    in vec2 position;

    void main() {
        gl_Position = vec4(position, 0.0, 1.0);
    }
"#;

const FRAGMENT_SHADER_SRC: &'static str = r#"
    #version 140

    out vec4 color;

    void main() {
        color = vec4(1.0, 0.0, 0.0, 1.0);
    }
"#;

pub struct GliumRenderer {
    display: GlutinFacade,
    vbuf: VertexBuffer<Vertex>,
    program: Program,
}

impl Default for GliumRenderer {
    fn default() -> Self {
        let display = WindowBuilder::new()
            .with_dimensions(SCREEN_WIDTH as u32 * 3, SCREEN_HEIGHT as u32 * 3)
            .with_title("sneeze".to_owned())
            .build_glium().unwrap();
        let shape = [
            Vertex::new(-1.0, 1.0),
            Vertex::new(1.0, 1.0),
            Vertex::new(-1.0, -1.0),
            Vertex::new(1.0, -1.0),
        ];

        GliumRenderer {
            vbuf: VertexBuffer::new(&display, &shape).unwrap(),
            program: Program::from_source(&display, VERTEX_SHADER_SRC, FRAGMENT_SHADER_SRC, None)
                .unwrap(),
            display: display,
        }
    }
}

impl GliumRenderer {
    fn handle_events(&mut self) {
        use glium::glutin::Event::*;

        for ev in self.display.poll_events() {
            match ev {
                Closed => {
                    info!("quit event -> exiting");
                    process::exit(0);
                }
                _ => ()
            }
        }
    }
}

impl super::Renderer for GliumRenderer {
    fn render(&mut self, frame_data: &[u8]) {
        let mut target = self.display.draw();
        target.draw(
            &self.vbuf,
            &NoIndices(PrimitiveType::TriangleStrip),
            &self.program,
            &uniforms::EmptyUniforms,
            &Default::default()).unwrap();
        target.finish().unwrap();

        self.handle_events();
    }
}
<|endoftext|>


<commit_before>use super::TokenStreamExt;

use std::borrow::Cow;

use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};

/// Types that can be interpolated inside a [`quote!`] invocation.
///
/// [`quote!`]: macro.quote.html
pub trait ToTokens {
    /// Write `self` to the given `TokenStream`.
    ///
    /// The token append methods provided by the [`TokenStreamExt`] extension
    /// trait may be useful for implementing `ToTokens`.
    ///
    /// [`TokenStreamExt`]: trait.TokenStreamExt.html
    ///
    /// # Example
    ///
    /// Example implementation for a struct representing Rust paths like
    /// `std::cmp::PartialEq`:
    ///
    /// ```
    /// extern crate quote;
    /// use quote::{TokenStreamExt, ToTokens};
    ///
    /// extern crate proc_macro2;
    /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream};
    ///
    /// pub struct Path {
    ///     pub global: bool,
    ///     pub segments: Vec<PathSegment>,
    /// }
    ///
    /// impl ToTokens for Path {
    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
    ///         for (i, segment) in self.segments.iter().enumerate() {
    ///             if i > 0 || self.global {
    ///                 // Double colon `::`
    ///                 tokens.append(Punct::new(':', Spacing::Joint));
    ///                 tokens.append(Punct::new(':', Spacing::Alone));
    ///             }
    ///             segment.to_tokens(tokens);
    ///         }
    ///     }
    /// }
    /// #
    /// # pub struct PathSegment;
    /// #
    /// # impl ToTokens for PathSegment {
    /// #     fn to_tokens(&self, tokens: &mut TokenStream) {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// # fn main() {}
    /// ```
    fn to_tokens(&self, tokens: &mut TokenStream);

    /// Convert `self` directly into a `TokenStream` object.
    ///
    /// This method is implicitly implemented using `to_tokens`, and acts as a
    /// convenience method for consumers of the `ToTokens` trait.
    fn into_token_stream(self) -> TokenStream
    where
        Self: Sized,
    {
        let mut tokens = TokenStream::new();
        self.to_tokens(&mut tokens);
        tokens
    }
}

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

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

impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        (**self).to_tokens(tokens);
    }
}

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

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

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Literal::string(self));
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.as_str().to_tokens(tokens);
    }
}

macro_rules! primitive {
    ($($t:ident => $name:ident)*) => ($(
        impl ToTokens for $t {
            fn to_tokens(&self, tokens: &mut TokenStream) {
                tokens.append(Literal::$name(*self));
            }
        }
    )*)
}

primitive! {
    i8 => i8_suffixed
    i16 => i16_suffixed
    i32 => i32_suffixed
    i64 => i64_suffixed
    isize => isize_suffixed

    u8 => u8_suffixed
    u16 => u16_suffixed
    u32 => u32_suffixed
    u64 => u64_suffixed
    usize => usize_suffixed

    f32 => f32_suffixed
    f64 => f64_suffixed
}

impl ToTokens for char {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Literal::character(*self));
    }
}

impl ToTokens for bool {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let word = if *self { "true" } else { "false" };
        tokens.append(Ident::new(word, Span::call_site()));
    }
}

impl ToTokens for Group {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Ident {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Punct {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Literal {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for TokenTree {
    fn to_tokens(&self, dst: &mut TokenStream) {
        dst.append(self.clone());
    }
}

impl ToTokens for TokenStream {
    fn to_tokens(&self, dst: &mut TokenStream) {
        dst.append_all(self.clone().into_iter());
    }

    fn into_token_stream(self) -> TokenStream {
        self
    }
}
<commit_msg>Optimize impl ToTokens for TokenStream<commit_after>use super::TokenStreamExt;

use std::borrow::Cow;
use std::iter;

use proc_macro2::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};

/// Types that can be interpolated inside a [`quote!`] invocation.
///
/// [`quote!`]: macro.quote.html
pub trait ToTokens {
    /// Write `self` to the given `TokenStream`.
    ///
    /// The token append methods provided by the [`TokenStreamExt`] extension
    /// trait may be useful for implementing `ToTokens`.
    ///
    /// [`TokenStreamExt`]: trait.TokenStreamExt.html
    ///
    /// # Example
    ///
    /// Example implementation for a struct representing Rust paths like
    /// `std::cmp::PartialEq`:
    ///
    /// ```
    /// extern crate quote;
    /// use quote::{TokenStreamExt, ToTokens};
    ///
    /// extern crate proc_macro2;
    /// use proc_macro2::{TokenTree, Spacing, Span, Punct, TokenStream};
    ///
    /// pub struct Path {
    ///     pub global: bool,
    ///     pub segments: Vec<PathSegment>,
    /// }
    ///
    /// impl ToTokens for Path {
    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
    ///         for (i, segment) in self.segments.iter().enumerate() {
    ///             if i > 0 || self.global {
    ///                 // Double colon `::`
    ///                 tokens.append(Punct::new(':', Spacing::Joint));
    ///                 tokens.append(Punct::new(':', Spacing::Alone));
    ///             }
    ///             segment.to_tokens(tokens);
    ///         }
    ///     }
    /// }
    /// #
    /// # pub struct PathSegment;
    /// #
    /// # impl ToTokens for PathSegment {
    /// #     fn to_tokens(&self, tokens: &mut TokenStream) {
    /// #         unimplemented!()
    /// #     }
    /// # }
    /// #
    /// # fn main() {}
    /// ```
    fn to_tokens(&self, tokens: &mut TokenStream);

    /// Convert `self` directly into a `TokenStream` object.
    ///
    /// This method is implicitly implemented using `to_tokens`, and acts as a
    /// convenience method for consumers of the `ToTokens` trait.
    fn into_token_stream(self) -> TokenStream
    where
        Self: Sized,
    {
        let mut tokens = TokenStream::new();
        self.to_tokens(&mut tokens);
        tokens
    }
}

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

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

impl<'a, T: ?Sized + ToOwned + ToTokens> ToTokens for Cow<'a, T> {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        (**self).to_tokens(tokens);
    }
}

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

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

impl ToTokens for str {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Literal::string(self));
    }
}

impl ToTokens for String {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        self.as_str().to_tokens(tokens);
    }
}

macro_rules! primitive {
    ($($t:ident => $name:ident)*) => ($(
        impl ToTokens for $t {
            fn to_tokens(&self, tokens: &mut TokenStream) {
                tokens.append(Literal::$name(*self));
            }
        }
    )*)
}

primitive! {
    i8 => i8_suffixed
    i16 => i16_suffixed
    i32 => i32_suffixed
    i64 => i64_suffixed
    isize => isize_suffixed

    u8 => u8_suffixed
    u16 => u16_suffixed
    u32 => u32_suffixed
    u64 => u64_suffixed
    usize => usize_suffixed

    f32 => f32_suffixed
    f64 => f64_suffixed
}

impl ToTokens for char {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(Literal::character(*self));
    }
}

impl ToTokens for bool {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        let word = if *self { "true" } else { "false" };
        tokens.append(Ident::new(word, Span::call_site()));
    }
}

impl ToTokens for Group {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Ident {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Punct {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for Literal {
    fn to_tokens(&self, tokens: &mut TokenStream) {
        tokens.append(self.clone());
    }
}

impl ToTokens for TokenTree {
    fn to_tokens(&self, dst: &mut TokenStream) {
        dst.append(self.clone());
    }
}

impl ToTokens for TokenStream {
    fn to_tokens(&self, dst: &mut TokenStream) {
        dst.extend(iter::once(self.clone()));
    }

    fn into_token_stream(self) -> TokenStream {
        self
    }
}
<|endoftext|>