<commit_before>// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.

extern crate glib;
use glib::prelude::*;

extern crate gstreamer as gst;
extern crate gstreamer_check as gst_check;

use std::thread;

extern crate gstthreadshare;

fn init() {
    use std::sync::{Once, ONCE_INIT};
    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| {
        gst::init().unwrap();
        gstthreadshare::plugin_register_static();
    });
}

#[test]
fn test_push() {
    init();

    let mut h = gst_check::Harness::new("ts-udpsrc");

    let caps = gst::Caps::new_simple("foo/bar", &[]);
    {
        let udpsrc = h.get_element().unwrap();
        udpsrc.set_property("caps", &caps).unwrap();
        udpsrc.set_property("port", &(5000 as u32)).unwrap();
        udpsrc.set_property("context", &"test-push").unwrap();
    }

    h.play();

    thread::spawn(move || {
        use std::net;
        use std::net::{IpAddr, Ipv4Addr, SocketAddr};
        use std::time;

        // Sleep 50ms to allow for the udpsrc to be ready to actually receive data
        thread::sleep(time::Duration::from_millis(50));

        let buffer = [0; 160];
        let socket = net::UdpSocket::bind("0.0.0.0:0").unwrap();

        let ipaddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
        let dest = SocketAddr::new(ipaddr, 5000 as u16);

        for _ in 0..3 {
            socket.send_to(&buffer, dest).unwrap();
        }
    });

    for _ in 0..3 {
        let buffer = h.pull().unwrap();
        assert_eq!(buffer.get_size(), 160);
    }

    let mut n_events = 0;
    loop {
        use gst::EventView;

        let event = h.pull_event().unwrap();
        match event.view() {
            EventView::StreamStart(..) => {
                assert_eq!(n_events, 0);
            }
            EventView::Caps(ev) => {
                assert_eq!(n_events, 1);
                let event_caps = ev.get_caps();
                assert_eq!(caps.as_ref(), event_caps);
            }
            EventView::Segment(..) => {
                assert_eq!(n_events, 2);
            }
            EventView::Eos(..) => {
                break;
            }
            _ => (),
        }
        n_events += 1;
    }
    assert!(n_events >= 3);
}
<commit_msg>ts-udpsrc: Add unit test for socket re-use and the socket/used-socket properties<commit_after>// Copyright (C) 2018 Sebastian Dröge <sebastian@centricular.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library 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
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
// Boston, MA 02110-1335, USA.

extern crate glib;
use glib::prelude::*;

extern crate gio;

extern crate gstreamer as gst;
extern crate gstreamer_check as gst_check;

use std::thread;

extern crate gstthreadshare;

fn init() {
    use std::sync::{Once, ONCE_INIT};
    static INIT: Once = ONCE_INIT;

    INIT.call_once(|| {
        gst::init().unwrap();
        gstthreadshare::plugin_register_static();
    });
}

#[test]
fn test_push() {
    init();

    let mut h = gst_check::Harness::new("ts-udpsrc");

    let caps = gst::Caps::new_simple("foo/bar", &[]);
    {
        let udpsrc = h.get_element().unwrap();
        udpsrc.set_property("caps", &caps).unwrap();
        udpsrc.set_property("port", &(5000 as u32)).unwrap();
        udpsrc.set_property("context", &"test-push").unwrap();
    }

    h.play();

    thread::spawn(move || {
        use std::net;
        use std::net::{IpAddr, Ipv4Addr, SocketAddr};
        use std::time;

        // Sleep 50ms to allow for the udpsrc to be ready to actually receive data
        thread::sleep(time::Duration::from_millis(50));

        let buffer = [0; 160];
        let socket = net::UdpSocket::bind("0.0.0.0:0").unwrap();

        let ipaddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
        let dest = SocketAddr::new(ipaddr, 5000 as u16);

        for _ in 0..3 {
            socket.send_to(&buffer, dest).unwrap();
        }
    });

    for _ in 0..3 {
        let buffer = h.pull().unwrap();
        assert_eq!(buffer.get_size(), 160);
    }

    let mut n_events = 0;
    loop {
        use gst::EventView;

        let event = h.pull_event().unwrap();
        match event.view() {
            EventView::StreamStart(..) => {
                assert_eq!(n_events, 0);
            }
            EventView::Caps(ev) => {
                assert_eq!(n_events, 1);
                let event_caps = ev.get_caps();
                assert_eq!(caps.as_ref(), event_caps);
            }
            EventView::Segment(..) => {
                assert_eq!(n_events, 2);
                break;
            }
            _ => (),
        }
        n_events += 1;
    }
    assert!(n_events >= 2);
}

#[test]
fn test_socket_reuse() {
    init();

    let mut ts_src_h = gst_check::Harness::new("ts-udpsrc");
    let mut sink_h = gst_check::Harness::new("udpsink");
    let mut ts_src_h2 = gst_check::Harness::new("ts-udpsrc");

    {
        let udpsrc = ts_src_h.get_element().unwrap();
        udpsrc.set_property("port", &(6000 as u32)).unwrap();
        udpsrc
            .set_property("context", &"test-socket-reuse")
            .unwrap();
    }
    ts_src_h.play();

    {
        let udpsrc = ts_src_h.get_element().unwrap();
        let socket = udpsrc
            .get_property("used-socket")
            .unwrap()
            .get::<gio::Socket>()
            .unwrap();

        let udpsink = sink_h.get_element().unwrap();
        udpsink.set_property("socket", &socket).unwrap();
        udpsink.set_property("host", &"127.0.0.1").unwrap();
        udpsink.set_property("port", &6001i32).unwrap();
    }
    sink_h.play();

    {
        let udpsrc = ts_src_h2.get_element().unwrap();
        udpsrc.set_property("port", &(6001 as u32)).unwrap();
        udpsrc
            .set_property("context", &"test-socket-reuse")
            .unwrap();
    }
    ts_src_h2.play();

    thread::spawn(move || {
        use std::net;
        use std::net::{IpAddr, Ipv4Addr, SocketAddr};
        use std::time;

        // Sleep 50ms to allow for the udpsrc to be ready to actually receive data
        thread::sleep(time::Duration::from_millis(50));

        let buffer = [0; 160];
        let socket = net::UdpSocket::bind("0.0.0.0:0").unwrap();

        let ipaddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
        let dest = SocketAddr::new(ipaddr, 6000 as u16);

        for _ in 0..3 {
            socket.send_to(&buffer, dest).unwrap();
        }
    });

    for _ in 0..3 {
        let buffer = ts_src_h.pull().unwrap();
        sink_h.push(buffer).into_result().unwrap();
        let buffer = ts_src_h2.pull().unwrap();

        assert_eq!(buffer.get_size(), 160);
    }
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

//! `sysinfo` is a crate used to get a system's information.
//!
//! Before any attempt to read the different structs' information, you need to update them to
//! get up-to-date information.
//!
//! # Examples
//!
//! ```
//! use sysinfo::{ProcessExt, SystemExt};
//!
//! let mut system = sysinfo::System::new_all();
//!
//! // First we update all information of our system struct.
//! system.refresh_all();
//!
//! // Now let's print every process' id and name:
//! for (pid, proc_) in system.get_processes() {
//!     println!("{}:{} => status: {:?}", pid, proc_.name(), proc_.status());
//! }
//!
//! // Then let's print the temperature of the different components:
//! for component in system.get_components() {
//!     println!("{:?}", component);
//! }
//!
//! // And then all disks' information:
//! for disk in system.get_disks() {
//!     println!("{:?}", disk);
//! }
//!
//! // And finally the RAM and SWAP information:
//! println!("total memory: {} KB", system.get_total_memory());
//! println!("used memory : {} KB", system.get_used_memory());
//! println!("total swap  : {} KB", system.get_total_swap());
//! println!("used swap   : {} KB", system.get_used_swap());
//!
//! // Display system information:
//! println!("System name:             {:?}", system.get_name());
//! println!("System kernel version:   {:?}", system.get_kernel_version());
//! println!("System OS version:       {:?}", system.get_os_version());
//! println!("System host name:        {:?}", system.get_host_name());
//! ```

#![crate_name = "sysinfo"]
#![crate_type = "lib"]
#![crate_type = "rlib"]
#![allow(unknown_lints)]
#![deny(missing_docs)]
#![deny(broken_intra_doc_links)]
#![allow(clippy::upper_case_acronyms)]
#![allow(renamed_and_removed_lints)]

#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[cfg(feature = "debug")]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{
        eprintln!($($x)*);
    }}
}

#[cfg(not(feature = "debug"))]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{}};
}

cfg_if::cfg_if! {
    if #[cfg(any(target_os = "macos", target_os = "ios"))] {
        mod apple;
        use apple as sys;
        extern crate core_foundation_sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(windows)] {
        mod windows;
        use windows as sys;
        extern crate winapi;
        extern crate ntapi;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(any(target_os = "linux", target_os = "android"))] {
        mod linux;
        use linux as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else {
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 0;
    }
}

pub use common::{
    AsU32, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Disk, NetworkData, Networks, Process, ProcessStatus, Processor, System};
pub use traits::{
    ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt,
};

#[cfg(feature = "c-interface")]
pub use c_interface::*;
pub use utils::get_current_pid;

#[cfg(feature = "c-interface")]
mod c_interface;
mod common;
mod debug;
mod system;
mod traits;
mod utils;

/// This function is only used on linux targets, on the other platforms it does nothing and returns
/// `false`.
///
/// On linux, to improve performance, we keep a `/proc` file open for each process we index with
/// a maximum number of files open equivalent to half of the system limit.
///
/// The problem is that some users might need all the available file descriptors so we need to
/// allow them to change this limit.
///
/// Note that if you set a limit bigger than the system limit, the system limit will be set.
///
/// Returns `true` if the new value has been set.
///
/// ```no_run
/// use sysinfo::{System, SystemExt, set_open_files_limit};
///
/// // We call the function before any call to the processes update.
/// if !set_open_files_limit(10) {
///     // It'll always return false on non-linux targets.
///     eprintln!("failed to update the open files limit...");
/// }
/// let s = System::new_all();
/// ```
pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
    #[cfg(any(target_os = "linux", target_os = "android"))]
    {
        if _new_limit < 0 {
            _new_limit = 0;
        }
        let max = sys::system::get_max_nb_fds();
        if _new_limit > max {
            _new_limit = max;
        }
        if let Ok(ref mut x) = unsafe { sys::system::REMAINING_FILES.lock() } {
            // If files are already open, to be sure that the number won't be bigger when those
            // files are closed, we subtract the current number of opened files to the new limit.
            let diff = max - **x;
            **x = _new_limit - diff;
            true
        } else {
            false
        }
    }
    #[cfg(all(not(target_os = "linux"), not(target_os = "android")))]
    {
        false
    }
}

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

    #[test]
    fn check_memory_usage() {
        let mut s = System::new();

        s.refresh_all();
        // We don't want to test on unsupported systems.
        if MIN_USERS > 0 {
            assert_eq!(
                s.get_processes()
                    .iter()
                    .all(|(_, proc_)| proc_.memory() == 0),
                false
            );
        }
    }

    #[cfg(target_os = "linux")]
    #[test]
    fn check_cpu_usage() {
        let mut s = System::new();

        s.refresh_all();
        // All CPU usage will start at zero until the second refresh
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() == 0.0),
            true
        );

        // Wait a bit to update CPU usage values
        std::thread::sleep(std::time::Duration::from_millis(100));
        s.refresh_all();
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
                    && proc_.cpu_usage() <= (s.get_processors().len() as f32) * 100.0),
            true
        );
    }

    #[test]
    fn check_users() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        assert!(s.get_users().len() >= MIN_USERS);

        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_all();
        assert!(s.get_users().is_empty());

        let s = System::new_all();
        assert!(s.get_users().len() >= MIN_USERS);
    }

    #[test]
    fn check_uid_gid() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        let users = s.get_users();
        assert!(users.len() >= MIN_USERS);

        for user in users {
            match user.get_name() {
                "root" => {
                    assert_eq!(*user.get_uid(), 0);
                    assert_eq!(*user.get_gid(), 0);
                }
                _ => {
                    assert!(*user.get_uid() > 0);
                    #[cfg(not(target_os = "windows"))]
                    assert!(*user.get_gid() > 0);
                }
            }
        }
    }

    #[test]
    fn check_system_info() {
        // We don't want to test on unsupported systems.
        if MIN_USERS > 0 {
            let s = System::new();
            assert!(!s.get_name().expect("Failed to get system name").is_empty());

            assert!(!s
                .get_kernel_version()
                .expect("Failed to get kernel version")
                .is_empty());

            assert!(!s
                .get_os_version()
                .expect("Failed to get os version")
                .is_empty());

            assert!(!s
                .get_long_os_version()
                .expect("Failed to get long OS version")
                .is_empty());
        }
    }

    #[test]
    fn check_host_name() {
        // We don't want to test on unsupported systems.
        if MIN_USERS > 0 {
            let s = System::new();
            assert!(!s
                .get_host_name()
                .expect("Failed to get host name")
                .is_empty());
        }
    }

    #[test]
    fn check_refresh_process_return_value() {
        // We don't want to test on unsupported systems.
        if MIN_USERS > 0 {
            let pid = get_current_pid().expect("Failed to get current PID");
            let mut s = System::new();

            // First check what happens in case the process isn't already in our process list.
            assert!(s.refresh_process(pid));
            // Then check that it still returns true if the process is already in our process list.
            assert!(s.refresh_process(pid));
        }
    }
}

// Used to check that System is Send and Sync.
#[cfg(doctest)]
doc_comment::doc_comment!(
    "
```
fn is_send<T: Send>() {}
is_send::<sysinfo::System>();
```

```
fn is_sync<T: Sync>() {}
is_sync::<sysinfo::System>();
```"
);
<commit_msg>Make it more clear how to use use the different information<commit_after>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

//! `sysinfo` is a crate used to get a system's information.
//!
//! /!\ Before any attempt to read the different structs' information, you need to update them to
//! get up-to-date information because for most of them, it works on diff between the current value
//! and the old one.
//!
//! Which is why, it's much better to keep the same instance of [`System`] around instead of
//! recreating it multiple times.
//!
//! # Examples
//!
//! ```
//! use sysinfo::{ProcessExt, SystemExt};
//!
//! let mut system = sysinfo::System::new_all();
//!
//! // First we update all information of our system struct.
//! system.refresh_all();
//!
//! // Now let's print every process' id and name:
//! for (pid, proc_) in system.get_processes() {
//!     println!("{}:{} => status: {:?}", pid, proc_.name(), proc_.status());
//! }
//!
//! // Then let's print the temperature of the different components:
//! for component in system.get_components() {
//!     println!("{:?}", component);
//! }
//!
//! // And then all disks' information:
//! for disk in system.get_disks() {
//!     println!("{:?}", disk);
//! }
//!
//! // And finally the RAM and SWAP information:
//! println!("total memory: {} KB", system.get_total_memory());
//! println!("used memory : {} KB", system.get_used_memory());
//! println!("total swap  : {} KB", system.get_total_swap());
//! println!("used swap   : {} KB", system.get_used_swap());
//!
//! // Display system information:
//! println!("System name:             {:?}", system.get_name());
//! println!("System kernel version:   {:?}", system.get_kernel_version());
//! println!("System OS version:       {:?}", system.get_os_version());
//! println!("System host name:        {:?}", system.get_host_name());
//! ```

#![crate_name = "sysinfo"]
#![crate_type = "lib"]
#![crate_type = "rlib"]
#![allow(unknown_lints)]
#![deny(missing_docs)]
#![deny(broken_intra_doc_links)]
#![allow(clippy::upper_case_acronyms)]
#![allow(renamed_and_removed_lints)]

#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[cfg(feature = "debug")]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{
        eprintln!($($x)*);
    }}
}

#[cfg(not(feature = "debug"))]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{}};
}

cfg_if::cfg_if! {
    if #[cfg(any(target_os = "macos", target_os = "ios"))] {
        mod apple;
        use apple as sys;
        extern crate core_foundation_sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(windows)] {
        mod windows;
        use windows as sys;
        extern crate winapi;
        extern crate ntapi;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(any(target_os = "linux", target_os = "android"))] {
        mod linux;
        use linux as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else {
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 0;
    }
}

pub use common::{
    AsU32, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Disk, NetworkData, Networks, Process, ProcessStatus, Processor, System};
pub use traits::{
    ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt,
};

#[cfg(feature = "c-interface")]
pub use c_interface::*;
pub use utils::get_current_pid;

#[cfg(feature = "c-interface")]
mod c_interface;
mod common;
mod debug;
mod system;
mod traits;
mod utils;

/// This function is only used on linux targets, on the other platforms it does nothing and returns
/// `false`.
///
/// On linux, to improve performance, we keep a `/proc` file open for each process we index with
/// a maximum number of files open equivalent to half of the system limit.
///
/// The problem is that some users might need all the available file descriptors so we need to
/// allow them to change this limit.
///
/// Note that if you set a limit bigger than the system limit, the system limit will be set.
///
/// Returns `true` if the new value has been set.
///
/// ```no_run
/// use sysinfo::{System, SystemExt, set_open_files_limit};
///
/// // We call the function before any call to the processes update.
/// if !set_open_files_limit(10) {
///     // It'll always return false on non-linux targets.
///     eprintln!("failed to update the open files limit...");
/// }
/// let s = System::new_all();
/// ```
pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
    #[cfg(any(target_os = "linux", target_os = "android"))]
    {
        if _new_limit < 0 {
            _new_limit = 0;
        }
        let max = sys::system::get_max_nb_fds();
        if _new_limit > max {
            _new_limit = max;
        }
        if let Ok(ref mut x) = unsafe { sys::system::REMAINING_FILES.lock() } {
            // If files are already open, to be sure that the number won't be bigger when those
            // files are closed, we subtract the current number of opened files to the new limit.
            let diff = max - **x;
            **x = _new_limit - diff;
            true
        } else {
            false
        }
    }
    #[cfg(all(not(target_os = "linux"), not(target_os = "android")))]
    {
        false
    }
}

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

    #[test]
    fn check_memory_usage() {
        let mut s = System::new();

        s.refresh_all();
        // We don't want to test on unsupported systems.
        if MIN_USERS > 0 {
            assert_eq!(
                s.get_processes()
                    .iter()
                    .all(|(_, proc_)| proc_.memory() == 0),
                false
            );
        }
    }

    #[cfg(target_os = "linux")]
    #[test]
    fn check_cpu_usage() {
        let mut s = System::new();

        s.refresh_all();
        // All CPU usage will start at zero until the second refresh
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() == 0.0),
            true
        );

        // Wait a bit to update CPU usage values
        std::thread::sleep(std::time::Duration::from_millis(100));
        s.refresh_all();
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
                    && proc_.cpu_usage() <= (s.get_processors().len() as f32) * 100.0),
            true
        );
    }

    #[test]
    fn check_users() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        assert!(s.get_users().len() >= MIN_USERS);

        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_all();
        assert!(s.get_users().is_empty());

        let s = System::new_all();
        assert!(s.get_users().len() >= MIN_USERS);
    }

    #[test]
    fn check_uid_gid() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        let users = s.get_users();
        assert!(users.len() >= MIN_USERS);

        for user in users {
            match user.get_name() {
                "root" => {
                    assert_eq!(*user.get_uid(), 0);
                    assert_eq!(*user.get_gid(), 0);
                }
                _ => {
                    assert!(*user.get_uid() > 0);
                    #[cfg(not(target_os = "windows"))]
                    assert!(*user.get_gid() > 0);
                }
            }
        }
    }

    #[test]
    fn check_system_info() {
        // We don't want to test on unsupported systems.
        if MIN_USERS > 0 {
            let s = System::new();
            assert!(!s.get_name().expect("Failed to get system name").is_empty());

            assert!(!s
                .get_kernel_version()
                .expect("Failed to get kernel version")
                .is_empty());

            assert!(!s
                .get_os_version()
                .expect("Failed to get os version")
                .is_empty());

            assert!(!s
                .get_long_os_version()
                .expect("Failed to get long OS version")
                .is_empty());
        }
    }

    #[test]
    fn check_host_name() {
        // We don't want to test on unsupported systems.
        if MIN_USERS > 0 {
            let s = System::new();
            assert!(!s
                .get_host_name()
                .expect("Failed to get host name")
                .is_empty());
        }
    }

    #[test]
    fn check_refresh_process_return_value() {
        // We don't want to test on unsupported systems.
        if MIN_USERS > 0 {
            let pid = get_current_pid().expect("Failed to get current PID");
            let mut s = System::new();

            // First check what happens in case the process isn't already in our process list.
            assert!(s.refresh_process(pid));
            // Then check that it still returns true if the process is already in our process list.
            assert!(s.refresh_process(pid));
        }
    }
}

// Used to check that System is Send and Sync.
#[cfg(doctest)]
doc_comment::doc_comment!(
    "
```
fn is_send<T: Send>() {}
is_send::<sysinfo::System>();
```

```
fn is_sync<T: Sync>() {}
is_sync::<sysinfo::System>();
```"
);
<|endoftext|>


<commit_before>//! A memory-safer wrapper around system dynamic library primitives.
//!
//! With this library you can load [dynamic libraries](struct.Library.html) and retrieve
//! [symbols](struct.Symbol.html) from the loaded libraries.
//!
//! Less safe platform specific bindings are available in the [`os::platform`](os/index.html)
//! modules.
use std::ffi::OsStr;
use std::marker;

#[cfg(unix)]
#[macro_use]
extern crate lazy_static;

#[cfg(unix)]
use self::os::unix as imp;
#[cfg(windows)]
use self::os::windows as imp;

pub mod os;
mod util;

pub type Result<T> = ::std::io::Result<T>;

/// A dynamically loaded library.
pub struct Library(imp::Library);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// // on Unix
    /// let lib = Library::new("libm.so.6").unwrap();
    /// // on OS X
    /// let lib = Library::new("libm.dylib").unwrap();
    /// // on Windows
    /// let lib = Library::new("msvcrt.dll").unwrap();
    /// ```
    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library> {
        imp::Library::new(filename).map(Library)
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    ///
    /// # Examples
    ///
    /// Simple function:
    ///
    /// ```ignore
    /// let sin: Symbol<extern fn(f64) -> f64> = unsafe {
    ///     lib.get(b"sin\0").unwrap()
    /// };
    /// ```
    ///
    /// A static or TLS variable:
    ///
    /// ```ignore
    /// let errno: Symbol<*mut u32> = unsafe {
    ///     lib.get(b"errno\0").unwrap()
    /// };
    /// ```
    pub unsafe fn get<'lib, T>(&'lib self, symbol: &[u8]) -> Result<Symbol<'lib, T>> {
        self.0.get(symbol).map(|from| {
            Symbol {
                inner: from,
                pd: marker::PhantomData
            }
        })
    }
}

/// Symbol from a library.
///
/// This type is a safeguard against using dynamically loaded symbols after a `Library` is
/// unloaded. Primary method to create an instance of a `Symbol` is via `Library::get`.
///
/// Due to implementation of the `Deref` trait, an instance of `Symbol` may be used as if it was a
/// function or variable directly, without taking care to “extract” function or variable manually
/// most of the time.
///
/// # Examples
///
/// ```ignore
/// let sin: Symbol<extern fn(f64) -> f64> = unsafe {
///     lib.get(b"sin\0").unwrap()
/// };
/// let sine0 = sin(0);
/// assert!(sine0 < 0.1E-10);
/// ```
pub struct Symbol<'lib, T: 'lib> {
    inner: imp::Symbol<T>,
    pd: marker::PhantomData<&'lib T>
}

impl<'lib, T> ::std::ops::Deref for Symbol<'lib, T> {
    type Target = T;
    fn deref(&self) -> &T {
        ::std::ops::Deref::deref(&self.inner)
    }
}

#[cfg(all(unix, not(any(target_os="macos", target_os="ios", target_os="android"))))]
#[test]
fn libm() {
    let lib = Library::new("libm.so.6").unwrap();
    let sin: Symbol<extern fn(f64) -> f64> = unsafe {
        lib.get(b"sin").unwrap()
    };
    assert!(sin(::std::f64::INFINITY).is_nan());
    let errno: Symbol<*mut u32> = unsafe {
        lib.get(b"errno").unwrap()
    };
    assert!(unsafe { **errno } != 0);
    unsafe { **errno = 0; }
}
<commit_msg>Add Debug impl for Library and Symbol<commit_after>//! A memory-safer wrapper around system dynamic library primitives.
//!
//! With this library you can load [dynamic libraries](struct.Library.html) and retrieve
//! [symbols](struct.Symbol.html) from the loaded libraries.
//!
//! Less safe platform specific bindings are available in the [`os::platform`](os/index.html)
//! modules.
use std::ffi::OsStr;
use std::fmt;
use std::marker;

#[cfg(unix)]
#[macro_use]
extern crate lazy_static;

#[cfg(unix)]
use self::os::unix as imp;
#[cfg(windows)]
use self::os::windows as imp;

pub mod os;
mod util;

pub type Result<T> = ::std::io::Result<T>;

/// A dynamically loaded library.
pub struct Library(imp::Library);

impl Library {
    /// Find and load a shared library (module).
    ///
    /// Locations where library is searched for is platform specific and can’t be adjusted
    /// portably.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// // on Unix
    /// let lib = Library::new("libm.so.6").unwrap();
    /// // on OS X
    /// let lib = Library::new("libm.dylib").unwrap();
    /// // on Windows
    /// let lib = Library::new("msvcrt.dll").unwrap();
    /// ```
    pub fn new<P: AsRef<OsStr>>(filename: P) -> Result<Library> {
        imp::Library::new(filename).map(Library)
    }

    /// Get a symbol by name.
    ///
    /// Mangling or symbol rustification is not done: trying to `get` something like `x::y`
    /// will not work.
    ///
    /// You may append a null byte at the end of the byte string to avoid string allocation in some
    /// cases. E.g. for symbol `sin` you may write `b"sin\0"` instead of `b"sin"`.
    ///
    /// # Unsafety
    ///
    /// Symbol of arbitrary requested type is returned. Using a symbol with wrong type is not
    /// memory safe.
    ///
    /// # Examples
    ///
    /// Simple function:
    ///
    /// ```ignore
    /// let sin: Symbol<extern fn(f64) -> f64> = unsafe {
    ///     lib.get(b"sin\0").unwrap()
    /// };
    /// ```
    ///
    /// A static or TLS variable:
    ///
    /// ```ignore
    /// let errno: Symbol<*mut u32> = unsafe {
    ///     lib.get(b"errno\0").unwrap()
    /// };
    /// ```
    pub unsafe fn get<'lib, T>(&'lib self, symbol: &[u8]) -> Result<Symbol<'lib, T>> {
        self.0.get(symbol).map(|from| {
            Symbol {
                inner: from,
                pd: marker::PhantomData
            }
        })
    }
}

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

/// Symbol from a library.
///
/// This type is a safeguard against using dynamically loaded symbols after a `Library` is
/// unloaded. Primary method to create an instance of a `Symbol` is via `Library::get`.
///
/// Due to implementation of the `Deref` trait, an instance of `Symbol` may be used as if it was a
/// function or variable directly, without taking care to “extract” function or variable manually
/// most of the time.
///
/// # Examples
///
/// ```ignore
/// let sin: Symbol<extern fn(f64) -> f64> = unsafe {
///     lib.get(b"sin\0").unwrap()
/// };
/// let sine0 = sin(0);
/// assert!(sine0 < 0.1E-10);
/// ```
pub struct Symbol<'lib, T: 'lib> {
    inner: imp::Symbol<T>,
    pd: marker::PhantomData<&'lib T>
}

impl<'lib, T> ::std::ops::Deref for Symbol<'lib, T> {
    type Target = T;
    fn deref(&self) -> &T {
        ::std::ops::Deref::deref(&self.inner)
    }
}

impl<'lib, T> fmt::Debug for Symbol<'lib, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.inner.fmt(f)
    }
}

#[cfg(all(unix, not(any(target_os="macos", target_os="ios", target_os="android"))))]
#[test]
fn libm() {
    let lib = Library::new("libm.so.6").unwrap();
    let sin: Symbol<extern fn(f64) -> f64> = unsafe {
        lib.get(b"sin").unwrap()
    };
    assert!(sin(::std::f64::INFINITY).is_nan());
    let errno: Symbol<*mut u32> = unsafe {
        lib.get(b"errno").unwrap()
    };
    assert!(unsafe { **errno } != 0);
    unsafe { **errno = 0; }
}
<|endoftext|>


<commit_before>//! Structured application logging.
//!
//! This module provides:
//!
//!  * The `emit!()` family of macros, for recording application events in an easily machine-readable format
//!  * Collectors for transmitting these events to back-end logging servers
//!
//! The widely-used `log` crate doesn't preserve the structure of the events that are written through it. For example:
//!
//! ```ignore
//! info!("Hello, {}!", env::var("USERNAME").unwrap());
//! ```
//!
//! This writes `"Hello, nblumhardt!"` to the log as an block of text, that can't be broken apart to reveal the username except
//! with regular expressions.
//!
//! The arguments passed to `emit` are named:
//!
//! ```ignore
//! eminfo!("Hello, {}!", user: env::var("USERNAME").unwrap());
//! ```
//!
//! This event can be rendered into text identically to the `log` example, but structured data collectors also capture the
//! aguments as a key/value property pairs.
//!
//! ```js
//! {
//!   "timestamp": "2016-03-17T00:17:01Z",
//!   "messageTemplate": "Hello, {name}!",
//!   "properties": {
//!     "name": "nblumhardt",
//!     "target": "example_app"
//!   }
//! }
//! ```
//!
//! Back-ends like Elasticsearch, Seq, and Splunk use these in queries like `user == "nblumhardt"` without up-front log parsing.
//!
//! Arguments are captured using `serde`, so there's the potential for complex values to be logged so long as they're `serde::ser::Serialize`.
//!
//! Further, because the template (format) itself is captured, it can be hashed to compute an "event type" for precisely finding
//! all occurrences of the event regardless of the value of the `user` argument.
//!
//! # Examples
//!
//! The example below writes events to stdout.
//!
//! ```
//! #[macro_use]
//! extern crate emit;
//! # extern crate log;
//!
//! use std::env;
//! use emit::pipeline;
//! use emit::collectors::stdio;
//!
//! fn main() {
//!     let _flush = pipeline::init(stdio::StdioCollector::new(), emit::LogLevel::Info);
//!
//!     eminfo!("Hello, {}!", name: env::var("USERNAME").unwrap());
//! }
//! ```
//!
//! Output:
//!
//! ```text
//! emit 2016-03-24T05:03:36Z Hello, {name}!
//!   name: "nblumhardt"
//!   target: "example_app"
//!
//! ```

extern crate serde;
extern crate serde_json;
extern crate chrono;

#[macro_use]
extern crate hyper;

#[macro_use]
extern crate log;

pub mod message_templates;
pub mod events;
pub mod pipeline;
pub mod collectors;

/// Re-exports log::LogLevel so that users can initialize the emit
/// crate without extra imports.
pub use log::LogLevel;

#[macro_export]
#[doc(hidden)]
macro_rules! __emit_get_event_data {
    ($target:expr, $s:expr, $( $n:ident: $v:expr ),* ) => {{
        #[allow(unused_imports)]
        use std::fmt::Write;
        use std::collections;

        // Underscores avoid the unused_mut warning
        let mut _names: Vec<&str> = vec![];
        let mut properties: collections::BTreeMap<&'static str, String> = collections::BTreeMap::new();

        $(
            _names.push(stringify!($n));
            properties.insert(stringify!($n), $crate::message_templates::capture(&$v));
        )*

        properties.insert("target", $crate::message_templates::capture(&$target));

        let template = $crate::message_templates::build_template($s, &_names);

        (template, properties)
    }};
}

#[macro_export]
macro_rules! emit {
    (target: $target:expr, $lvl:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        let lvl = $lvl;
        if $crate::pipeline::is_enabled(lvl) {
            let (template, properties) = __emit_get_event_data!($target, $s, $($n: $v),*);
            let event = $crate::events::Event::new_now(lvl, template, properties);
            $crate::pipeline::emit(event);
        }
    }};

    ($lvl:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        emit!(target: module_path!(), $lvl, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! emerror {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Error, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Error, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! emwarn {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Warn, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Warn, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! eminfo {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Info, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Info, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! emdebug {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Debug, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Debug, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! emtrace {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Trace, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Trace, $s, $($n: $v),*);
    }};
}

#[cfg(test)]
mod tests {
    // use collectors::stdio;
    use collectors::seq;
    use pipeline;
    use std::env;
    use log;

    #[test]
    fn unparameterized_templates_are_captured() {
        let (template, properties) = __emit_get_event_data!("t", "Starting...",);
        assert_eq!(template, "Starting...");
        assert_eq!(properties.len(), 1);
    }

    #[test]
    fn template_and_properties_are_captured() {
        let u = "nblumhardt";
        let q = 42;

        let (template, properties) = __emit_get_event_data!("t", "User {} exceeded quota of {}!", user: u, quota: q);
        assert_eq!(template, "User {user} exceeded quota of {quota}!");
        assert_eq!(properties.get("user"), Some(&"\"nblumhardt\"".to_owned()));
        assert_eq!(properties.get("quota"), Some(&"42".to_owned()));
        assert_eq!(properties.len(), 3);
    }

    #[test]
    fn emitted_events_are_flushed() {
        // let _flush = pipeline::init(stdio::StdioCollector::new(), log::LogLevel::Info);
        let _flush = pipeline::init(seq::SeqCollector::new_local(), log::LogLevel::Info);
        eminfo!("Hello, {}!", name: env::var("USERNAME").unwrap());
    }
}
<commit_msg>Removed some temporary testing changes<commit_after>//! Structured application logging.
//!
//! This module provides:
//!
//!  * The `emit!()` family of macros, for recording application events in an easily machine-readable format
//!  * Collectors for transmitting these events to back-end logging servers
//!
//! The widely-used `log` crate doesn't preserve the structure of the events that are written through it. For example:
//!
//! ```ignore
//! info!("Hello, {}!", env::var("USERNAME").unwrap());
//! ```
//!
//! This writes `"Hello, nblumhardt!"` to the log as an block of text, that can't be broken apart to reveal the username except
//! with regular expressions.
//!
//! The arguments passed to `emit` are named:
//!
//! ```ignore
//! eminfo!("Hello, {}!", user: env::var("USERNAME").unwrap());
//! ```
//!
//! This event can be rendered into text identically to the `log` example, but structured data collectors also capture the
//! aguments as a key/value property pairs.
//!
//! ```js
//! {
//!   "timestamp": "2016-03-17T00:17:01Z",
//!   "messageTemplate": "Hello, {name}!",
//!   "properties": {
//!     "name": "nblumhardt",
//!     "target": "example_app"
//!   }
//! }
//! ```
//!
//! Back-ends like Elasticsearch, Seq, and Splunk use these in queries like `user == "nblumhardt"` without up-front log parsing.
//!
//! Arguments are captured using `serde`, so there's the potential for complex values to be logged so long as they're `serde::ser::Serialize`.
//!
//! Further, because the template (format) itself is captured, it can be hashed to compute an "event type" for precisely finding
//! all occurrences of the event regardless of the value of the `user` argument.
//!
//! # Examples
//!
//! The example below writes events to stdout.
//!
//! ```
//! #[macro_use]
//! extern crate emit;
//! # extern crate log;
//!
//! use std::env;
//! use emit::pipeline;
//! use emit::collectors::stdio;
//!
//! fn main() {
//!     let _flush = pipeline::init(stdio::StdioCollector::new(), emit::LogLevel::Info);
//!
//!     eminfo!("Hello, {}!", name: env::var("USERNAME").unwrap());
//! }
//! ```
//!
//! Output:
//!
//! ```text
//! emit 2016-03-24T05:03:36Z Hello, {name}!
//!   name: "nblumhardt"
//!   target: "example_app"
//!
//! ```

extern crate serde;
extern crate serde_json;
extern crate chrono;

#[macro_use]
extern crate hyper;

#[macro_use]
extern crate log;

pub mod message_templates;
pub mod events;
pub mod pipeline;
pub mod collectors;

/// Re-exports log::LogLevel so that users can initialize the emit
/// crate without extra imports.
pub use log::LogLevel;

#[macro_export]
#[doc(hidden)]
macro_rules! __emit_get_event_data {
    ($target:expr, $s:expr, $( $n:ident: $v:expr ),* ) => {{
        #[allow(unused_imports)]
        use std::fmt::Write;
        use std::collections;

        // Underscores avoid the unused_mut warning
        let mut _names: Vec<&str> = vec![];
        let mut properties: collections::BTreeMap<&'static str, String> = collections::BTreeMap::new();

        $(
            _names.push(stringify!($n));
            properties.insert(stringify!($n), $crate::message_templates::capture(&$v));
        )*

        properties.insert("target", $crate::message_templates::capture(&$target));

        let template = $crate::message_templates::build_template($s, &_names);

        (template, properties)
    }};
}

#[macro_export]
macro_rules! emit {
    (target: $target:expr, $lvl:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        let lvl = $lvl;
        if $crate::pipeline::is_enabled(lvl) {
            let (template, properties) = __emit_get_event_data!($target, $s, $($n: $v),*);
            let event = $crate::events::Event::new_now(lvl, template, properties);
            $crate::pipeline::emit(event);
        }
    }};

    ($lvl:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        emit!(target: module_path!(), $lvl, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! emerror {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Error, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Error, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! emwarn {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Warn, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Warn, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! eminfo {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Info, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Info, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! emdebug {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Debug, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Debug, $s, $($n: $v),*);
    }};
}

#[macro_export]
macro_rules! emtrace {
    (target: $target:expr, $s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(target: $target, log::LogLevel::Trace, $s, $($n: $v),*);
    }};

    ($s:expr, $($n:ident: $v:expr),*) => {{
        #[allow(unused_imports)]
        use log;
        emit!(log::LogLevel::Trace, $s, $($n: $v),*);
    }};
}

#[cfg(test)]
mod tests {
    use collectors::stdio;
    //use collectors::seq;
    use pipeline;
    use std::env;
    use log;

    #[test]
    fn unparameterized_templates_are_captured() {
        let (template, properties) = __emit_get_event_data!("t", "Starting...",);
        assert_eq!(template, "Starting...");
        assert_eq!(properties.len(), 1);
    }

    #[test]
    fn template_and_properties_are_captured() {
        let u = "nblumhardt";
        let q = 42;

        let (template, properties) = __emit_get_event_data!("t", "User {} exceeded quota of {}!", user: u, quota: q);
        assert_eq!(template, "User {user} exceeded quota of {quota}!");
        assert_eq!(properties.get("user"), Some(&"\"nblumhardt\"".to_owned()));
        assert_eq!(properties.get("quota"), Some(&"42".to_owned()));
        assert_eq!(properties.len(), 3);
    }

    #[test]
    fn emitted_events_are_flushed() {
        let _flush = pipeline::init(stdio::StdioCollector::new(), log::LogLevel::Info);
        //let _flush = pipeline::init(seq::SeqCollector::new_local(), log::LogLevel::Info);
        eminfo!("Hello, {}!", name: env::var("USERNAME").unwrap());
    }
}
<|endoftext|>


<commit_before>#[test]
fn it_works() {
}
<commit_msg>Add some code for coverage testing<commit_after>pub struct Foo {
    a: u64,
    b: i8,
}

impl Foo {
    pub fn new() -> Foo {
        Foo { a: 42, b: 41 }
    }

    pub fn add(&mut self) {
        self.b += 1;
    }

    pub fn dec(&mut self) {
        self.b -= 1;
    }

    pub fn get(&self) -> u64 {
        self.a
    }
}

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

    #[test]
    fn add() {
        let mut f = Foo::new();
        f.add();
        assert_eq!(f.b, 42);
    }
}
<|endoftext|>


<commit_before>/// 2D coordinate
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Coord {
    pub x: usize,
    pub y: usize
}

/// 2D dimensions
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Size {
    pub width: usize,
    pub height: usize
}

impl Coord {
    /// Create a coordinate at (x, y)
    pub fn new(x: usize, y: usize) -> Coord {
        Coord {
            x: x,
            y: y
        }
    }
}

impl Size {
    /// Create a 2D size of (width, height)
    pub fn new(width: usize, height: usize) -> Size {
        Size {
            width: width,
            height: height
        }
    }

    pub fn area(&self) -> usize {
        self.width * self.height
    }

    /// Return true if the coordinate fits within self's width and
    /// height, false otherwise.
    pub fn contains_coord(&self, coord: Coord) -> bool {
        coord.x < self.width && coord.y < self.height
    }
}

/// Rectangle defined by inclusive minimum and maximum coordinates
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Rect {
    /// Minimum coordinate (inclusive)
    min_coord: Coord,

    /// Maximum coordinate (inclusive)
    max_coord: Coord
}

impl Rect {
    /// Calculate rectangle width
    pub fn width(&self) -> usize {
        return self.max_coord.x - self.min_coord.x + 1;
    }

    /// Calculate rectangle height
    pub fn height(&self) -> usize {
        return self.max_coord.y - self.min_coord.y + 1;
    }

    /// Calculate rectangle size
    pub fn size(&self) -> Size {
        Size::new(self.width(), self.height())
    }
}

pub struct Vec2D<T> {
    elems: Vec<T>,
    size: Size
}

impl<Elem: Copy> Vec2D<Elem> {
    pub fn from_example(size: Size, example: &Elem) -> Vec2D<Elem> {
        Vec2D {
            elems: vec![*example; size.area()],
            size: size
        }
    }

    pub fn from_vec(size: Size, src: Vec<Elem>) -> Option<Vec2D<Elem>> {
        if size.area() == src.len() {
            Some(Vec2D {
                elems: src,
                size: size
            })
        }
        else {
            None
        }
    }

    pub fn rect_iter_mut<'a>(&'a mut self, rect: Rect) -> Option<RectIterMut<'a, Elem>> {
        if self.size.contains_coord(rect.max_coord) {
            Some(RectIterMut {
                grid: std::marker::PhantomData,
                stride: (self.size.width - rect.width() + 1) as isize,
                cur_elem: self.elems.as_mut_ptr(),
                rect: rect,
                cur_coord: rect.min_coord
            })
        }
        else {
            None
        }
    }
}

impl<'a, Elem> Iterator for RectIterMut<'a, Elem> {
    type Item = (Coord, &'a mut Elem);

    fn next(&mut self) -> Option<Self::Item> {
        if self.cur_coord.y <= self.rect.max_coord.y {
            let result = (self.cur_coord, unsafe { &mut *self.cur_elem });

            self.cur_coord.x += 1;
            if self.cur_coord.x <= self.rect.max_coord.x {
                unsafe { self.cur_elem = self.cur_elem.offset(1); }
            }
            else {
                self.cur_coord.x = self.rect.min_coord.x;
                self.cur_coord.y += 1;
                unsafe { self.cur_elem = self.cur_elem.offset(self.stride); }
            }
            Some(result)
        }
        else {
            None
        }
    }
}

pub struct RectIterMut<'a, Elem: 'a> {
    grid: std::marker::PhantomData<&'a mut Vec2D<Elem>>,

    rect: Rect,
    cur_elem: *mut Elem,
    cur_coord: Coord,
    stride: isize
}

#[test]
fn test_rect_iter_mut() {
    let elems = vec![1, 2, 3, 4];
    let mut grid = Vec2D::from_vec(Size::new(2, 2), elems).unwrap();
    let rect = Rect::new(Coord::new(0, 0), Coord::new(1, 1)).unwrap();

    let mut actual_coords = Vec::new();
    for (coord, elem) in grid.rect_iter_mut(rect).unwrap() {
        *elem = -(*elem);
        actual_coords.push((coord.x, coord.y));
    }
    assert_eq!(actual_coords, [(0, 0), (1, 0), (0, 1), (1, 1)]);
    assert_eq!(grid.elems, [-1, -2, -3, -4]);
}

impl Rect {
    /// Create a new Rect defined by inclusive minimum and maximum
    /// coordinates. If min_coord is greater than max_coord on either
    /// axis then None is returned.
    pub fn new(min_coord: Coord, max_coord: Coord) -> Option<Rect> {
        if min_coord.x <= max_coord.x && min_coord.y <= max_coord.y {
            Some(Rect {
                min_coord: min_coord,
                max_coord: max_coord
            })
        }
        else {
            None
        }
    }

}
<commit_msg>Reorg<commit_after>/// 2D coordinate
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Coord {
    pub x: usize,
    pub y: usize
}

/// Rectangle defined by inclusive minimum and maximum coordinates
#[derive(Clone, Copy, Eq, Debug, PartialEq)]
pub struct Rect {
    /// Minimum coordinate (inclusive)
    min_coord: Coord,

    /// Maximum coordinate (inclusive)
    max_coord: Coord
}

/// 2D dimension
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Size {
    pub width: usize,
    pub height: usize
}

/// Container for 2D data
pub struct Vec2D<T> {
    elems: Vec<T>,
    size: Size
}

/// Mutable iterator over a Vec2D
pub struct RectIterMut<'a, Elem: 'a> {
    grid: std::marker::PhantomData<&'a mut Vec2D<Elem>>,

    rect: Rect,
    cur_elem: *mut Elem,
    cur_coord: Coord,
    stride: isize
}

impl Coord {
    /// Create a coordinate at (x, y)
    pub fn new(x: usize, y: usize) -> Coord {
        Coord {
            x: x,
            y: y
        }
    }
}

impl Rect {
    /// Calculate rectangle width
    pub fn width(&self) -> usize {
        return self.max_coord.x - self.min_coord.x + 1;
    }

    /// Calculate rectangle height
    pub fn height(&self) -> usize {
        return self.max_coord.y - self.min_coord.y + 1;
    }

    /// Calculate rectangle size
    pub fn size(&self) -> Size {
        Size::new(self.width(), self.height())
    }
}

impl Size {
    /// Create a 2D size of (width, height)
    pub fn new(width: usize, height: usize) -> Size {
        Size {
            width: width,
            height: height
        }
    }

    pub fn area(&self) -> usize {
        self.width * self.height
    }

    /// Return true if the coordinate fits within self's width and
    /// height, false otherwise.
    pub fn contains_coord(&self, coord: Coord) -> bool {
        coord.x < self.width && coord.y < self.height
    }
}

impl<Elem: Copy> Vec2D<Elem> {
    pub fn from_example(size: Size, example: &Elem) -> Vec2D<Elem> {
        Vec2D {
            elems: vec![*example; size.area()],
            size: size
        }
    }

    pub fn from_vec(size: Size, src: Vec<Elem>) -> Option<Vec2D<Elem>> {
        if size.area() == src.len() {
            Some(Vec2D {
                elems: src,
                size: size
            })
        }
        else {
            None
        }
    }

    pub fn rect_iter_mut<'a>(&'a mut self, rect: Rect) -> Option<RectIterMut<'a, Elem>> {
        if self.size.contains_coord(rect.max_coord) {
            Some(RectIterMut {
                grid: std::marker::PhantomData,
                stride: (self.size.width - rect.width() + 1) as isize,
                cur_elem: self.elems.as_mut_ptr(),
                rect: rect,
                cur_coord: rect.min_coord
            })
        }
        else {
            None
        }
    }
}

impl<'a, Elem> Iterator for RectIterMut<'a, Elem> {
    type Item = (Coord, &'a mut Elem);

    fn next(&mut self) -> Option<Self::Item> {
        if self.cur_coord.y <= self.rect.max_coord.y {
            let result = (self.cur_coord, unsafe { &mut *self.cur_elem });

            self.cur_coord.x += 1;
            if self.cur_coord.x <= self.rect.max_coord.x {
                unsafe { self.cur_elem = self.cur_elem.offset(1); }
            }
            else {
                self.cur_coord.x = self.rect.min_coord.x;
                self.cur_coord.y += 1;
                unsafe { self.cur_elem = self.cur_elem.offset(self.stride); }
            }
            Some(result)
        }
        else {
            None
        }
    }
}

impl Rect {
    /// Create a new Rect defined by inclusive minimum and maximum
    /// coordinates. If min_coord is greater than max_coord on either
    /// axis then None is returned.
    pub fn new(min_coord: Coord, max_coord: Coord) -> Option<Rect> {
        if min_coord.x <= max_coord.x && min_coord.y <= max_coord.y {
            Some(Rect {
                min_coord: min_coord,
                max_coord: max_coord
            })
        }
        else {
            None
        }
    }

}

#[test]
fn test_rect_iter_mut() {
    let elems = vec![1, 2, 3, 4];
    let mut grid = Vec2D::from_vec(Size::new(2, 2), elems).unwrap();
    let rect = Rect::new(Coord::new(0, 0), Coord::new(1, 1)).unwrap();

    let mut actual_coords = Vec::new();
    for (coord, elem) in grid.rect_iter_mut(rect).unwrap() {
        *elem = -(*elem);
        actual_coords.push((coord.x, coord.y));
    }
    assert_eq!(actual_coords, [(0, 0), (1, 0), (0, 1), (1, 1)]);
    assert_eq!(grid.elems, [-1, -2, -3, -4]);
}
<|endoftext|>


<commit_before>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

extern crate num;

use std::ops::{Add, Index, Mul, Sub};
use num::{One, Zero};

/// 2D matrix.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Matrix<T> {
    row: usize,
    column: usize,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn<F>(row: usize, column: usize, f: F) -> Matrix<T>
        where F:Fn(usize, usize) -> T
    {
        Matrix {
            row: row,
            column: column,
            data: (0 .. row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: usize, column: usize, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (usize, usize) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> usize { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> usize { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T> Index<(usize, usize)> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, (i, j): (usize, usize)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Matrix<Rhs>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Add<Rhs>>::Output>;

    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Add<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Sub<Rhs>>::Output>;

    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Sub<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs> Mul<Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        (&self).mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) ->  Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<&'a Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(other)
    }
}

impl<'a, 'b, Lhs, Rhs> Mul<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in 1 .. self.column() {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

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

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<commit_msg>add implementation of IndexMut trait<commit_after>//! Manipulations and data types that represent 2d matrix.

#![warn(bad_style, missing_docs,
        unused, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results, unused_typecasts)]

extern crate num;

use std::ops::{Add, Index, IndexMut, Mul, Sub};
use num::{One, Zero};

/// 2D matrix.
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct Matrix<T> {
    row: usize,
    column: usize,
    data: Vec<T>
}

impl<T> Matrix<T> {
    /// Creates a new `Matrix`.
    #[inline]
    pub fn from_fn<F>(row: usize, column: usize, f: F) -> Matrix<T>
        where F:Fn(usize, usize) -> T
    {
        Matrix {
            row: row,
            column: column,
            data: (0 .. row * column).map(|i| f(i / column, i % column)).collect()
        }
    }

    /// Creates a new `Matrix` from vector.
    #[inline]
    pub fn from_vec(row: usize, column: usize, data: Vec<T>) -> Matrix<T> {
        assert_eq!(row * column, data.len());
        Matrix { row: row, column: column, data: data }
    }

    /// Returns the matrix's row and column.
    #[inline]
    pub fn size(&self) -> (usize, usize) { (self.row(), self.column()) }
    /// Returns the matrix's row.
    #[inline]
    pub fn row(&self) -> usize { self.row }
    /// Returns the matrix's column.
    #[inline]
    pub fn column(&self) -> usize { self.column }
}

impl<T: Zero> Matrix<T> {
    /// Creates a matrix whose elements are all zero.
    #[inline]
    pub fn zero(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |_, _| Zero::zero())
    }
}

impl<T: One + Zero> Matrix<T> {
    /// Creates a identity matrix.
    #[inline]
    pub fn one(row: usize, column: usize) -> Matrix<T> {
        Matrix::from_fn(row, column, |i, j| {
            if i == j {
                One::one()
            } else {
                Zero::zero()
            }
        })
    }
}

impl<T: Clone> Matrix<T> {
    #[inline]
    /// Returns transpose of the matrix.
    pub fn trans(&self) -> Matrix<T> {
        Matrix::from_fn(self.column(), self.row(), |i, j| self[(j, i)].clone())
    }
}

impl<T> Index<(usize, usize)> for Matrix<T> {
    type Output = T;

    #[inline]
    fn index(&self, (i, j): (usize, usize)) -> &T {
        assert!(i < self.row() && j < self.column());
        &self.data[i * self.column() + j]
    }
}

impl<T> IndexMut<(usize, usize)> for Matrix<T> {
    #[inline]
    fn index_mut(&mut self, (i, j): (usize, usize)) -> &mut T {
        assert!(i < self.row && j < self.column);
        &mut self.data[i * self.column + j]
    }
}

macro_rules! forward_val_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<Lhs, Rhs> $imp<Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(&other)
            }
        }
    }
}

macro_rules! forward_ref_val_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<Matrix<Rhs>> for &'a Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                self.$method(&other)
            }
        }
    }
}

macro_rules! forward_val_ref_binop {
    (impl $imp:ident, $method:ident) => {
        impl<'a, Lhs, Rhs> $imp<&'a Matrix<Rhs>> for Matrix<Lhs>
            where Lhs: $imp<Rhs> + Clone, Rhs: Clone
        {
            type Output = Matrix<<Lhs as $imp<Rhs>>::Output>;

            #[inline]
            fn $method(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as $imp<Rhs>>::Output> {
                (&self).$method(other)
            }
        }
    }
}

macro_rules! forward_all_binop {
    (impl $imp:ident, $method:ident) => {
        forward_val_val_binop!(impl $imp, $method);
        forward_ref_val_binop!(impl $imp, $method);
        forward_val_ref_binop!(impl $imp, $method);
    };
}

forward_all_binop!(impl Add, add);

impl<'a, 'b, Lhs, Rhs> Add<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Add<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Add<Rhs>>::Output>;

    #[inline]
    fn add(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Add<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() + other[(i, j)].clone())
    }
}

forward_all_binop!(impl Sub, sub);

impl<'a, 'b, Lhs, Rhs> Sub<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Sub<Rhs> + Clone, Rhs: Clone
{
    type Output = Matrix<<Lhs as Sub<Rhs>>::Output>;

    #[inline]
    fn sub(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Sub<Rhs>>::Output> {
        assert_eq!(self.size(), other.size());
        Matrix::from_fn(self.row(), self.column(), |i, j| self[(i, j)].clone() - other[(i, j)].clone())
    }
}

impl<Lhs, Rhs> Mul<Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        (&self).mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: Matrix<Rhs>) ->  Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(&other)
    }
}

impl<'a, Lhs, Rhs> Mul<&'a Matrix<Rhs>> for Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        self.mul(other)
    }
}

impl<'a, 'b, Lhs, Rhs> Mul<&'b Matrix<Rhs>> for &'a Matrix<Lhs>
    where Lhs: Mul<Rhs> + Clone, Rhs: Clone,
          <Lhs as Mul<Rhs>>::Output: Add<Output = <Lhs as Mul<Rhs>>::Output>
{
    type Output = Matrix<<Lhs as Mul<Rhs>>::Output>;

    #[inline]
    fn mul(self, other: &Matrix<Rhs>) -> Matrix<<Lhs as Mul<Rhs>>::Output> {
        assert_eq!(self.column(), other.row());
        Matrix::from_fn(self.row(), other.column(), |i, j| {
            let mut sum = self[(i, 0)].clone() * other[(0, j)].clone();
            for k in 1 .. self.column() {
                sum = sum + self[(i, k)].clone() * other[(k, j)].clone();
            }
            sum
        })
    }
}

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

    #[test]
    fn from_vec() {
        let mat = Matrix::from_vec(2, 3, vec![(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2)]);
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn index() {
        let mat = Matrix::from_fn(3, 5, |i, j| (i, j));
        for i in 0 .. mat.row() {
            for j in 0 .. mat.column() {
                assert_eq!((i, j), mat[(i, j)]);
            }
        }
    }

    #[test]
    fn mul() {
        let m1 = Matrix::from_vec(1, 3, vec![1.0f64, 2.0, 3.0]);
        let m2 = Matrix::from_vec(3, 1, vec![1.0, 2.0, 3.0]);
        assert_eq!(Matrix::from_vec(1, 1, vec![14.0]), m1 * m2);
        assert_eq!(Matrix::from_vec(3, 1, vec![1.0f64, 4.0, 7.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 1, vec![1.0, 0.0, 0.0]));
        assert_eq!(Matrix::from_vec(3, 2, vec![1.0f64, 3.0, 4.0, 6.0, 7.0, 9.0]),
                   Matrix::from_vec(3, 3, vec![1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]) *
                   Matrix::from_vec(3, 2, vec![1.0, 0.0, 0.0, 0.0, 0.0, 1.0]));
    }
}

<|endoftext|>


<commit_before>//! Iterator-based `linspace` and `logspace` functions

#![cfg_attr(test, plugin(quickcheck_macros))]
#![deny(missing_docs, warnings)]
#![feature(plugin)]

#[cfg(test)]
extern crate quickcheck;
extern crate cast;

use cast::CastTo;
use std::num::Float;

#[cfg(test)]
mod test;

/// Iterator that yields equally spaced numbers in the linear scale
#[derive(Copy)]
pub struct Linspace<T> where T: cast::Float {
    start: T,
    state: usize,
    step: T,
    stop: usize,
}

impl<T> DoubleEndedIterator for Linspace<T> where T: cast::Float {
    fn next_back(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            self.stop -= 1;
            Some(self.start + self.step * self.stop.to::<T>())
        }
    }
}

impl<T> Iterator for Linspace<T> where T: cast::Float {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            let next = self.start + self.step * self.state.to::<T>();
            self.state += 1;
            Some(next)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.stop - self.state;
        (exact, Some(exact))
    }
}

/// Iterator that yields equally spaced numbers in the logarithmic scale
#[derive(Copy)]
pub struct Logspace<T> where T: cast::Float {
    start: T,
    state: usize,
    step: T,
    stop: usize,
}

impl<T> DoubleEndedIterator for Logspace<T> where T: cast::Float {
    fn next_back(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            self.stop -= 1;
            Some((self.start + self.step * self.stop.to::<T>()).exp())
        }
    }
}

impl<T> Iterator for Logspace<T> where T: cast::Float {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            let next = self.start + self.step * self.state.to::<T>();
            self.state += 1;
            Some(next.exp())
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.stop - self.state;
        (exact, Some(exact))
    }
}

/// Returns an iterator that yields `n` evenly spaced numbers over the `[start, end]` interval
///
/// # Panics
///
/// Panics if `end` < `start`
///
/// # Examples
///
/// **Note** These assertions will likely fail because of rounding errors. (In real applications
/// you shouldn't directly use equality between floats, but instead check that the absolute
/// difference is within some tolerance)
///
/// ``` ignore
/// assert_eq!(vec![2., 2.25, 2.5, 2.75, 3.], linspace(2., 3., 5).collect::<Vec<_>>())
/// assert_eq!(vec![3., 2.75, 2.5, 2.25, 2.], linspace(2., 3., 5).rev().collect::<Vec<_>>())
/// ```
pub fn linspace<T>(start: T, end: T, n: usize) -> Linspace<T> where T: cast::Float {
    assert!(start <= end);

    let step = if n < 2 {
        // NB The value of `step` doesn't matter in these cases
        0.to::<T>()
    } else {
        (end - start) / (n - 1).to::<T>()
    };

    Linspace {
        start: start,
        state: 0,
        step: step,
        stop: n,
    }
}

/// Logarithmic version of `linspace`
///
/// # Panics
///
/// Panics if `start` or `end` is a non-positive number, or if `end` < `start`
///
/// # Examples
///
/// **Note** These assertions will likely fail because of rounding errors. (In real applications
/// you shouldn't directly use equality between floats, but instead check that the absolute
/// difference is within some tolerance)
///
/// ``` ignore
/// assert_eq!(vec![0.1, 1., 10., 100.], logspace(0.1, 100., 4).collect::<Vec<_>>())
/// assert_eq!(vec![100., 10., 1., 0.1], logspace(0.1, 100., 4).rev().collect::<Vec<_>>())
/// ```
pub fn logspace<T>(start: T, end: T, n: usize) -> Logspace<T> where T: cast::Float {
    let _0 = 0.to::<T>();

    assert!(start > _0 && end > _0 && start <= end);

    let (start, end) = (start.ln(), end.ln());

    let step = if n < 2 {
        // NB The value of `step` doesn't matter in these cases
        _0
    } else {
        (end - start) / (n - 1).to::<T>()
    };

    Logspace {
        start: start,
        state: 0,
        step: step,
        stop: n,
    }
}
<commit_msg>feat: `Linspace`/`Logspace` are no longer implicitly copyable<commit_after>//! Iterator-based `linspace` and `logspace` functions

#![cfg_attr(test, plugin(quickcheck_macros))]
#![deny(missing_docs, warnings)]
#![feature(plugin)]

#[cfg(test)]
extern crate quickcheck;
extern crate cast;

use cast::CastTo;
use std::num::Float;

#[cfg(test)]
mod test;

/// Iterator that yields equally spaced numbers in the linear scale
#[derive(Clone)]
pub struct Linspace<T> where T: cast::Float {
    start: T,
    state: usize,
    step: T,
    stop: usize,
}

impl<T> DoubleEndedIterator for Linspace<T> where T: cast::Float {
    fn next_back(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            self.stop -= 1;
            Some(self.start + self.step * self.stop.to::<T>())
        }
    }
}

impl<T> Iterator for Linspace<T> where T: cast::Float {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            let next = self.start + self.step * self.state.to::<T>();
            self.state += 1;
            Some(next)
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.stop - self.state;
        (exact, Some(exact))
    }
}

/// Iterator that yields equally spaced numbers in the logarithmic scale
#[derive(Clone)]
pub struct Logspace<T> where T: cast::Float {
    start: T,
    state: usize,
    step: T,
    stop: usize,
}

impl<T> DoubleEndedIterator for Logspace<T> where T: cast::Float {
    fn next_back(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            self.stop -= 1;
            Some((self.start + self.step * self.stop.to::<T>()).exp())
        }
    }
}

impl<T> Iterator for Logspace<T> where T: cast::Float {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        if self.state == self.stop {
            None
        } else {
            let next = self.start + self.step * self.state.to::<T>();
            self.state += 1;
            Some(next.exp())
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let exact = self.stop - self.state;
        (exact, Some(exact))
    }
}

/// Returns an iterator that yields `n` evenly spaced numbers over the `[start, end]` interval
///
/// # Panics
///
/// Panics if `end` < `start`
///
/// # Examples
///
/// **Note** These assertions will likely fail because of rounding errors. (In real applications
/// you shouldn't directly use equality between floats, but instead check that the absolute
/// difference is within some tolerance)
///
/// ``` ignore
/// assert_eq!(vec![2., 2.25, 2.5, 2.75, 3.], linspace(2., 3., 5).collect::<Vec<_>>())
/// assert_eq!(vec![3., 2.75, 2.5, 2.25, 2.], linspace(2., 3., 5).rev().collect::<Vec<_>>())
/// ```
pub fn linspace<T>(start: T, end: T, n: usize) -> Linspace<T> where T: cast::Float {
    assert!(start <= end);

    let step = if n < 2 {
        // NB The value of `step` doesn't matter in these cases
        0.to::<T>()
    } else {
        (end - start) / (n - 1).to::<T>()
    };

    Linspace {
        start: start,
        state: 0,
        step: step,
        stop: n,
    }
}

/// Logarithmic version of `linspace`
///
/// # Panics
///
/// Panics if `start` or `end` is a non-positive number, or if `end` < `start`
///
/// # Examples
///
/// **Note** These assertions will likely fail because of rounding errors. (In real applications
/// you shouldn't directly use equality between floats, but instead check that the absolute
/// difference is within some tolerance)
///
/// ``` ignore
/// assert_eq!(vec![0.1, 1., 10., 100.], logspace(0.1, 100., 4).collect::<Vec<_>>())
/// assert_eq!(vec![100., 10., 1., 0.1], logspace(0.1, 100., 4).rev().collect::<Vec<_>>())
/// ```
pub fn logspace<T>(start: T, end: T, n: usize) -> Logspace<T> where T: cast::Float {
    let _0 = 0.to::<T>();

    assert!(start > _0 && end > _0 && start <= end);

    let (start, end) = (start.ln(), end.ln());

    let step = if n < 2 {
        // NB The value of `step` doesn't matter in these cases
        _0
    } else {
        (end - start) / (n - 1).to::<T>()
    };

    Logspace {
        start: start,
        state: 0,
        step: step,
        stop: n,
    }
}
<|endoftext|>


<commit_before>mod token;

pub fn compile(sass: String, style: &str) -> String {
    let mut sr = SassReader::new(sass);
    println!("{:?}", sr);
    let parsed = sr.parse();
    match style {
        "nested"     => nested(parsed),
        "compressed" => compressed(parsed),
        "expanded"   => expanded(parsed),
        "compact"    => compact(parsed),
        _            => panic!("Unknown style: {}. Please specify one of nested, compressed, expanded, or compact.", style),
    }
}

fn nested(sass: String) -> String {
    sass
}

fn compressed(sass: String) -> String {
    sass.replace(" ", "").replace("\n", "")
}

fn expanded(sass: String) -> String {
    sass
}

fn compact(sass: String) -> String {
    sass
}

struct SassRuleSet {
    pub rules: Vec<SassRule>,
}

struct SassRule {
    pub selectors: Vec<token::Token>,
    pub propsNVals: Vec<PropertyValueSet>,
}

struct PropertyValueSet {
    pub property: token::Token,
    pub value: token::Token,
}

#[derive(Debug)]
struct SassReader {
    pub pos: u32,
    pub last_pos: u32,
    pub curr: Option<char>,
    pub peek_tok: token::Token,
    sass: String,
}

impl SassReader {
    pub fn new(str: String) -> SassReader {
        let mut sr = SassReader {
            pos: 0,
            last_pos: 0,
            curr: Some('\n'),
            peek_tok: token::Eof,
            sass: str,
        };
        sr.bump();
        sr.advance_token();
        sr
    }

    pub fn bump(&mut self) {
        self.last_pos = self.pos;
        let current_pos = self.pos as usize;
        if current_pos < self.sass.len() {
            let ch = char_at(&self.sass, current_pos);

            self.pos = self.pos + (ch.len_utf8() as u32);
            self.curr = Some(ch);
        } else {
            self.curr = None;
        }
    }

    pub fn advance_token(&mut self) {
        match self.scan_whitespace() {
            Some(whitespace) => {
                self.peek_tok = whitespace;
            },
            None => {
                if self.is_eof() {
                    self.peek_tok = token::Eof;
                } else {
                    self.peek_tok = self.next_token_inner();
                }
            },
        }
    }

    pub fn next_token(&mut self) -> token::Token {
        let ret_val = self.peek_tok.clone();
        self.advance_token();
        ret_val
    }

    pub fn parse(&mut self) -> String {
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        self.sass.clone()
    }

    fn parse_rules(&mut self) -> Result<SassRuleSet, &'static str> {
        let mut rules = vec![];
        while let Some(rule) = try!(self.parse_rule()) {
            rules.push(rule);
        }
        Ok(SassRuleSet { rules: rules })
    }

    fn parse_rule(&mut self) -> Result<Option<SassRule>, &'static str> {
        let mut selectors = vec![];
        while let Some(selector) = try!(self.parse_selector()) {
            selectors.push(selector);
        }
        let mut propsNVals = vec![];
        while let Some(property_value_set) = try!(self.parse_property_value_set()) {
            propsNVals.push(property_value_set);
        }
        Ok(Some(SassRule { selectors: selectors, propsNVals: propsNVals }))
    }

    fn parse_selector(&mut self) -> Result<Option<token::Token>, &'static str> {
        Err("not implemented")
    }

    fn parse_property_value_set(&mut self) -> Result<Option<PropertyValueSet>, &'static str> {
        Err("not implemented")
    }

    fn next_token_inner(&mut self) -> token::Token {
        let c = match self.curr {
            Some(c) => c,
            None => return token::Eof,
        };

        if c >= 'a' && c <= 'z' {
            let start = self.last_pos;
            while !self.curr.is_none() && self.curr.unwrap() >= 'a' && self.curr.unwrap() <= 'z' {
                self.bump();
            }
            return token::Selector { start_pos: start, end_pos: self.last_pos }
        }

        match c {
            ';' => { self.bump(); return token::Semi; },
            ':' => { self.bump(); return token::Colon; },
            ',' => { self.bump(); return token::Comma; },
            '{' => { self.bump(); return token::OpenDelim(token::Brace); },
            '}' => { self.bump(); return token::CloseDelim(token::Brace); },
            _   => { return token::Unknown { pos: self.last_pos } },
        }
    }

    fn scan_whitespace(&mut self) -> Option<token::Token> {
        match self.curr.unwrap_or('\0') {
            c if is_whitespace(Some(c)) => {
                let start = self.last_pos;
                while is_whitespace(self.curr) { self.bump(); }
                Some(token::Whitespace { start_pos: start, end_pos: self.last_pos })
            },
            _ => None
        }
    }

    fn is_eof(&self) -> bool {
        self.curr.is_none()
    }
}

pub fn char_at(s: &str, byte: usize) -> char {
    s[byte..].chars().next().unwrap()
}

pub fn is_whitespace(c: Option<char>) -> bool {
    match c.unwrap_or('\x00') { // None can be null for now... it's not whitespace
        ' ' | '\n' | '\t' | '\r' => true,
        _ => false
    }
}
<commit_msg>Rename SassReader to SassTokenizer<commit_after>mod token;

pub fn compile(sass: String, style: &str) -> String {
    let mut sr = SassTokenizer::new(sass);
    println!("{:?}", sr);
    let parsed = sr.parse();
    match style {
        "nested"     => nested(parsed),
        "compressed" => compressed(parsed),
        "expanded"   => expanded(parsed),
        "compact"    => compact(parsed),
        _            => panic!("Unknown style: {}. Please specify one of nested, compressed, expanded, or compact.", style),
    }
}

fn nested(sass: String) -> String {
    sass
}

fn compressed(sass: String) -> String {
    sass.replace(" ", "").replace("\n", "")
}

fn expanded(sass: String) -> String {
    sass
}

fn compact(sass: String) -> String {
    sass
}

struct SassRuleSet {
    pub rules: Vec<SassRule>,
}

struct SassRule {
    pub selectors: Vec<token::Token>,
    pub propsNVals: Vec<PropertyValueSet>,
}

struct PropertyValueSet {
    pub property: token::Token,
    pub value: token::Token,
}

#[derive(Debug)]
struct SassTokenizer {
    pub pos: u32,
    pub last_pos: u32,
    pub curr: Option<char>,
    pub peek_tok: token::Token,
    sass: String,
}

impl SassTokenizer {
    pub fn new(str: String) -> SassTokenizer {
        let mut sr = SassTokenizer {
            pos: 0,
            last_pos: 0,
            curr: Some('\n'),
            peek_tok: token::Eof,
            sass: str,
        };
        sr.bump();
        sr.advance_token();
        sr
    }

    pub fn bump(&mut self) {
        self.last_pos = self.pos;
        let current_pos = self.pos as usize;
        if current_pos < self.sass.len() {
            let ch = char_at(&self.sass, current_pos);

            self.pos = self.pos + (ch.len_utf8() as u32);
            self.curr = Some(ch);
        } else {
            self.curr = None;
        }
    }

    pub fn advance_token(&mut self) {
        match self.scan_whitespace() {
            Some(whitespace) => {
                self.peek_tok = whitespace;
            },
            None => {
                if self.is_eof() {
                    self.peek_tok = token::Eof;
                } else {
                    self.peek_tok = self.next_token_inner();
                }
            },
        }
    }

    pub fn next_token(&mut self) -> token::Token {
        let ret_val = self.peek_tok.clone();
        self.advance_token();
        ret_val
    }

    pub fn parse(&mut self) -> String {
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        println!("{:?}", self.next_token());
        self.sass.clone()
    }

    fn parse_rules(&mut self) -> Result<SassRuleSet, &'static str> {
        let mut rules = vec![];
        while let Some(rule) = try!(self.parse_rule()) {
            rules.push(rule);
        }
        Ok(SassRuleSet { rules: rules })
    }

    fn parse_rule(&mut self) -> Result<Option<SassRule>, &'static str> {
        let mut selectors = vec![];
        while let Some(selector) = try!(self.parse_selector()) {
            selectors.push(selector);
        }
        let mut propsNVals = vec![];
        while let Some(property_value_set) = try!(self.parse_property_value_set()) {
            propsNVals.push(property_value_set);
        }
        Ok(Some(SassRule { selectors: selectors, propsNVals: propsNVals }))
    }

    fn parse_selector(&mut self) -> Result<Option<token::Token>, &'static str> {
        Err("not implemented")
    }

    fn parse_property_value_set(&mut self) -> Result<Option<PropertyValueSet>, &'static str> {
        Err("not implemented")
    }

    fn next_token_inner(&mut self) -> token::Token {
        let c = match self.curr {
            Some(c) => c,
            None => return token::Eof,
        };

        if c >= 'a' && c <= 'z' {
            let start = self.last_pos;
            while !self.curr.is_none() && self.curr.unwrap() >= 'a' && self.curr.unwrap() <= 'z' {
                self.bump();
            }
            return token::Selector { start_pos: start, end_pos: self.last_pos }
        }

        match c {
            ';' => { self.bump(); return token::Semi; },
            ':' => { self.bump(); return token::Colon; },
            ',' => { self.bump(); return token::Comma; },
            '{' => { self.bump(); return token::OpenDelim(token::Brace); },
            '}' => { self.bump(); return token::CloseDelim(token::Brace); },
            _   => { return token::Unknown { pos: self.last_pos } },
        }
    }

    fn scan_whitespace(&mut self) -> Option<token::Token> {
        match self.curr.unwrap_or('\0') {
            c if is_whitespace(Some(c)) => {
                let start = self.last_pos;
                while is_whitespace(self.curr) { self.bump(); }
                Some(token::Whitespace { start_pos: start, end_pos: self.last_pos })
            },
            _ => None
        }
    }

    fn is_eof(&self) -> bool {
        self.curr.is_none()
    }
}

pub fn char_at(s: &str, byte: usize) -> char {
    s[byte..].chars().next().unwrap()
}

pub fn is_whitespace(c: Option<char>) -> bool {
    match c.unwrap_or('\x00') { // None can be null for now... it's not whitespace
        ' ' | '\n' | '\t' | '\r' => true,
        _ => false
    }
}
<|endoftext|>