<commit_before>#![feature(metadata_ext)]
#![cfg_attr(any(target_os = "bitrig",
                target_os = "freebsd",
                target_os = "ios",
                target_os = "macos",
                target_os = "openbsd"), feature(raw_ext))]

#[cfg(unix)] use std::os::unix::prelude::*;
#[cfg(windows)] use std::os::windows::prelude::*;

use std::fmt;
use std::fs;

/// A helper structure to represent a timestamp for a file.
///
/// The actual value contined within is platform-specific and does not have the
/// same meaning across platforms, but comparisons and stringification can be
/// significant among the same platform.
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)]
pub struct FileTime {
    seconds: u64,
    nanos: u32,
}

impl FileTime {
    /// Creates a new timestamp representing a 0 time.
    ///
    /// Useful for creating the base of a cmp::max chain of times.
    pub fn zero() -> FileTime {
        FileTime { seconds: 0, nanos: 0 }
    }

    /// Creates a new timestamp from the last modification time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `mtime` field of `stat` on Unix
    /// platforms and the `ftLastWriteTime` field on Windows platforms.
    pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            let meta = meta.as_raw();
            FileTime::from_os_repr(meta.mtime() as u64, meta.mtime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_write_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the last access time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `atime` field of `stat` on Unix
    /// platforms and the `ftLastAccessTime` field on Windows platforms.
    pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            let meta = meta.as_raw();
            FileTime::from_os_repr(meta.atime() as u64, meta.atime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_access_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the creation time listed in the specified
    /// metadata.
    ///
    /// The returned value corresponds to the `birthtime` field of `stat` on
    /// Unix platforms and the `ftCreationTime` field on Windows platforms. Note
    /// that not all Unix platforms have this field available and may return
    /// `None` in some circumstances.
    pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
        macro_rules! birthtim {
            ($(($e:expr, $i:ident)),*) => {
                #[cfg(any($(target_os = $e),*))]
                fn imp(meta: &fs::Metadata) -> Option<FileTime> {
                    $(
                        #[cfg(target_os = $e)]
                        use std::os::$i::fs::MetadataExt;
                    )*
                    let raw = meta.as_raw_stat();
                    Some(FileTime::from_os_repr(raw.st_birthtime as u64,
                                                raw.st_birthtime_nsec as u32))
                }

                #[cfg(all(not(windows),
                          $(not(target_os = $e)),*))]
                fn imp(_meta: &fs::Metadata) -> Option<FileTime> {
                    None
                }
            }
        }

        birthtim! {
            ("bitrig", bitrig),
            ("freebsd", freebsd),
            ("ios", ios),
            ("macos", macos),
            ("openbsd", openbsd)
        }

        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> Option<FileTime> {
            FileTime::from_os_repr(meta.last_access_time())
        }
        imp(meta)
    }

    #[cfg(windows)]
    fn from_os_repr(time: u64) -> FileTime {
        // Windows write times are in 100ns intervals, so do a little math to
        // get it into the right representation.
        FileTime {
            seconds: time / (1_000_000_000 / 100),
            nanos: ((time % (1_000_000_000 / 100)) * 100) as u32,
        }
    }

    #[cfg(unix)]
    fn from_os_repr(seconds: u64, _nanos: u32) -> FileTime {
        // FIXME: currently there is a bug in the standard library where the
        //        nanosecond accessor is just accessing the seconds again, once
        //        that bug is fixed this should take nanoseconds into account.
        FileTime { seconds: seconds, nanos: 0 }
    }

    /// Returns the whole number of seconds represented by this timestamp.
    ///
    /// Note that this value's meaning is **platform specific**. On Unix
    /// platform time stamps are typically relative to January 1, 1970, but on
    /// Windows platforms time stamps are relative to January 1, 1601.
    pub fn seconds(&self) -> u64 { self.seconds }

    /// Returns the nanosecond precision of this timestamp.
    ///
    /// The returned value is always less than one billion and represents a
    /// portion of a second forward from the seconds returned by the `seconds`
    /// method.
    pub fn nanoseconds(&self) -> u32 { self.nanos }
}

impl fmt::Display for FileTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}.{:09}s", self.seconds, self.nanos)
    }
}
<commit_msg>Add an accessor for seconds relative to 1970<commit_after>#![feature(metadata_ext)]
#![cfg_attr(any(target_os = "bitrig",
                target_os = "freebsd",
                target_os = "ios",
                target_os = "macos",
                target_os = "openbsd"), feature(raw_ext))]

#[cfg(unix)] use std::os::unix::prelude::*;
#[cfg(windows)] use std::os::windows::prelude::*;

use std::fmt;
use std::fs;

/// A helper structure to represent a timestamp for a file.
///
/// The actual value contined within is platform-specific and does not have the
/// same meaning across platforms, but comparisons and stringification can be
/// significant among the same platform.
#[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)]
pub struct FileTime {
    seconds: u64,
    nanos: u32,
}

impl FileTime {
    /// Creates a new timestamp representing a 0 time.
    ///
    /// Useful for creating the base of a cmp::max chain of times.
    pub fn zero() -> FileTime {
        FileTime { seconds: 0, nanos: 0 }
    }

    /// Creates a new timestamp from the last modification time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `mtime` field of `stat` on Unix
    /// platforms and the `ftLastWriteTime` field on Windows platforms.
    pub fn from_last_modification_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            let meta = meta.as_raw();
            FileTime::from_os_repr(meta.mtime() as u64, meta.mtime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_write_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the last access time listed in the
    /// specified metadata.
    ///
    /// The returned value corresponds to the `atime` field of `stat` on Unix
    /// platforms and the `ftLastAccessTime` field on Windows platforms.
    pub fn from_last_access_time(meta: &fs::Metadata) -> FileTime {
        #[cfg(unix)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            let meta = meta.as_raw();
            FileTime::from_os_repr(meta.atime() as u64, meta.atime_nsec() as u32)
        }
        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> FileTime {
            FileTime::from_os_repr(meta.last_access_time())
        }
        imp(meta)
    }

    /// Creates a new timestamp from the creation time listed in the specified
    /// metadata.
    ///
    /// The returned value corresponds to the `birthtime` field of `stat` on
    /// Unix platforms and the `ftCreationTime` field on Windows platforms. Note
    /// that not all Unix platforms have this field available and may return
    /// `None` in some circumstances.
    pub fn from_creation_time(meta: &fs::Metadata) -> Option<FileTime> {
        macro_rules! birthtim {
            ($(($e:expr, $i:ident)),*) => {
                #[cfg(any($(target_os = $e),*))]
                fn imp(meta: &fs::Metadata) -> Option<FileTime> {
                    $(
                        #[cfg(target_os = $e)]
                        use std::os::$i::fs::MetadataExt;
                    )*
                    let raw = meta.as_raw_stat();
                    Some(FileTime::from_os_repr(raw.st_birthtime as u64,
                                                raw.st_birthtime_nsec as u32))
                }

                #[cfg(all(not(windows),
                          $(not(target_os = $e)),*))]
                fn imp(_meta: &fs::Metadata) -> Option<FileTime> {
                    None
                }
            }
        }

        birthtim! {
            ("bitrig", bitrig),
            ("freebsd", freebsd),
            ("ios", ios),
            ("macos", macos),
            ("openbsd", openbsd)
        }

        #[cfg(windows)]
        fn imp(meta: &fs::Metadata) -> Option<FileTime> {
            FileTime::from_os_repr(meta.last_access_time())
        }
        imp(meta)
    }

    #[cfg(windows)]
    fn from_os_repr(time: u64) -> FileTime {
        // Windows write times are in 100ns intervals, so do a little math to
        // get it into the right representation.
        FileTime {
            seconds: time / (1_000_000_000 / 100),
            nanos: ((time % (1_000_000_000 / 100)) * 100) as u32,
        }
    }

    #[cfg(unix)]
    fn from_os_repr(seconds: u64, _nanos: u32) -> FileTime {
        // FIXME: currently there is a bug in the standard library where the
        //        nanosecond accessor is just accessing the seconds again, once
        //        that bug is fixed this should take nanoseconds into account.
        FileTime { seconds: seconds, nanos: 0 }
    }

    /// Returns the whole number of seconds represented by this timestamp.
    ///
    /// Note that this value's meaning is **platform specific**. On Unix
    /// platform time stamps are typically relative to January 1, 1970, but on
    /// Windows platforms time stamps are relative to January 1, 1601.
    pub fn seconds(&self) -> u64 { self.seconds }

    /// Returns the whole number of seconds represented by this timestamp,
    /// relative to the Unix epoch start of January 1, 1970.
    ///
    /// Note that this does not return the same value as `seconds` for Windows
    /// platforms as seconds are relative to a different date there.
    pub fn seconds_relative_to_1970(&self) -> u64 {
        self.seconds - if cfg!(windows) {11644473600} else {0}
    }

    /// Returns the nanosecond precision of this timestamp.
    ///
    /// The returned value is always less than one billion and represents a
    /// portion of a second forward from the seconds returned by the `seconds`
    /// method.
    pub fn nanoseconds(&self) -> u32 { self.nanos }
}

impl fmt::Display for FileTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}.{:09}s", self.seconds, self.nanos)
    }
}
<|endoftext|>


<commit_before>extern crate bincode;
extern crate rustc_serialize;

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, decode};
use rustc_serialize::{Encodable, Decodable};

use std::error::Error;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, ErrorKind};
use std::fs::OpenOptions;
use std::mem::{size_of};
use std::cmp::max;
use std::convert::From;

const NUM_CHILDREN: usize = 32;

// specify the types for the keys & values
pub trait KeyType: Ord + Encodable + Decodable {}
pub trait ValueType: Encodable + Decodable {}

#[derive(RustcEncodable, RustcDecodable, PartialEq)]
enum Payload<K: Ord, V: ValueType> {
        Value(V),
        Children([(K,u64); NUM_CHILDREN]),
    }

#[derive(RustcEncodable, RustcDecodable, PartialEq)]
struct Node<K: KeyType, V: ValueType> {
    key: K,
    parent: u64,
    payload: Payload<K,V>, // either children, or actual values
}

/// This struct represents an on-disk B+Tree. There are NUM_CHILDREN keys at each
/// level in the tree. The on-disk format is as follows where VV is the version
/// number:
/// |-------------------------------------------|
/// | 0x2b 0x42 0x72 0x54 | 0x65 0x65 0x00 0xVV |
/// |-------------------------------------------|
/// | smallest record in bincode format         |
/// |-------------------------------------------|
/// | ...                                       |
/// |-------------------------------------------|
/// | largest record in bincode format          |
/// |-------------------------------------------|
/// | internal nodes ...                        |
/// |-------------------------------------------|
/// | root node                                 |
/// |-------------------------------------------|
pub struct BTree<K: KeyType, V: ValueType> {
    fd: File,           // the file backing the whole thing
    root: Node<K,V>,    // in-memory copy of the root node
    key_size: usize,    // the size of the key in bytes
    value_size: usize,  // the size of the value in bytes
}

impl <K: KeyType, V: ValueType> BTree<K, V> {
    pub fn new(key_size: usize, value_size: usize) -> Result<BTree<K,V>, Box<Error>> {
        let mut file = try!(OpenOptions::new()
                                  .read(true)
                                  .write(true)
                                  .create(true)
                                  .open("btree.dat"));

        // make sure we've opened a proper file
        let mut version_string = Vec::with_capacity(8);

        try!(file.read_exact(&mut version_string));

        if version_string[0] != 0x2b {
            return Err(From::from(std::io::Error::new(ErrorKind::InvalidData, "Invalid BTree file version")));
        }

        // total size of a Node
        let total_size = key_size + size_of::<u64>() + max(value_size, (key_size+size_of::<u64>()) * NUM_CHILDREN);
        let mut buff = Vec::with_capacity(total_size);

        // seek total_size in from the end of the file to read the root node
        try!(file.seek(SeekFrom::End(total_size as i64)));
        try!(file.read_exact(&mut buff));

        let root_node: Node<K,V> = decode(&buff[..]).unwrap();

        Ok(BTree{ fd: file, key_size: key_size, value_size: value_size, root: root_node })
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        println!("It works!!!")
    }
}
<commit_msg>First cut at the new method<commit_after>extern crate bincode;
extern crate rustc_serialize;

use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, decode};
use rustc_serialize::{Encodable, Decodable};

use std::cmp::max;
use std::convert::From;
use std::error::Error;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::{Read, Write, Seek, SeekFrom, ErrorKind};
use std::mem::{size_of};
use std::str;

const NUM_CHILDREN: usize = 32;
const FILE_HEADER: &'static str = "B+Tree\0";
const CURRENT_VERSION: u8 = 0x01;

// specify the types for the keys & values
pub trait KeyType: Ord + Encodable + Decodable {}
pub trait ValueType: Encodable + Decodable {}

#[derive(RustcEncodable, RustcDecodable, PartialEq)]
enum Payload<K: Ord, V: ValueType> {
        Value(V),
        Children([(K,u64); NUM_CHILDREN]),
    }

#[derive(RustcEncodable, RustcDecodable, PartialEq)]
struct Node<K: KeyType, V: ValueType> {
    key: K,
    parent: u64,
    payload: Payload<K,V>, // either children, or actual values
}

/// This struct represents an on-disk B+Tree. There are NUM_CHILDREN keys at each
/// level in the tree. The on-disk format is as follows where VV is the version
/// number:
/// |-------------------------------------------|
/// | 0x42 0x2b 0x54 0x72 | 0x65 0x65 0x00 0xVV |
/// | B    +    T    r    | e    e    \0   0xVV |
/// |-------------------------------------------|
/// | smallest record in bincode format         |
/// |-------------------------------------------|
/// | ...                                       |
/// |-------------------------------------------|
/// | largest record in bincode format          |
/// |-------------------------------------------|
/// | internal nodes ...                        |
/// |-------------------------------------------|
/// | root node                                 |
/// |-------------------------------------------|
pub struct BTree<K: KeyType, V: ValueType> {
    fd: File,                // the file backing the whole thing
    root: Option<Node<K,V>>, // optional in-memory copy of the root node
    key_size: usize,         // the size of the key in bytes
    value_size: usize,       // the size of the value in bytes
}

impl <K: KeyType, V: ValueType> BTree<K, V> {
    pub fn new(key_size: usize, value_size: usize) -> Result<BTree<K,V>, Box<Error>> {
        let mut file = try!(OpenOptions::new()
                                  .read(true)
                                  .write(true)
                                  .create(true)
                                  .open("btree.dat"));

        // check to see if this is a new file
        let metadata = try!(file.metadata());

        if metadata.len() == 0 {
            // write out our header
            try!(file.write(FILE_HEADER.as_bytes()));
            // write out our version
            try!(file.write(&[CURRENT_VERSION]));

            Ok(BTree{fd: file, key_size: key_size, value_size: value_size, root: None})
        } else {
            // make sure we've opened a proper file
            let mut version_string = Vec::with_capacity(8);

            try!(file.read_exact(&mut version_string));

            if try!(str::from_utf8(&version_string[0..FILE_HEADER.len()])) != FILE_HEADER ||
               version_string[FILE_HEADER.len()] != CURRENT_VERSION {
                return Err(From::from(std::io::Error::new(ErrorKind::InvalidData, "Invalid BTree file version")));
            }

            // total size of a Node
            let total_size = key_size + size_of::<u64>() + max(value_size, (key_size+size_of::<u64>()) * NUM_CHILDREN);
            let mut buff = Vec::with_capacity(total_size);

            // seek total_size in from the end of the file to read the root node
            try!(file.seek(SeekFrom::End(total_size as i64)));
            try!(file.read_exact(&mut buff));

            let root_node: Node<K,V> = try!(decode(&buff[..]));

            Ok(BTree{fd: file, key_size: key_size, value_size: value_size, root: Some(root_node)})
        }
    }
}

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        println!("It works!!!")
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::{io, mem, ptr, slice};

pub fn write<W: io::Write, V: Integer>(wr: &mut W, value: V) -> io::Result<()> {
    value.write(wr)
}

pub trait Integer {
    fn write<W: io::Write>(self, &mut W) -> io::Result<()>;
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => ($(
    impl Integer for $t {
        #[allow(unused_comparisons)]
        fn write<W: io::Write>(self, wr: &mut W) -> io::Result<()> {
            let is_nonnegative = self >= 0;
            let mut n = if is_nonnegative {
                self as $conv_fn
            } else {
                try!(wr.write_all(b"-"));
                // convert the negative num to positive by summing 1 to it's 2 complement
                (!(self as $conv_fn)).wrapping_add(1)
            };
            let mut buf: [u8; 20] = unsafe { mem::uninitialized() };
            let mut curr = buf.len() as isize;
            let buf_ptr = buf.as_mut_ptr();
            let lut_ptr = DEC_DIGITS_LUT.as_ptr();

            unsafe {
                // eagerly decode 4 characters at a time
                if <$t>::max_value() as u64 >= 10000 {
                    while n >= 10000 {
                        let rem = (n % 10000) as isize;
                        n /= 10000;

                        let d1 = (rem / 100) << 1;
                        let d2 = (rem % 100) << 1;
                        curr -= 4;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                        ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                    }
                }

                // if we reach here numbers are <= 9999, so at most 4 chars long
                let mut n = n as isize; // possibly reduce 64bit math

                // decode 2 more chars, if > 2 chars
                if n >= 100 {
                    let d1 = (n % 100) << 1;
                    n /= 100;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                // decode last 1 or 2 chars
                if n < 10 {
                    curr -= 1;
                    *buf_ptr.offset(curr) = (n as u8) + 48;
                } else {
                    let d1 = n << 1;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }
            }

            wr.write_all(unsafe {
                slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize)
            })
        }
    })*);
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);
<commit_msg>Inline itoa::write<commit_after>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::{io, mem, ptr, slice};

#[inline]
pub fn write<W: io::Write, V: Integer>(wr: &mut W, value: V) -> io::Result<()> {
    value.write(wr)
}

pub trait Integer {
    fn write<W: io::Write>(self, &mut W) -> io::Result<()>;
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_Integer {
    ($($t:ident),* as $conv_fn:ident) => ($(
    impl Integer for $t {
        #[allow(unused_comparisons)]
        fn write<W: io::Write>(self, wr: &mut W) -> io::Result<()> {
            let is_nonnegative = self >= 0;
            let mut n = if is_nonnegative {
                self as $conv_fn
            } else {
                try!(wr.write_all(b"-"));
                // convert the negative num to positive by summing 1 to it's 2 complement
                (!(self as $conv_fn)).wrapping_add(1)
            };
            let mut buf: [u8; 20] = unsafe { mem::uninitialized() };
            let mut curr = buf.len() as isize;
            let buf_ptr = buf.as_mut_ptr();
            let lut_ptr = DEC_DIGITS_LUT.as_ptr();

            unsafe {
                // eagerly decode 4 characters at a time
                if <$t>::max_value() as u64 >= 10000 {
                    while n >= 10000 {
                        let rem = (n % 10000) as isize;
                        n /= 10000;

                        let d1 = (rem / 100) << 1;
                        let d2 = (rem % 100) << 1;
                        curr -= 4;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                        ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                    }
                }

                // if we reach here numbers are <= 9999, so at most 4 chars long
                let mut n = n as isize; // possibly reduce 64bit math

                // decode 2 more chars, if > 2 chars
                if n >= 100 {
                    let d1 = (n % 100) << 1;
                    n /= 100;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }

                // decode last 1 or 2 chars
                if n < 10 {
                    curr -= 1;
                    *buf_ptr.offset(curr) = (n as u8) + 48;
                } else {
                    let d1 = n << 1;
                    curr -= 2;
                    ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                }
            }

            wr.write_all(unsafe {
                slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize)
            })
        }
    })*);
}

impl_Integer!(i8, u8, i16, u16, i32, u32 as u32);
impl_Integer!(i64, u64 as u64);
#[cfg(target_pointer_width = "16")]
impl_Integer!(isize, usize as u16);
#[cfg(target_pointer_width = "32")]
impl_Integer!(isize, usize as u32);
#[cfg(target_pointer_width = "64")]
impl_Integer!(isize, usize as u64);
<|endoftext|>


<commit_before>//! A crate with utilities to determine the number of CPUs available on the
//! current system.
//!
//! Sometimes the CPU will exaggerate the number of CPUs it contains, because it can use
//! [processor tricks] to deliver increased performance when there are more threads. This
//! crate provides methods to get both the logical and physical numbers of cores.
//!
//! This information can be used as a guide to how many tasks can be run in parallel.
//! There are many properties of the system architecture that will affect parallelism,
//! for example memory access speeds (for all the caches and RAM) and the physical
//! architecture of the processor, so the number of CPUs should be used as a rough guide
//! only.
//!
//!
//! ## Examples
//!
//! Fetch the number of logical CPUs.
//!
//! ```
//! let cpus = num_cpus::get();
//! ```
//!
//! See [`rayon::Threadpool`] for an example of where the number of CPUs could be
//! used when setting up parallel jobs (Where the threadpool example uses a fixed
//! number 8, it could use the number of CPUs).
//!
//! [processor tricks]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
//! [`rayon::ThreadPool`]: https://docs.rs/rayon/0.8.2/rayon/struct.ThreadPool.html
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/num_cpus/1.7.0")]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of available CPUs of the current system.
///
/// This function will get the number of logical cores. Sometimes this is different from the number
/// of physical cores (See [Simultaneous multithreading on Wikipedia][smt]).
///
/// # Examples
///
/// ```
/// let cpus = num_cpus::get();
/// if cpus > 1 {
///     println!("We are on a multicore system with {} CPUs", cpus);
/// } else {
///     println!("We are on a single core system");
/// }
/// ```
///
/// # Note
///
/// This will check [sched affinity] on Linux, showing a lower number of CPUs if the current
/// thread does not have access to all the computer's CPUs.
///
/// [smt]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
/// [sched affinity]: http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current system.
///
/// # Note
///
/// Physical count is supported only on Linux, mac OS and Windows platforms.
/// On other platforms, or if the physical count fails on supported platforms,
/// this function returns the same as [`get()`], which is the number of logical
/// CPUS.
///
/// # Examples
///
/// ```
/// let logical_cpus = num_cpus::get();
/// let physical_cpus = num_cpus::get_physical();
/// if logical_cpus > physical_cpus {
///     println!("We have simultaneous multithreading with about {:.2} \
///               logical cores to 1 physical core.",
///               (logical_cpus as f64) / (physical_cpus as f64));
/// } else if logical_cpus == physical_cpus {
///     println!("Either we don't have simultaneous multithreading, or our \
///               system doesn't support getting the number of physical CPUs.");
/// } else {
///     println!("We have less logical CPUs than physical CPUs, maybe we only have access to \
///               some of the CPUs on our system.");
/// }
/// ```
///
/// [`get()`]: fn.get.html
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(any(target_os = "linux", target_os = "windows", target_os="macos")))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fallback
    get_num_cpus()
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus() -> usize {
    match get_num_physical_cpus_windows() {
        Some(num) => num,
        None => get_num_cpus()
    }
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus_windows() -> Option<usize> {
    // Inspired by https://msdn.microsoft.com/en-us/library/ms683194

    use std::ptr;
    use std::mem;

    #[allow(non_upper_case_globals)]
    const RelationProcessorCore: u32 = 0;

    #[repr(C)]
    #[allow(non_camel_case_types)]
    struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
        mask: usize,
        relationship: u32,
        _unused: [u64; 2]
    }

    extern "system" {
        fn GetLogicalProcessorInformation(
            info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
            length: &mut u32
        ) -> u32;
    }

    // First we need to determine how much space to reserve.

    // The required size of the buffer, in bytes.
    let mut needed_size = 0;

    unsafe {
        GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
    }

    let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;

    // Could be 0, or some other bogus size.
    if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
        return None;
    }

    let count = needed_size / struct_size;

    // Allocate some memory where we will store the processor info.
    let mut buf = Vec::with_capacity(count as usize);

    let result;

    unsafe {
        result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
    }

    // Failed for any reason.
    if result == 0 {
        return None;
    }

    let count = needed_size / struct_size;

    unsafe {
        buf.set_len(count as usize);
    }

    let phys_proc_count = buf.iter()
        // Only interested in processor packages (physical processors.)
        .filter(|proc_info| proc_info.relationship == RelationProcessorCore)
        .count();

    if phys_proc_count == 0 {
        None
    } else {
        Some(phys_proc_count)
    }
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashSet;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut set = HashSet::new();
    let mut coreid: u32 = 0;
    let mut physid: u32 = 0;
    let mut chgcount = 0;
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" || parts[0] == "physical id" {
            let value = match parts[1].trim().parse() {
              Ok(val) => val,
              Err(_) => break,
            };
            match parts[0] {
                "core id"     => coreid = value,
                "physical id" => physid = value,
                _ => {},
            }
            chgcount += 1;
        }
        if chgcount == 2 {
            set.insert((physid, coreid));
            chgcount = 0;
        }
    }
    let count = set.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "macos")]
fn get_num_physical_cpus() -> usize {
    use std::ffi::CStr;
    use std::ptr;

    let mut cpus: i32 = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    let sysctl_name = CStr::from_bytes_with_nul(b"hw.physicalcpu\0")
        .expect("byte literal is missing NUL");

    unsafe {
        if 0 != libc::sysctlbyname(sysctl_name.as_ptr(),
                                   &mut cpus as *mut _ as *mut _,
                                   &mut cpus_size as *mut _ as *mut _,
                                   ptr::null_mut(),
                                   0) {
            return get_num_cpus();
        }
    }
    cpus as usize
}

#[cfg(target_os = "linux")]
fn get_num_cpus() -> usize {
    let mut set:  libc::cpu_set_t = unsafe { std::mem::zeroed() };
    if unsafe { libc::sched_getaffinity(0, std::mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
        let mut count: u32 = 0;
        for i in 0..libc::CPU_SETSIZE as usize {
            if unsafe { libc::CPU_ISSET(i, &set) } {
                count += 1
            }
        }
        count as usize
    } else {
        let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
        if cpus < 1 {
            1
        } else {
            cpus as usize
        }
    }
}

#[cfg(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "fuchsia")
)]
fn get_num_cpus() -> usize {
    // On ARM targets, processors could be turned off to save power.
    // Use `_SC_NPROCESSORS_CONF` to get the real number.
    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_CONF;
    #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_ONLN;

    let cpus = unsafe { libc::sysconf(CONF_NAME) };
    if cpus < 1 {
        1
    } else {
        cpus as usize
    }
}

#[cfg(any(target_os = "emscripten", target_os = "redox", target_os = "haiku"))]
fn get_num_cpus() -> usize {
    1
}

#[cfg(test)]
mod tests {
    fn env_var(name: &'static str) -> Option<usize> {
        ::std::env::var(name).ok().map(|val| val.parse().unwrap())
    }

    #[test]
    fn test_get() {
        let num = super::get();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }

    #[test]
    fn test_get_physical() {
        let num = super::get_physical();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }
}
<commit_msg>Change `fallback` to `fall back`<commit_after>//! A crate with utilities to determine the number of CPUs available on the
//! current system.
//!
//! Sometimes the CPU will exaggerate the number of CPUs it contains, because it can use
//! [processor tricks] to deliver increased performance when there are more threads. This
//! crate provides methods to get both the logical and physical numbers of cores.
//!
//! This information can be used as a guide to how many tasks can be run in parallel.
//! There are many properties of the system architecture that will affect parallelism,
//! for example memory access speeds (for all the caches and RAM) and the physical
//! architecture of the processor, so the number of CPUs should be used as a rough guide
//! only.
//!
//!
//! ## Examples
//!
//! Fetch the number of logical CPUs.
//!
//! ```
//! let cpus = num_cpus::get();
//! ```
//!
//! See [`rayon::Threadpool`] for an example of where the number of CPUs could be
//! used when setting up parallel jobs (Where the threadpool example uses a fixed
//! number 8, it could use the number of CPUs).
//!
//! [processor tricks]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
//! [`rayon::ThreadPool`]: https://docs.rs/rayon/0.8.2/rayon/struct.ThreadPool.html
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/num_cpus/1.7.0")]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of available CPUs of the current system.
///
/// This function will get the number of logical cores. Sometimes this is different from the number
/// of physical cores (See [Simultaneous multithreading on Wikipedia][smt]).
///
/// # Examples
///
/// ```
/// let cpus = num_cpus::get();
/// if cpus > 1 {
///     println!("We are on a multicore system with {} CPUs", cpus);
/// } else {
///     println!("We are on a single core system");
/// }
/// ```
///
/// # Note
///
/// This will check [sched affinity] on Linux, showing a lower number of CPUs if the current
/// thread does not have access to all the computer's CPUs.
///
/// [smt]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
/// [sched affinity]: http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current system.
///
/// # Note
///
/// Physical count is supported only on Linux, mac OS and Windows platforms.
/// On other platforms, or if the physical count fails on supported platforms,
/// this function returns the same as [`get()`], which is the number of logical
/// CPUS.
///
/// # Examples
///
/// ```
/// let logical_cpus = num_cpus::get();
/// let physical_cpus = num_cpus::get_physical();
/// if logical_cpus > physical_cpus {
///     println!("We have simultaneous multithreading with about {:.2} \
///               logical cores to 1 physical core.",
///               (logical_cpus as f64) / (physical_cpus as f64));
/// } else if logical_cpus == physical_cpus {
///     println!("Either we don't have simultaneous multithreading, or our \
///               system doesn't support getting the number of physical CPUs.");
/// } else {
///     println!("We have less logical CPUs than physical CPUs, maybe we only have access to \
///               some of the CPUs on our system.");
/// }
/// ```
///
/// [`get()`]: fn.get.html
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(any(target_os = "linux", target_os = "windows", target_os="macos")))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fall back
    get_num_cpus()
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus() -> usize {
    match get_num_physical_cpus_windows() {
        Some(num) => num,
        None => get_num_cpus()
    }
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus_windows() -> Option<usize> {
    // Inspired by https://msdn.microsoft.com/en-us/library/ms683194

    use std::ptr;
    use std::mem;

    #[allow(non_upper_case_globals)]
    const RelationProcessorCore: u32 = 0;

    #[repr(C)]
    #[allow(non_camel_case_types)]
    struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
        mask: usize,
        relationship: u32,
        _unused: [u64; 2]
    }

    extern "system" {
        fn GetLogicalProcessorInformation(
            info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
            length: &mut u32
        ) -> u32;
    }

    // First we need to determine how much space to reserve.

    // The required size of the buffer, in bytes.
    let mut needed_size = 0;

    unsafe {
        GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
    }

    let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;

    // Could be 0, or some other bogus size.
    if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
        return None;
    }

    let count = needed_size / struct_size;

    // Allocate some memory where we will store the processor info.
    let mut buf = Vec::with_capacity(count as usize);

    let result;

    unsafe {
        result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
    }

    // Failed for any reason.
    if result == 0 {
        return None;
    }

    let count = needed_size / struct_size;

    unsafe {
        buf.set_len(count as usize);
    }

    let phys_proc_count = buf.iter()
        // Only interested in processor packages (physical processors.)
        .filter(|proc_info| proc_info.relationship == RelationProcessorCore)
        .count();

    if phys_proc_count == 0 {
        None
    } else {
        Some(phys_proc_count)
    }
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashSet;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut set = HashSet::new();
    let mut coreid: u32 = 0;
    let mut physid: u32 = 0;
    let mut chgcount = 0;
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" || parts[0] == "physical id" {
            let value = match parts[1].trim().parse() {
              Ok(val) => val,
              Err(_) => break,
            };
            match parts[0] {
                "core id"     => coreid = value,
                "physical id" => physid = value,
                _ => {},
            }
            chgcount += 1;
        }
        if chgcount == 2 {
            set.insert((physid, coreid));
            chgcount = 0;
        }
    }
    let count = set.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "macos")]
fn get_num_physical_cpus() -> usize {
    use std::ffi::CStr;
    use std::ptr;

    let mut cpus: i32 = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    let sysctl_name = CStr::from_bytes_with_nul(b"hw.physicalcpu\0")
        .expect("byte literal is missing NUL");

    unsafe {
        if 0 != libc::sysctlbyname(sysctl_name.as_ptr(),
                                   &mut cpus as *mut _ as *mut _,
                                   &mut cpus_size as *mut _ as *mut _,
                                   ptr::null_mut(),
                                   0) {
            return get_num_cpus();
        }
    }
    cpus as usize
}

#[cfg(target_os = "linux")]
fn get_num_cpus() -> usize {
    let mut set:  libc::cpu_set_t = unsafe { std::mem::zeroed() };
    if unsafe { libc::sched_getaffinity(0, std::mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
        let mut count: u32 = 0;
        for i in 0..libc::CPU_SETSIZE as usize {
            if unsafe { libc::CPU_ISSET(i, &set) } {
                count += 1
            }
        }
        count as usize
    } else {
        let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
        if cpus < 1 {
            1
        } else {
            cpus as usize
        }
    }
}

#[cfg(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "fuchsia")
)]
fn get_num_cpus() -> usize {
    // On ARM targets, processors could be turned off to save power.
    // Use `_SC_NPROCESSORS_CONF` to get the real number.
    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_CONF;
    #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_ONLN;

    let cpus = unsafe { libc::sysconf(CONF_NAME) };
    if cpus < 1 {
        1
    } else {
        cpus as usize
    }
}

#[cfg(any(target_os = "emscripten", target_os = "redox", target_os = "haiku"))]
fn get_num_cpus() -> usize {
    1
}

#[cfg(test)]
mod tests {
    fn env_var(name: &'static str) -> Option<usize> {
        ::std::env::var(name).ok().map(|val| val.parse().unwrap())
    }

    #[test]
    fn test_get() {
        let num = super::get();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }

    #[test]
    fn test_get_physical() {
        let num = super::get_physical();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }
}
<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(step_by)]
#![feature(test)]
#![feature(core)]
#![feature(rand)]

#[cfg(test)] extern crate test;

mod cryptoutil;
mod md5;

pub use md5::Md5;
<commit_msg>slice_bytes feature<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(step_by)]
#![feature(slice_bytes)]
#![feature(test)]
#![feature(rand)]

#[cfg(test)] extern crate test;

mod cryptoutil;
mod md5;

pub use md5::Md5;
<|endoftext|>


<commit_before>/*!
Provides a very bare-bones way of having custom `derive` support in stable Rust.
*/
#[macro_export]
macro_rules! custom_derive {
    (
        $(#[$($attrs:tt)*])*
        enum $($it:tt)*
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*), (), (),
            (enum $($it)*)
        }
    };

    (
        $(#[$($attrs:tt)*])*
        pub $($it:tt)*
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*), (), (),
            (pub $($it)*)
        }
    };

    (
        $(#[$($attrs:tt)*])*
        struct $($it:tt)*
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*), (), (),
            (struct $($it)*)
        }
    };

    (@as_item $($i:item)*) => {$($i)*};

    (
        @split_attrs
        (),
        $non_derives:tt,
        $derives:tt,
        $it:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            { $non_derives, $it },
            $derives,
            (),
            ()
        }
    };

    (
        @split_attrs
        (#[derive($($new_drv:ident $(($($new_drv_args:tt)*))*),*)], $(#[$($attrs:tt)*],)*),
        $non_derives:tt,
        ($($derives:ident,)*),
        $it:tt
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*),
            $non_derives,
            ($($derives,)* $(#[$new_drv $(($($new_drv_args)*))*],)*),
            $it
        }
    };

    (
        @split_attrs
        (#[$new_attr:meta], $(#[$($attrs:tt)*],)*),
        ($($non_derives:tt)*),
        $derives:tt,
        $it:tt
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*),
            ($($non_derives)* #[$new_attr],),
            $derives,
            $it
        }
    };

    /*
    Built-in derives:
        Clone, Hash, RustcEncodable, RustcDecodable, PartialEq, Eq, PartialOrd, Ord,
        Debug, Default, Send, Sync, Copy,
    */

    (@split_derive_attrs
        { ($(#[$($non_derives:tt)*],)*), ($($it:tt)*) },
        (), ($($bi_drvs:ident,)*), ($($user_drvs:tt)*)
    ) => {
        custom_derive! {
            @as_item
            #[derive($($bi_drvs,)*)]
            $(#[$($non_derives)*])*
            $($it)*
        }

        custom_derive! {
            @expand_user_drvs
            ($($user_drvs)*), ($($it)*)
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[Clone], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Clone,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[RustcEncodable], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* RustcEncodable,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[RustcDecodable], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* RustcDecodable,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[PartialEq], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* PartialEq,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[Eq], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Eq,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[PartialOrd], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* PartialOrd,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[Ord], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Ord,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[Debug], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Debug,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[Default], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Default,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[Send], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Send,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[Sync], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Sync,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[Copy], $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Copy,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[$new_user:tt], $($tail:tt)*), $bi_drvs:tt, ($($user_drvs:ident,)*)
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed, ($($tail)*), $bi_drvs, ($($user_drvs,)* $new_user(),)
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (#[$new_user:tt ($($new_user_args:tt)*)], $($tail:tt)*), $bi_drvs:tt, ($($user_drvs:ident,)*)
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed, ($($tail)*), $bi_drvs, ($($user_drvs,)* $new_user($($new_user_args)*),)
        }
    };

    (@expand_user_drvs
        (), ($($it:tt)*)
    ) => {};

    (@expand_user_drvs
        ($user_drv:ident $args:tt, $($tail:ident,)*), ($($it:tt)*)
    ) => {
        $user_drv! { $args $($it)* }
        custom_derive! {
            @expand_user_drvs
            ($($tail)*), ($($it)*)
        }
    };
}
<commit_msg>Fixed parsing of custom derivation attributes.<commit_after>/*!
Provides a very bare-bones way of having custom `derive` support in stable Rust.
*/
#[macro_export]
macro_rules! custom_derive {
    (
        $(#[$($attrs:tt)*])*
        enum $($it:tt)*
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*), (), (),
            (enum $($it)*)
        }
    };

    (
        $(#[$($attrs:tt)*])*
        pub $($it:tt)*
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*), (), (),
            (pub $($it)*)
        }
    };

    (
        $(#[$($attrs:tt)*])*
        struct $($it:tt)*
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*), (), (),
            (struct $($it)*)
        }
    };

    (@as_item $($i:item)*) => {$($i)*};

    (
        @split_attrs
        (),
        $non_derives:tt,
        $derives:tt,
        $it:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            { $non_derives, $it },
            $derives,
            (),
            ()
        }
    };

    (
        @split_attrs
        (#[derive($($new_drv:ident $(($($new_drv_args:tt)*))*),*)], $(#[$($attrs:tt)*],)*),
        $non_derives:tt,
        ($($derives:ident,)*),
        $it:tt
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*),
            $non_derives,
            ($($derives,)* $($new_drv $(($($new_drv_args)*))*,)*),
            $it
        }
    };

    (
        @split_attrs
        (#[$new_attr:meta], $(#[$($attrs:tt)*],)*),
        ($($non_derives:tt)*),
        $derives:tt,
        $it:tt
    ) => {
        custom_derive! {
            @split_attrs
            ($(#[$($attrs)*],)*),
            ($($non_derives)* #[$new_attr],),
            $derives,
            $it
        }
    };

    /*
    Built-in derives:
        Clone, Hash, RustcEncodable, RustcDecodable, PartialEq, Eq, PartialOrd, Ord,
        Debug, Default, Send, Sync, Copy,
    */

    (@split_derive_attrs
        { ($(#[$($non_derives:tt)*],)*), ($($it:tt)*) },
        (), ($($bi_drvs:ident,)*), ($($user_drvs:tt)*)
    ) => {
        custom_derive! {
            @as_item
            #[derive($($bi_drvs,)*)]
            $(#[$($non_derives)*])*
            $($it)*
        }

        custom_derive! {
            @expand_user_drvs
            ($($user_drvs)*), ($($it)*)
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (Clone, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Clone,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (RustcEncodable, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* RustcEncodable,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (RustcDecodable, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* RustcDecodable,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (PartialEq, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* PartialEq,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (Eq, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Eq,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (PartialOrd, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* PartialOrd,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (Ord, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Ord,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (Debug, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Debug,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (Default, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Default,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (Send ,$($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Send,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (Sync, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Sync,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        (Copy, $($tail:tt)*), ($($bi_drvs:ident,)*), $user_drvs:tt
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed,
            ($($tail)*), ($($bi_drvs,)* Copy,), $user_drvs
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        ($new_user:ident, $($tail:tt)*), $bi_drvs:tt, ($($user_drvs:tt)*)
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed, ($($tail)*), $bi_drvs, ($($user_drvs)* $new_user(),)
        }
    };

    (@split_derive_attrs
        $fixed:tt,
        ($new_user:ident ($($new_user_args:tt)*), $($tail:tt)*), $bi_drvs:tt, ($($user_drvs:tt)*)
    ) => {
        custom_derive! {
            @split_derive_attrs
            $fixed, ($($tail)*), $bi_drvs, ($($user_drvs)* $new_user($($new_user_args)*),)
        }
    };

    (@expand_user_drvs
        (), ($($it:tt)*)
    ) => {};

    (@expand_user_drvs
        ($user_drv:ident $arg:tt, $($tail:tt)*), ($($it:tt)*)
    ) => {
        $user_drv! { $arg $($it)* }
        custom_derive! {
            @expand_user_drvs
            ($($tail)*), ($($it)*)
        }
    };
}
<|endoftext|>


<commit_before>
#![doc="A generics based scientific computing library for Rust

# Introduction

This library aims to provide scientific computing functionality in Rust.
Current focus is to provide a comprehensive API with simple straight-forward
implementations. Different modules cover functionality
covering matrices, linear algebra, signal processing and statistics.

# Implementation

The implementation's aim to take the best advantage
of language features in Rust, yet avoid getting too much into
heavy degree of performance optimization. We do take
advantage of Rust features like generic programming,
immutable by default approach, type traits, iterators,
amongst others. This is a pure Rust implementation.
There is no integration planned at the moment with
C libraries like BLAS or LAPACK.

"]

#![feature(unsafe_destructor, globs)]
#![feature(phase)]
#[phase(plugin, link)] extern crate log;

pub mod entry;
pub mod number;
pub mod error;

pub mod discrete{
    #![doc="Discrete mathematics
    "]

    pub use self::modular::*;
    //pub use self::permutations::*;

    mod modular;
    pub mod permutations;

}

pub mod matrix {
    #![doc="Fundamental matrix structures
    "]
    pub use super::number::*;
    pub use super::error::*;
    pub use self::constructors::*;
    pub use self::iter::*;
    pub use self::matrix::*;
    pub use self::matrix_conversion::*;
    pub use self::matrix_minmax::*;
    pub use self::random::*;
    pub use self::traits::*;
    pub use self::view::*;
    pub use self::view_conversion::*;
    pub use self::view_minmax::*;
    pub use self::triangular_matrix::*;

    mod constructors;
    mod iter;
    mod matrix;
    mod matrix_conversion;
    mod matrix_minmax;
    mod random;
    pub mod traits;
    mod view;
    mod view_conversion;
    mod view_minmax;
    mod triangular_matrix;
}

pub mod linalg {
    #![doc="Linear algebra algorithms
    "]
    pub use self::linear_system::*;
    pub use self::det::*;
    pub use self::lu::*;
    pub use super::error::*;
    pub use self::singularity::*;
    pub use self::inverse::*;
    pub use self::rank::*;

    mod linear_system;
    mod det;
    mod lu;
    mod singularity;
    mod inverse;
    mod rank;

}

pub mod stat {
    #![doc="Statistics
    "]
}

pub mod opt {
    #![doc="Optimization
    "]
    pub mod lp {
    #![doc="Linear programming
    "]
    }
    pub mod ls {
    #![doc="Least squares
    "]
    }
    pub mod cvx {
    #![doc="Convex optimization
    "]
    }
}

pub mod signal {
    #![doc="Signal processing
    "]
    pub use self::signal::*;
    mod signal;
}

pub mod image {
#![doc="Image processing
"]
}

pub mod audio {
#![doc="Audio signal processing
"]
}

pub mod dx {
#![doc="Data exchange

This module and its submodules intend to provide
functions for exchanging scientific data in different
formats.

Initial targets are:

* HDF (Hierarchical Data Format)
* MAT (MATLAB format)

# Remarks

At the moment, the graphics capabilities
do not exist within SciRust. In order
to create graphics, one needs to write
data generated in a SciRust program
and save it in a suitable format
so that it can be imported in systems like
SciPy etc. The graphics facilities of those
systems can then be used.

"]

}

pub mod external{
#![doc="External code.

This module holds external code picked up from outside
sources till a more formal solution is found.

# Contents

## complex.rs

Rust code base has a complex.rs file but it is not yet
part of Standard Library. Using the file as it is
in the code base. When Rust provides built-in support
for complex numbers, then this library will be removed.

"]

pub mod complex;

}

// for internal use only
pub mod util{

    pub mod memory;
}

// for internal use only
mod testdata{

    #[cfg(test)]
    pub mod matrix {

        pub use self::simple::*;

        mod simple;

    }
}
<commit_msg>addition of new modules.<commit_after>
#![doc="A generics based scientific computing library for Rust

# Introduction

This library aims to provide scientific computing functionality in Rust.
Current focus is to provide a comprehensive API with simple straight-forward
implementations. Different modules cover functionality
covering matrices, linear algebra, signal processing and statistics.

# Implementation

The implementation's aim to take the best advantage
of language features in Rust, yet avoid getting too much into
heavy degree of performance optimization. We do take
advantage of Rust features like generic programming,
immutable by default approach, type traits, iterators,
amongst others. This is a pure Rust implementation.
There is no integration planned at the moment with
C libraries like BLAS or LAPACK.

"]

#![feature(unsafe_destructor, globs)]
#![feature(phase)]
#[phase(plugin, link)] extern crate log;

pub mod entry;
pub mod number;
pub mod error;

pub mod discrete{
    #![doc="Discrete mathematics
    "]

    pub use self::modular::*;
    //pub use self::permutations::*;

    mod modular;
    pub mod permutations;

}

pub mod matrix {
    #![doc="Fundamental matrix structures
    "]
    pub use super::number::*;
    pub use super::error::*;
    pub use self::constructors::*;
    pub use self::iter::*;
    pub use self::matrix::*;
    pub use self::matrix_conversion::*;
    pub use self::matrix_minmax::*;
    pub use self::random::*;
    pub use self::traits::*;
    pub use self::view::*;
    pub use self::view_conversion::*;
    pub use self::view_minmax::*;
    pub use self::triangular_matrix::*;
    pub use self::vector::*;

    mod constructors;
    mod iter;
    pub mod matrix;
    mod matrix_conversion;
    mod matrix_minmax;
    mod random;
    pub mod traits;
    pub mod vector;
    mod view;
    mod view_conversion;
    mod view_minmax;
    mod triangular_matrix;
}

pub mod linalg {
    #![doc="Linear algebra algorithms
    "]
    pub use self::linear_system::*;
    pub use self::det::*;
    pub use self::lu::*;
    pub use super::error::*;
    pub use self::singularity::*;
    pub use self::inverse::*;
    pub use self::rank::*;

    mod linear_system;
    mod det;
    mod lu;
    mod singularity;
    mod inverse;
    mod rank;

}

pub mod stat {
    #![doc="Statistics
    "]
}

pub mod opt {
    #![doc="Optimization
    "]
    pub mod lp {
    #![doc="Linear programming
    "]
    }
    pub mod ls {
    #![doc="Least squares
    "]
    }
    pub mod cvx {
    #![doc="Convex optimization
    "]
    }
}

pub mod signal {
    #![doc="Signal processing
    "]
    pub use self::signal::*;
    mod signal;
}

pub mod image {
#![doc="Image processing
"]
}

pub mod audio {
#![doc="Audio signal processing
"]
}

pub mod dx {
#![doc="Data exchange

This module and its submodules intend to provide
functions for exchanging scientific data in different
formats.

Initial targets are:

* HDF (Hierarchical Data Format)
* MAT (MATLAB format)

# Remarks

At the moment, the graphics capabilities
do not exist within SciRust. In order
to create graphics, one needs to write
data generated in a SciRust program
and save it in a suitable format
so that it can be imported in systems like
SciPy etc. The graphics facilities of those
systems can then be used.

"]

}

pub mod external{
#![doc="External code.

This module holds external code picked up from outside
sources till a more formal solution is found.

# Contents

## complex.rs

Rust code base has a complex.rs file but it is not yet
part of Standard Library. Using the file as it is
in the code base. When Rust provides built-in support
for complex numbers, then this library will be removed.

"]

pub mod complex;

}

// for internal use only
pub mod util{

    pub mod memory;
    pub mod slice_vec_conversion;
}

// for internal use only
mod testdata{

    #[cfg(test)]
    pub mod matrix {

        pub use self::simple::*;

        mod simple;

    }
}
<|endoftext|>


<commit_before>extern crate conduit;
extern crate "mime-types" as mime;
extern crate time;

use std::fmt::Show;
use std::collections::HashMap;
use std::io;
use std::io::fs::File;
use std::io::util::NullReader;
use conduit::{Request, Response, Handler};

pub struct Static {
    path: Path,
    types: mime::Types
}

impl Static {
    pub fn new(path: Path) -> Static {
        Static {
            path: path,
            types: mime::Types::new()
                .ok().expect("Couldn't load mime-types")
        }
    }
}

impl Handler for Static {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show + 'static>> {
        let request_path = request.path().slice_from(1);
        let path = self.path.join(request_path);

        if !self.path.is_ancestor_of(&path) {
            return Ok(not_found())
        }

        let mime = self.types.mime_for_path(&path);
        let mut file = match File::open(&path) {
            Ok(f) => f,
            Err(..) => return Ok(not_found()),
        };
        let stat = try!(file.stat().map_err(|e| box e as Box<Show>));
        match stat.kind {
            io::TypeDirectory => return Ok(not_found()),
            _ => {}
        }
        let ts = time::Timespec {
            sec: (stat.modified as i64) / 1000,
            nsec: (((stat.modified as u32) % 1000) as i32) * 1000000
        };
        let tm = time::at(ts).to_utc();

        let mut headers = HashMap::new();
        headers.insert("Content-Type".to_string(), vec![mime.to_string()]);
        headers.insert("Content-Length".to_string(), vec![stat.size.to_string()]);
        headers.insert("Last-Modified".to_string(),
                       vec![tm.strftime("%a, %d %b %Y %T GMT").unwrap()
                              .to_string()]);

        Ok(Response {
            status: (200, "OK"),
            headers: headers,
            body: box file as Box<Reader + Send>
        })
    }
}

fn not_found() -> Response {
    Response {
        status: (404, "Not Found"),
        headers: HashMap::new(),
        body: box NullReader,
    }
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as test;

    use std::io::{fs, File, TempDir, USER_RWX};

    use conduit;
    use conduit::Handler;
    use Static;

    #[test]
    fn test_static() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        let handler = Static::new(root.clone());
        File::create(&root.join("Cargo.toml")).write(b"[package]").unwrap();
        let mut req = test::MockRequest::new(conduit::Get, "/Cargo.toml");
        let mut res = handler.call(&mut req).ok().expect("No response");
        let body = res.body.read_to_string().ok().expect("No body");
        assert_eq!(body.as_slice(), "[package]");
        assert_eq!(res.headers.get("Content-Type"),
                   Some(&vec!("text/plain".to_string())));
        assert_eq!(res.headers.get("Content-Length"),
                   Some(&vec!["9".to_string()]));
    }

    #[test]
    fn test_mime_types() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        fs::mkdir(&root.join("src"), USER_RWX).unwrap();
        File::create(&root.join("src/fixture.css")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/src/fixture.css");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.headers.get("Content-Type"),
                   Some(&vec!("text/css".to_string())));
        assert_eq!(res.headers.get("Content-Length"),
                   Some(&vec!["0".to_string()]));
    }

    #[test]
    fn test_missing() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/nope");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 404);
    }

    #[test]
    fn test_dir() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        fs::mkdir(&root.join("foo"), USER_RWX).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/foo");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 404);
    }

    #[test]
    fn last_modified() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        File::create(&root.join("test")).unwrap();
        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(conduit::Get, "/test");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 200);
        assert!(res.headers.get("Last-Modified").is_some());
    }
}
<commit_msg>Update to rust master<commit_after>extern crate conduit;
extern crate "mime-types" as mime;
extern crate time;

use std::fmt::Show;
use std::collections::HashMap;
use std::io::FileType;
use std::io::fs::File;
use std::io::util::NullReader;
use conduit::{Request, Response, Handler};

pub struct Static {
    path: Path,
    types: mime::Types
}

impl Static {
    pub fn new(path: Path) -> Static {
        Static {
            path: path,
            types: mime::Types::new()
                .ok().expect("Couldn't load mime-types")
        }
    }
}

impl Handler for Static {
    fn call(&self, request: &mut Request) -> Result<Response, Box<Show + 'static>> {
        let request_path = request.path().slice_from(1);
        let path = self.path.join(request_path);

        if !self.path.is_ancestor_of(&path) {
            return Ok(not_found())
        }

        let mime = self.types.mime_for_path(&path);
        let mut file = match File::open(&path) {
            Ok(f) => f,
            Err(..) => return Ok(not_found()),
        };
        let stat = try!(file.stat().map_err(|e| box e as Box<Show>));
        match stat.kind {
            FileType::Directory => return Ok(not_found()),
            _ => {}
        }
        let ts = time::Timespec {
            sec: (stat.modified as i64) / 1000,
            nsec: (((stat.modified as u32) % 1000) as i32) * 1000000
        };
        let tm = time::at(ts).to_utc();

        let mut headers = HashMap::new();
        headers.insert("Content-Type".to_string(), vec![mime.to_string()]);
        headers.insert("Content-Length".to_string(), vec![stat.size.to_string()]);
        headers.insert("Last-Modified".to_string(),
                       vec![tm.strftime("%a, %d %b %Y %T GMT").unwrap()
                              .to_string()]);

        Ok(Response {
            status: (200, "OK"),
            headers: headers,
            body: box file as Box<Reader + Send>
        })
    }
}

fn not_found() -> Response {
    Response {
        status: (404, "Not Found"),
        headers: HashMap::new(),
        body: box NullReader,
    }
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as test;

    use std::io::{fs, File, TempDir, USER_RWX};

    use conduit::{Handler, Method};
    use Static;

    #[test]
    fn test_static() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        let handler = Static::new(root.clone());
        File::create(&root.join("Cargo.toml")).write(b"[package]").unwrap();
        let mut req = test::MockRequest::new(Method::Get, "/Cargo.toml");
        let mut res = handler.call(&mut req).ok().expect("No response");
        let body = res.body.read_to_string().ok().expect("No body");
        assert_eq!(body.as_slice(), "[package]");
        assert_eq!(res.headers.get("Content-Type"),
                   Some(&vec!("text/plain".to_string())));
        assert_eq!(res.headers.get("Content-Length"),
                   Some(&vec!["9".to_string()]));
    }

    #[test]
    fn test_mime_types() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        fs::mkdir(&root.join("src"), USER_RWX).unwrap();
        File::create(&root.join("src/fixture.css")).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/src/fixture.css");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.headers.get("Content-Type"),
                   Some(&vec!("text/css".to_string())));
        assert_eq!(res.headers.get("Content-Length"),
                   Some(&vec!["0".to_string()]));
    }

    #[test]
    fn test_missing() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/nope");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 404);
    }

    #[test]
    fn test_dir() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();

        fs::mkdir(&root.join("foo"), USER_RWX).unwrap();

        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/foo");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 404);
    }

    #[test]
    fn last_modified() {
        let td = TempDir::new("conduit-static").unwrap();
        let root = td.path();
        File::create(&root.join("test")).unwrap();
        let handler = Static::new(root.clone());
        let mut req = test::MockRequest::new(Method::Get, "/test");
        let res = handler.call(&mut req).ok().expect("No response");
        assert_eq!(res.status.val0(), 200);
        assert!(res.headers.get("Last-Modified").is_some());
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/reqwest/0.7.0")]

//! # reqwest
//!
//! The `reqwest` crate provides a convenient, higher-level HTTP Client.
//!
//! It handles many of the things that most people just expect an HTTP client
//! to do for them.
//!
//! - Uses system-native TLS
//! - Plain bodies, JSON, urlencoded, (TODO: multipart)
//! - Customizable redirect policy
//! - (TODO: Cookies)
//!
//! The `reqwest::Client` is synchronous, making it a great fit for
//! applications that only require a few HTTP requests, and wish to handle
//! them synchronously.
//!
//! ## Making a GET request
//!
//! For a single request, you can use the [`get`][get] shortcut method.
//!
//! ```rust
//! use std::io::Read;
//! # use reqwest::{Error, Response};
//!
//! # fn run() -> Result<Response, Error> {
//! let mut resp = reqwest::get("https://www.rust-lang.org")?;
//! assert!(resp.status().is_success());
//!
//! let mut content = String::new();
//! resp.read_to_string(&mut content);
//! # Ok(resp)
//! # }
//! ```
//!
//! As you can see, reqwest's [`Response`][response] struct implements Rust's
//! `Read` trait, so many useful standard library and third party crates will
//! have convenience methods that take a `Response` anywhere `T: Read` is
//! acceptable.
//!
//! If you plan to perform multiple requests, it is best to create a [`Client`][client]
//! and reuse it, taking advantage of keep-alive connection pooling.
//!
//! ## Making POST requests (or setting request bodies)
//!
//! There are several ways you can set the body of a request. The basic one is
//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the
//! exact raw bytes of what the body should be. It accepts various types,
//! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom
//! Reader, you can use the `reqwest::Body::new()` constructor.
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # fn run() -> Result<(), Error> {
//! let client = reqwest::Client::new()?;
//! let res = client.post("http://httpbin.org/post")?
//!     .body("the exact body that is sent")
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! ### Forms
//!
//! It's very common to want to send form data in a request body. This can be
//! done with any type that can be serialized into form data.
//!
//! This can be an array of tuples, or a `HashMap`, or a custom type that
//! implements [`Serialize`][serde].
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # fn run() -> Result<(), Error> {
//! // This will POST a body of `foo=bar&baz=quux`
//! let params = [("foo", "bar"), ("baz", "quux")];
//! let client = reqwest::Client::new()?;
//! let res = client.post("http://httpbin.org/post")?
//!     .form(&params)?
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! ### JSON
//!
//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in
//! a similar fashion the `form` method. It can take any value that can be
//! serialized into JSON.
//!
//! ```rust
//! # use reqwest::Error;
//! # use std::collections::HashMap;
//! #
//! # fn run() -> Result<(), Error> {
//! // This will POST a body of `{"lang":"rust","body":"json"}`
//! let mut map = HashMap::new();
//! map.insert("lang", "rust");
//! map.insert("body", "json");
//!
//! let client = reqwest::Client::new()?;
//! let res = client.post("http://httpbin.org/post")?
//!     .json(&map)?
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! [hyper]: http://hyper.rs
//! [client]: ./struct.Client.html
//! [response]: ./struct.Response.html
//! [get]: ./fn.get.html
//! [builder]: ./client/struct.RequestBuilder.html
//! [serde]: http://serde.rs

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
#[macro_use]
extern crate log;
extern crate libflate;
extern crate native_tls;
extern crate serde;
extern crate serde_json;
extern crate serde_urlencoded;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_tls;
extern crate url;

pub use hyper::header;
pub use hyper::mime;
pub use hyper::Method;
pub use hyper::StatusCode;
pub use url::Url;
pub use url::ParseError as UrlError;

pub use self::client::{Client, ClientBuilder};
pub use self::error::{Error, Result};
pub use self::body::Body;
pub use self::into_url::IntoUrl;
pub use self::proxy::Proxy;
pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy};
pub use self::request::{Request, RequestBuilder};
pub use self::response::Response;
pub use self::tls::Certificate;

// this module must be first because of the `try_` macro
#[macro_use]
mod error;

/// A set of unstable functionality.
///
/// This module is only available when the `unstable` feature is enabled.
/// There is no backwards compatibility guarantee for any of the types within.
#[cfg(feature = "unstable")]
pub mod unstable {
    /// An 'async' implementation of the reqwest `Client`.
    ///
    /// Relies on the `futures` crate, which is unstable, hence this module
    /// is unstable.
    pub mod async {
        pub use ::async_impl::{
            Body,
            Chunk,
            Client,
            ClientBuilder,
            Request,
            RequestBuilder,
            Response,
        };
    }
}

mod async_impl;
mod connect;
mod body;
mod client;
mod into_url;
mod proxy;
mod redirect;
mod request;
mod response;
mod tls;
mod wait;

/// Shortcut method to quickly make a `GET` request.
///
/// See also the methods on the [`reqwest::Response`](./struct.Response.html)
/// type.
///
/// # Examples
///
/// ```rust
/// use std::io::Read;
///
/// # fn run() -> Result<(), Box<::std::error::Error>> {
/// let mut result = String::new();
/// reqwest::get("https://www.rust-lang.org")?
///     .read_to_string(&mut result)?;
/// # Ok(())
/// # }
/// # fn main() { }
/// ```
///
/// # Errors
///
/// This function fails if:
///
/// - native TLS backend cannot be initialized
/// - supplied `Url` cannot be parsed
/// - there was an error while sending request
/// - redirect loop was detected
/// - redirect limit was exhausted
pub fn get<T: IntoUrl>(url: T) -> ::Result<Response> {
    Client::new()?
        .get(url)?
        .send()
}

fn _assert_impls() {
    fn assert_send<T: Send>() {}
    fn assert_sync<T: Sync>() {}
    fn assert_clone<T: Clone>() {}

    assert_send::<Client>();
    assert_sync::<Client>();
    assert_clone::<Client>();

    assert_send::<Request>();
    assert_send::<RequestBuilder>();

    assert_send::<Response>();

    assert_send::<Error>();
    assert_sync::<Error>();
}
<commit_msg>add note that reqwest handles proxies<commit_after>#![deny(warnings)]
#![deny(missing_docs)]
#![deny(missing_debug_implementations)]
#![doc(html_root_url = "https://docs.rs/reqwest/0.7.0")]

//! # reqwest
//!
//! The `reqwest` crate provides a convenient, higher-level HTTP Client.
//!
//! It handles many of the things that most people just expect an HTTP client
//! to do for them.
//!
//! - Uses system-native TLS
//! - Plain bodies, JSON, urlencoded, (TODO: multipart)
//! - Customizable redirect policy
//! - Proxies
//! - (TODO: Cookies)
//!
//! The `reqwest::Client` is synchronous, making it a great fit for
//! applications that only require a few HTTP requests, and wish to handle
//! them synchronously.
//!
//! ## Making a GET request
//!
//! For a single request, you can use the [`get`][get] shortcut method.
//!
//! ```rust
//! use std::io::Read;
//! # use reqwest::{Error, Response};
//!
//! # fn run() -> Result<Response, Error> {
//! let mut resp = reqwest::get("https://www.rust-lang.org")?;
//! assert!(resp.status().is_success());
//!
//! let mut content = String::new();
//! resp.read_to_string(&mut content);
//! # Ok(resp)
//! # }
//! ```
//!
//! As you can see, reqwest's [`Response`][response] struct implements Rust's
//! `Read` trait, so many useful standard library and third party crates will
//! have convenience methods that take a `Response` anywhere `T: Read` is
//! acceptable.
//!
//! If you plan to perform multiple requests, it is best to create a [`Client`][client]
//! and reuse it, taking advantage of keep-alive connection pooling.
//!
//! ## Making POST requests (or setting request bodies)
//!
//! There are several ways you can set the body of a request. The basic one is
//! by using the `body()` method of a [`RequestBuilder`][builder]. This lets you set the
//! exact raw bytes of what the body should be. It accepts various types,
//! including `String`, `Vec<u8>`, and `File`. If you wish to pass a custom
//! Reader, you can use the `reqwest::Body::new()` constructor.
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # fn run() -> Result<(), Error> {
//! let client = reqwest::Client::new()?;
//! let res = client.post("http://httpbin.org/post")?
//!     .body("the exact body that is sent")
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! ### Forms
//!
//! It's very common to want to send form data in a request body. This can be
//! done with any type that can be serialized into form data.
//!
//! This can be an array of tuples, or a `HashMap`, or a custom type that
//! implements [`Serialize`][serde].
//!
//! ```rust
//! # use reqwest::Error;
//! #
//! # fn run() -> Result<(), Error> {
//! // This will POST a body of `foo=bar&baz=quux`
//! let params = [("foo", "bar"), ("baz", "quux")];
//! let client = reqwest::Client::new()?;
//! let res = client.post("http://httpbin.org/post")?
//!     .form(&params)?
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! ### JSON
//!
//! There is also a `json` method helper on the [`RequestBuilder`][builder] that works in
//! a similar fashion the `form` method. It can take any value that can be
//! serialized into JSON.
//!
//! ```rust
//! # use reqwest::Error;
//! # use std::collections::HashMap;
//! #
//! # fn run() -> Result<(), Error> {
//! // This will POST a body of `{"lang":"rust","body":"json"}`
//! let mut map = HashMap::new();
//! map.insert("lang", "rust");
//! map.insert("body", "json");
//!
//! let client = reqwest::Client::new()?;
//! let res = client.post("http://httpbin.org/post")?
//!     .json(&map)?
//!     .send()?;
//! # Ok(())
//! # }
//! ```
//!
//! [hyper]: http://hyper.rs
//! [client]: ./struct.Client.html
//! [response]: ./struct.Response.html
//! [get]: ./fn.get.html
//! [builder]: ./client/struct.RequestBuilder.html
//! [serde]: http://serde.rs

extern crate bytes;
#[macro_use]
extern crate futures;
extern crate hyper;
extern crate hyper_tls;
#[macro_use]
extern crate log;
extern crate libflate;
extern crate native_tls;
extern crate serde;
extern crate serde_json;
extern crate serde_urlencoded;
extern crate tokio_core;
extern crate tokio_io;
extern crate tokio_tls;
extern crate url;

pub use hyper::header;
pub use hyper::mime;
pub use hyper::Method;
pub use hyper::StatusCode;
pub use url::Url;
pub use url::ParseError as UrlError;

pub use self::client::{Client, ClientBuilder};
pub use self::error::{Error, Result};
pub use self::body::Body;
pub use self::into_url::IntoUrl;
pub use self::proxy::Proxy;
pub use self::redirect::{RedirectAction, RedirectAttempt, RedirectPolicy};
pub use self::request::{Request, RequestBuilder};
pub use self::response::Response;
pub use self::tls::Certificate;

// this module must be first because of the `try_` macro
#[macro_use]
mod error;

/// A set of unstable functionality.
///
/// This module is only available when the `unstable` feature is enabled.
/// There is no backwards compatibility guarantee for any of the types within.
#[cfg(feature = "unstable")]
pub mod unstable {
    /// An 'async' implementation of the reqwest `Client`.
    ///
    /// Relies on the `futures` crate, which is unstable, hence this module
    /// is unstable.
    pub mod async {
        pub use ::async_impl::{
            Body,
            Chunk,
            Client,
            ClientBuilder,
            Request,
            RequestBuilder,
            Response,
        };
    }
}

mod async_impl;
mod connect;
mod body;
mod client;
mod into_url;
mod proxy;
mod redirect;
mod request;
mod response;
mod tls;
mod wait;

/// Shortcut method to quickly make a `GET` request.
///
/// See also the methods on the [`reqwest::Response`](./struct.Response.html)
/// type.
///
/// # Examples
///
/// ```rust
/// use std::io::Read;
///
/// # fn run() -> Result<(), Box<::std::error::Error>> {
/// let mut result = String::new();
/// reqwest::get("https://www.rust-lang.org")?
///     .read_to_string(&mut result)?;
/// # Ok(())
/// # }
/// # fn main() { }
/// ```
///
/// # Errors
///
/// This function fails if:
///
/// - native TLS backend cannot be initialized
/// - supplied `Url` cannot be parsed
/// - there was an error while sending request
/// - redirect loop was detected
/// - redirect limit was exhausted
pub fn get<T: IntoUrl>(url: T) -> ::Result<Response> {
    Client::new()?
        .get(url)?
        .send()
}

fn _assert_impls() {
    fn assert_send<T: Send>() {}
    fn assert_sync<T: Sync>() {}
    fn assert_clone<T: Clone>() {}

    assert_send::<Client>();
    assert_sync::<Client>();
    assert_clone::<Client>();

    assert_send::<Request>();
    assert_send::<RequestBuilder>();

    assert_send::<Response>();

    assert_send::<Error>();
    assert_sync::<Error>();
}
<|endoftext|>