<commit_before>// ZSnapMgr :: ZFS snapshot and backup manager
//
// Copyright (c) 2016 by William R. Fraser
//

use std::collections::btree_map::*;
use std::ffi::OsString;
use std::io::Write;
use std::path::Path;

extern crate chrono;
extern crate libc;
extern crate ring;

use chrono::*;

#[macro_use] mod zfs_error; // include this first because its macros are used in other modules.
mod hash_stream;
mod inheritable_pipe;
mod zfs;

use inheritable_pipe::InheritablePipe;
use zfs::ZFS;
use zfs_error::ZfsError;

pub struct ZSnapMgr {
    zfs: ZFS,
}

fn date_from_snapshot(snap: &str) -> Option<Date<Local>> {
    let datepart = match snap.splitn(2, '@').last() {
        Some(s) => s,
        None => return None,
    };

    let dateparts: Vec<i32> = datepart.splitn(3, '-')
                                      .filter_map(|part| {
                                          part.parse::<i32>()
                                              .ok()
                                      })
                                      .collect();

    if dateparts.len() != 3 {
        return None;
    }

    Some(Local.ymd(dateparts[0], dateparts[1] as u32, dateparts[2] as u32))
}

trait Succ {
    fn succ(&self) -> Self;
}

trait WeekOfYear {
    fn week_of_year(&self) -> IsoWeek;
}

impl<Tz: TimeZone> Succ for Date<Tz> {
    fn succ(&self) -> Self {
        Date::<Tz>::succ(self)
    }
}

impl Succ for NaiveDate {
    fn succ(&self) -> Self {
        NaiveDate::succ(self)
    }
}

impl<T: Datelike + Succ> WeekOfYear for T {
    fn week_of_year(&self) -> IsoWeek {
        // The original C# version of this program used System.Globalization.Calendar.GetWeekOfYear
        // for this, using System.Globalization.DateTimeFormatInfo.InvariantInfo for the
        // parameters.
        //
        // "The first week of the year starts on the first day of the year and ends before the
        // following designated first day of the week."
        // The first day of the week is designated as Sunday.
        //
        // This is similar to the ISO week date, except that ISO week date has:
        //  - week starting on Monday
        //  - the first day of the year can be week 53 from the previous year (week 1 is defined as
        //    being the first week containing January 4 of that year)
        //
        // This isn't going to replicate the C# method exactly - the value can be +/- 1 depending
        // on which year it is for.
        // Figuring out whether to add 1 or not depending on the year is hard, and this method is
        // only used for finding the first snapshot in a week, so the difference isn't important,
        // as long as days in the same week get the same value.
        // In fact, the C# method wouldn't even uphold this property on the first week of the year
        // usually -- it would unconditionally change from 53 or 54 to 1 mid-week. This method does
        // not.

        if self.weekday() == Weekday::Sun {
            // We want weeks starting on Sunday, so if it's Sunday, use the ISO week number for
            // tomorrow.
            self.succ().iso_week()
        } else {
            self.iso_week()
        }
    }
}

impl ZSnapMgr {
    pub fn new(use_sudo: bool) -> ZSnapMgr {
        ZSnapMgr { zfs: ZFS { use_sudo } }
    }

    pub fn get_volumes(&self) -> Result<Vec<String>, ZfsError> {
        self.zfs.volumes(None)
    }

    pub fn get_snapshots(&self, dataset: Option<&str>) -> Result<Vec<String>, ZfsError> {
        self.zfs.snapshots(dataset)
    }

    pub fn backup(&self,
                  path: &Path,
                  snapshot: &str,
                  passphrase: &str,
                  incremental_start: Option<&str>)
                  -> Result<(), ZfsError> {
        let mut passphrase_pipe =
            zfstry!(InheritablePipe::new(), or "failed to create passphrase pipe");

        zfstry!(write!(passphrase_pipe, "{}\n", passphrase), or "failed to write passphrase to pipe");

        let destination_path = path.join(OsString::from(snapshot.replace("/", "_") + ".zfs.bz2.gpg"));

        self.zfs.send(snapshot,
                      &destination_path,
                      incremental_start,
                      Some(&format!("pbzip2 | gpg --batch --symmetric --passphrase-fd {} \
                                     --output -",
                                    passphrase_pipe.child_fd())))
    }

    pub fn snapshot_automanage(&self) -> Result<(), ZfsError> {
        let today = Local::today();
        let today_str = format!("{:04}-{:02}-{:02}",
                                today.year(),
                                today.month(),
                                today.day());

        let mut all_snaps = self.get_snapshots(None)?;
        let mut snaps_map: BTreeMap<String, BTreeMap<Date<Local>, String>> = BTreeMap::new();
        for snap in all_snaps.drain(..) {
            let snap_date = match date_from_snapshot(&snap) {
                Some(date) => date,
                None => continue,
            };

            let volume = snap.splitn(2, '@').next().unwrap().to_string();
            let entry = snaps_map.entry(volume).or_insert_with(BTreeMap::new);
            entry.insert(snap_date, snap);
        }

        let mut to_delete = Vec::<String>::new();
        let mut to_create = Vec::<String>::new();

        for (volume, snaps) in snaps_map {
            let mut count = 0;

            for (snap_date, snap) in snaps.iter().rev() {
                count += 1;

                let days_old = (today.signed_duration_since(*snap_date)).num_days();

                if (count == 1) && (days_old != 0) {
                    println!("{}\t{}\t0 days old\t#1\t[NEW]", volume, today_str);
                    to_create.push(format!("{}@{}", volume, today_str));
                    count += 1;
                }

                print!("{}\t{}\t{} days old\t#{}",
                       volume,
                       snap.splitn(2, '@').last().unwrap(),
                       days_old,
                       count);

                // Give the tuple elements names.
                struct Pair<'a> {
                    date: &'a Date<Local>,
                    snap: &'a str,
                };

                const ISO8601_DATE_FMT: &str = "%Y-%m-%d";

                let mut delete = None::<String>; // set to Some(reason) if deletion should happen

                let first_of_month = snaps.iter()
                                          .map(|(date, snap)| Pair { date, snap })
                                          .find(|pair| {
                                              pair.date.year() == snap_date.year() &&
                                              pair.date.month() == snap_date.month()
                                          })
                                          .unwrap();

                if count > 60 {
                    // Keep only the first snapshot of the month.
                    if first_of_month.snap != snap {
                        delete = Some(format!("not first of month ({})",
                            first_of_month.date.format(ISO8601_DATE_FMT)));
                    }
                } else if count > 30 {
                    // Keep only the first snapshot of the week or month.
                    let first_of_week = snaps.iter()
                                             .map(|(date, snap)| Pair { date, snap })
                                             .find(|pair| {
                                                 pair.date.week_of_year() == snap_date.week_of_year()
                                             })
                                             .unwrap();

                    if first_of_week.snap != snap &&
                       first_of_month.snap != snap {
                        delete = Some(format!("not first of month ({}) or first of week ({})",
                            first_of_month.date.format(ISO8601_DATE_FMT),
                            first_of_week.date.format(ISO8601_DATE_FMT)));
                    }
                }

                if let Some(why) = delete {
                    print!("\t[DELETE] {}", why);
                    to_delete.push(snap.to_string());
                }

                println!();
            }
        }

        for snap in to_delete {
            // TODO
            println!("ZFS DELETE {}", snap);
        }

        for snap in to_create {
            // TODO
            println!("ZFS SNAPSHOT {}", snap);
        }

        Err(ZfsError::from("snapshot automanage is not yet implemented."))
    }
}
<commit_msg>change from pbzip2 to zstdmt; it's much faster<commit_after>// ZSnapMgr :: ZFS snapshot and backup manager
//
// Copyright (c) 2016 by William R. Fraser
//

use std::collections::btree_map::*;
use std::ffi::OsString;
use std::io::Write;
use std::path::Path;

extern crate chrono;
extern crate libc;
extern crate ring;

use chrono::*;

#[macro_use] mod zfs_error; // include this first because its macros are used in other modules.
mod hash_stream;
mod inheritable_pipe;
mod zfs;

use inheritable_pipe::InheritablePipe;
use zfs::ZFS;
use zfs_error::ZfsError;

pub struct ZSnapMgr {
    zfs: ZFS,
}

fn date_from_snapshot(snap: &str) -> Option<Date<Local>> {
    let datepart = match snap.splitn(2, '@').last() {
        Some(s) => s,
        None => return None,
    };

    let dateparts: Vec<i32> = datepart.splitn(3, '-')
                                      .filter_map(|part| {
                                          part.parse::<i32>()
                                              .ok()
                                      })
                                      .collect();

    if dateparts.len() != 3 {
        return None;
    }

    Some(Local.ymd(dateparts[0], dateparts[1] as u32, dateparts[2] as u32))
}

trait Succ {
    fn succ(&self) -> Self;
}

trait WeekOfYear {
    fn week_of_year(&self) -> IsoWeek;
}

impl<Tz: TimeZone> Succ for Date<Tz> {
    fn succ(&self) -> Self {
        Date::<Tz>::succ(self)
    }
}

impl Succ for NaiveDate {
    fn succ(&self) -> Self {
        NaiveDate::succ(self)
    }
}

impl<T: Datelike + Succ> WeekOfYear for T {
    fn week_of_year(&self) -> IsoWeek {
        // The original C# version of this program used System.Globalization.Calendar.GetWeekOfYear
        // for this, using System.Globalization.DateTimeFormatInfo.InvariantInfo for the
        // parameters.
        //
        // "The first week of the year starts on the first day of the year and ends before the
        // following designated first day of the week."
        // The first day of the week is designated as Sunday.
        //
        // This is similar to the ISO week date, except that ISO week date has:
        //  - week starting on Monday
        //  - the first day of the year can be week 53 from the previous year (week 1 is defined as
        //    being the first week containing January 4 of that year)
        //
        // This isn't going to replicate the C# method exactly - the value can be +/- 1 depending
        // on which year it is for.
        // Figuring out whether to add 1 or not depending on the year is hard, and this method is
        // only used for finding the first snapshot in a week, so the difference isn't important,
        // as long as days in the same week get the same value.
        // In fact, the C# method wouldn't even uphold this property on the first week of the year
        // usually -- it would unconditionally change from 53 or 54 to 1 mid-week. This method does
        // not.

        if self.weekday() == Weekday::Sun {
            // We want weeks starting on Sunday, so if it's Sunday, use the ISO week number for
            // tomorrow.
            self.succ().iso_week()
        } else {
            self.iso_week()
        }
    }
}

impl ZSnapMgr {
    pub fn new(use_sudo: bool) -> ZSnapMgr {
        ZSnapMgr { zfs: ZFS { use_sudo } }
    }

    pub fn get_volumes(&self) -> Result<Vec<String>, ZfsError> {
        self.zfs.volumes(None)
    }

    pub fn get_snapshots(&self, dataset: Option<&str>) -> Result<Vec<String>, ZfsError> {
        self.zfs.snapshots(dataset)
    }

    pub fn backup(&self,
                  path: &Path,
                  snapshot: &str,
                  passphrase: &str,
                  incremental_start: Option<&str>)
                  -> Result<(), ZfsError> {
        let mut passphrase_pipe =
            zfstry!(InheritablePipe::new(), or "failed to create passphrase pipe");

        zfstry!(write!(passphrase_pipe, "{}\n", passphrase), or "failed to write passphrase to pipe");

        let destination_path = path.join(OsString::from(snapshot.replace("/", "_") + ".zfs.zst.gpg"));

        self.zfs.send(snapshot,
                      &destination_path,
                      incremental_start,
                      Some(&format!("zstd -T0 --size-hint=1000000000 | gpg --batch --symmetric --passphrase-fd {} \
                                     --output -",
                                    passphrase_pipe.child_fd())))
    }

    pub fn snapshot_automanage(&self) -> Result<(), ZfsError> {
        let today = Local::today();
        let today_str = format!("{:04}-{:02}-{:02}",
                                today.year(),
                                today.month(),
                                today.day());

        let mut all_snaps = self.get_snapshots(None)?;
        let mut snaps_map: BTreeMap<String, BTreeMap<Date<Local>, String>> = BTreeMap::new();
        for snap in all_snaps.drain(..) {
            let snap_date = match date_from_snapshot(&snap) {
                Some(date) => date,
                None => continue,
            };

            let volume = snap.splitn(2, '@').next().unwrap().to_string();
            let entry = snaps_map.entry(volume).or_insert_with(BTreeMap::new);
            entry.insert(snap_date, snap);
        }

        let mut to_delete = Vec::<String>::new();
        let mut to_create = Vec::<String>::new();

        for (volume, snaps) in snaps_map {
            let mut count = 0;

            for (snap_date, snap) in snaps.iter().rev() {
                count += 1;

                let days_old = (today.signed_duration_since(*snap_date)).num_days();

                if (count == 1) && (days_old != 0) {
                    println!("{}\t{}\t0 days old\t#1\t[NEW]", volume, today_str);
                    to_create.push(format!("{}@{}", volume, today_str));
                    count += 1;
                }

                print!("{}\t{}\t{} days old\t#{}",
                       volume,
                       snap.splitn(2, '@').last().unwrap(),
                       days_old,
                       count);

                // Give the tuple elements names.
                struct Pair<'a> {
                    date: &'a Date<Local>,
                    snap: &'a str,
                };

                const ISO8601_DATE_FMT: &str = "%Y-%m-%d";

                let mut delete = None::<String>; // set to Some(reason) if deletion should happen

                let first_of_month = snaps.iter()
                                          .map(|(date, snap)| Pair { date, snap })
                                          .find(|pair| {
                                              pair.date.year() == snap_date.year() &&
                                              pair.date.month() == snap_date.month()
                                          })
                                          .unwrap();

                if count > 60 {
                    // Keep only the first snapshot of the month.
                    if first_of_month.snap != snap {
                        delete = Some(format!("not first of month ({})",
                            first_of_month.date.format(ISO8601_DATE_FMT)));
                    }
                } else if count > 30 {
                    // Keep only the first snapshot of the week or month.
                    let first_of_week = snaps.iter()
                                             .map(|(date, snap)| Pair { date, snap })
                                             .find(|pair| {
                                                 pair.date.week_of_year() == snap_date.week_of_year()
                                             })
                                             .unwrap();

                    if first_of_week.snap != snap &&
                       first_of_month.snap != snap {
                        delete = Some(format!("not first of month ({}) or first of week ({})",
                            first_of_month.date.format(ISO8601_DATE_FMT),
                            first_of_week.date.format(ISO8601_DATE_FMT)));
                    }
                }

                if let Some(why) = delete {
                    print!("\t[DELETE] {}", why);
                    to_delete.push(snap.to_string());
                }

                println!();
            }
        }

        for snap in to_delete {
            // TODO
            println!("ZFS DELETE {}", snap);
        }

        for snap in to_create {
            // TODO
            println!("ZFS SNAPSHOT {}", snap);
        }

        Err(ZfsError::from("snapshot automanage is not yet implemented."))
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016 Benjamin Fry <benjaminfry@me.com>

use std::ascii::AsciiExt;

/// returns true if and only if the phrase is a palindrome
///
/// # Arguments
///
/// * `phrase` - the phrase to inspect
///
/// This is just to be fun with iterators...
/// This should be O(n/2), and would be fewer lines without all the comments.
pub fn is_palindrome(phrase: &str) -> bool {
    // get the chars iterator and associated index
    phrase.char_indices().filter(|&(_,c)| c.is_alphabetic())
                // zip with the second half...
                .zip(phrase.char_indices()
                           // which needs to be reversed...
                           .rev()
                           // and filter out bad cars
                           .filter(|&(_,c)| c.is_alphabetic()))
                // accept all input until the indexes have crossed
                .take_while(|&((first_count, _), (last_count, _))| {first_count < last_count})
                // check that all the chars from the begining and end match
                .all(|((_, first_char), (_, last_char))| {
                    first_char.to_ascii_lowercase() == last_char.to_ascii_lowercase()
                })
}

/// this is a class array implementation (for comparison)
///
/// # Arguments
///
/// * `phrase` - the phrase to inspect
///
/// This is definitely not the most efficient, but is meant show the difference to above. And be
///  close to the semantics used in C/C++, with the exception of the chars().collect() this should
///  be O(n/2).
pub fn is_palindrome_classic(phrase: &str) -> bool {
    if phrase.len() == 0 { return true }

    // need to do this because Rust is rightly trying to force you away from treating strs as
    //  arrays
    let phrase: Vec<char> = phrase.chars().collect();

    // start from the beginning
    let mut first_idx = 0;

    // and the end, btw, don't forget the off-by-one b/c of the
    let mut last_idx = phrase.len() - 1;
    // loop and guard that we don't go too far
    while first_idx < last_idx {
        // filter out non-alphabetics
        if !phrase[first_idx].is_alphabetic() { first_idx += 1; continue }
        if !phrase[last_idx].is_alphabetic() { last_idx -= 1; continue }

        // compare the values
        if phrase[first_idx].to_ascii_lowercase() != phrase[last_idx].to_ascii_lowercase() {
            return false;
        }

        first_idx += 1;
        last_idx -= 1;
    }

    // is this actually simpler or more readable? I don't think so...

    true
}

#[test]
fn test_is_palindrome() {
    test_is_palindrome_base(is_palindrome);
}

#[test]
fn test_palindrome_classic() {
    test_is_palindrome_base(is_palindrome_classic);
}

#[cfg(test)]
fn test_is_palindrome_base<F>(is_palindrome: F) where F: Fn(&str) -> bool {
    assert!(is_palindrome(""));
    assert!(is_palindrome("a"));
    assert!(is_palindrome(".,,/.,/.,././.,=-=--"));
    assert!(is_palindrome("a,,,,,,,,,,,,,,,a"));
    assert!(is_palindrome("a,,,,,bb,,,,,,,,a"));
    assert!(is_palindrome("race car"));
    assert!(is_palindrome("racecar"));
    assert!(is_palindrome("raccar"));
    assert!(is_palindrome("A man, a plan, a canal, Panama!"));
    assert!(is_palindrome("Amor, Roma"));
    assert!(is_palindrome("stack cats"));
    assert!(is_palindrome("step on no pets"));
    assert!(is_palindrome("taco cat"));
    assert!(is_palindrome("put it up"));
    assert!(is_palindrome("Was it a car or a cat I saw?"));
    assert!(is_palindrome("No ‘x’ in Nixon"));

    // negative for good messure
    assert!(!is_palindrome("Not a palindrome"))
}
<commit_msg>update comments<commit_after>// Copyright (C) 2016 Benjamin Fry <benjaminfry@me.com>

use std::ascii::AsciiExt;

/// returns true if and only if the phrase is a palindrome
///
/// # Arguments
///
/// * `phrase` - the phrase to inspect
///
/// This is just to be fun with iterators...
/// This should be O(n/2), and would be fewer lines without all the comments.
pub fn is_palindrome(phrase: &str) -> bool {
    // get the chars iterator and associated index
    phrase.char_indices().filter(|&(_,c)| c.is_alphabetic())
                // zip with the second half...
                .zip(phrase.char_indices()
                           // which needs to be reversed...
                           .rev()
                           // and filter out bad cars
                           .filter(|&(_,c)| c.is_alphabetic()))
                // accept all input until the indexes have crossed
                .take_while(|&((first_count, _), (last_count, _))| {first_count < last_count})
                // check that all the chars from the begining and end match
                .all(|((_, first_char), (_, last_char))| {
                    first_char.to_ascii_lowercase() == last_char.to_ascii_lowercase()
                })
}

/// this is a class array implementation (for comparison)
///
/// # Arguments
///
/// * `phrase` - the phrase to inspect
///
/// This is definitely not the most efficient, but is meant show the difference to above. And be
///  close to the semantics used in C/C++, with the exception of the chars().collect() this should
///  be O(n/2).
pub fn is_palindrome_classic(phrase: &str) -> bool {
    if phrase.len() == 0 { return true }

    // need to do this because Rust is rightly trying to force you away from treating strs as
    //  arrays
    let phrase: Vec<char> = phrase.chars().collect();

    // start from the beginning
    let mut first_idx = 0;

    // and the end, btw, don't forget the off-by-one b/c of len() is actually past the last index...
    //  this is a classic error avoided implicitly above.
    let mut last_idx = phrase.len() - 1;
    // loop and guard that we don't go too far
    while first_idx < last_idx {
        // filter out non-alphabetics, the += and -= would be something you could accidentally screw up,
        //   avoided in the iterator based impl
        if !phrase[first_idx].is_alphabetic() { first_idx += 1; continue }
        if !phrase[last_idx].is_alphabetic() { last_idx -= 1; continue }

        // compare the values, did we compare the write indexes? again avoided in the iterator impl
        if phrase[first_idx].to_ascii_lowercase() != phrase[last_idx].to_ascii_lowercase() {
            return false;
        }

        // same += and -= potential bug avoided in the iterator impl
        first_idx += 1;
        last_idx -= 1;
    }

    // is this actually simpler or more readable? I don't think so...

    true
}

#[test]
fn test_is_palindrome() {
    test_is_palindrome_base(is_palindrome);
}

#[test]
fn test_palindrome_classic() {
    test_is_palindrome_base(is_palindrome_classic);
}

#[cfg(test)]
fn test_is_palindrome_base<F>(is_palindrome: F) where F: Fn(&str) -> bool {
    assert!(is_palindrome(""));
    assert!(is_palindrome("a"));
    assert!(is_palindrome(".,,/.,/.,././.,=-=--"));
    assert!(is_palindrome("a,,,,,,,,,,,,,,,a"));
    assert!(is_palindrome("a,,,,,bb,,,,,,,,a"));
    assert!(is_palindrome("race car"));
    assert!(is_palindrome("racecar"));
    assert!(is_palindrome("raccar"));
    assert!(is_palindrome("A man, a plan, a canal, Panama!"));
    assert!(is_palindrome("Amor, Roma"));
    assert!(is_palindrome("stack cats"));
    assert!(is_palindrome("step on no pets"));
    assert!(is_palindrome("taco cat"));
    assert!(is_palindrome("put it up"));
    assert!(is_palindrome("Was it a car or a cat I saw?"));
    assert!(is_palindrome("No ‘x’ in Nixon"));

    // negative for good messure
    assert!(!is_palindrome("Not a palindrome"))
}
<|endoftext|>


<commit_before>// Copyright 2017 Dmytro Milinevskyi <dmilinevskyi@gmail.com>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![warn(missing_docs)]

//! # Woodpecker - fast and extensible logger for Rust
//!
//! The main goal of `woodpecker` is to be incredibly fast for the code
//! that doesn't generate the log.
//!
//! Please check out the project [homepage](https://github.com/niamster/woodpecker)
//! for more details on features, issues and limitation.
//!
//! The log levels are assigned in a hierarchical manner.
//!
//! If there's no exact match for a requested log then the closest match is used.
//!
//! That means that the log level for `foo::bar::qux` is deduced from the log level
//! for `foo::bar` unless the log level for `foo::bar::qux` is explicitly set.
//!
//! See documentation for the [wp_get_level](macro.wp_get_level.html) and [log](macro.log.html)
//! macros for more details on the hierarchy.
//!
//! # Installation
//! To start using `woodpecker` it's enough to just enable it in your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! woodpecker = "0.1"
//! ```
//!
//! In your `main.rs`:
//!
//! ```rust
//! #[macro_use]
//! extern crate woodpecker;
//! use woodpecker as wp;
//!
//! fn main() {
//!     wp::init();
//!
//!     warn!("It's alive!");
//! }
//! ```
//!
//! And start using logging functions as `debug`, `info`, etc. as with
//! generic rust [logger](https://doc.rust-lang.org/log)
//!
//! # Example
//!
//! ```rust
//! #[macro_use]
//! extern crate woodpecker;
//! use woodpecker as wp;
//!
//! fn main() {
//!     wp::init();
//!
//!     wp_set_level!(wp::LogLevel::INFO);
//!     info!("{} is saying hello", "woodpecker");
//!     debug!("I'm invisible");
//! }
//!
//! ```
//!
//! Woodpecker supports logging in a dedicated thread.
//!
//! This frees the application from the latency caused by formatting
//! the log string and emitting it into a log sink(terminal, file, network, etc.).
//!
//! It's important to use [sync](fn.sync.html) in the end of the `main` funtion
//! to ensure that all log records are properly flushed.
//!
//! The logging thread is either activated explicitly via
//! [init_with_thread](fn.init_with_thread.html) function or by setting
//! `WP_LOG_THREAD` environment variable which overrides compile-time settings.

#[doc(hidden)]
#[macro_use]
pub mod helpers;

/// Definition of the log levels.
pub mod levels;
#[doc(inline)]
pub use levels::LogLevel;

/// Definition of the log record entry.
pub mod record;
#[doc(inline)]
pub use record::Record;

/// The logger core.
#[macro_use]
pub mod logger;
#[doc(inline)]
pub use logger::{init, init_with_thread, sync};

/// Collection of log handlers.
pub mod handlers;

/// Collection of log record formatters.
pub mod formatters;
<commit_msg>update crate version in readme<commit_after>// Copyright 2017 Dmytro Milinevskyi <dmilinevskyi@gmail.com>

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

// http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![warn(missing_docs)]

//! # Woodpecker - fast and extensible logger for Rust
//!
//! The main goal of `woodpecker` is to be incredibly fast for the code
//! that doesn't generate the log.
//!
//! Please check out the project [homepage](https://github.com/niamster/woodpecker)
//! for more details on features, issues and limitation.
//!
//! The log levels are assigned in a hierarchical manner.
//!
//! If there's no exact match for a requested log then the closest match is used.
//!
//! That means that the log level for `foo::bar::qux` is deduced from the log level
//! for `foo::bar` unless the log level for `foo::bar::qux` is explicitly set.
//!
//! See documentation for the [wp_get_level](macro.wp_get_level.html) and [log](macro.log.html)
//! macros for more details on the hierarchy.
//!
//! # Installation
//! To start using `woodpecker` it's enough to just enable it in your `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! woodpecker = "0.2"
//! ```
//!
//! In your `main.rs`:
//!
//! ```rust
//! #[macro_use]
//! extern crate woodpecker;
//! use woodpecker as wp;
//!
//! fn main() {
//!     wp::init();
//!
//!     warn!("It's alive!");
//! }
//! ```
//!
//! And start using logging functions as `debug`, `info`, etc. as with
//! generic rust [logger](https://doc.rust-lang.org/log)
//!
//! # Example
//!
//! ```rust
//! #[macro_use]
//! extern crate woodpecker;
//! use woodpecker as wp;
//!
//! fn main() {
//!     wp::init();
//!
//!     wp_set_level!(wp::LogLevel::INFO);
//!     info!("{} is saying hello", "woodpecker");
//!     debug!("I'm invisible");
//! }
//!
//! ```
//!
//! Woodpecker supports logging in a dedicated thread.
//!
//! This frees the application from the latency caused by formatting
//! the log string and emitting it into a log sink(terminal, file, network, etc.).
//!
//! It's important to use [sync](fn.sync.html) in the end of the `main` funtion
//! to ensure that all log records are properly flushed.
//!
//! The logging thread is either activated explicitly via
//! [init_with_thread](fn.init_with_thread.html) function or by setting
//! `WP_LOG_THREAD` environment variable which overrides compile-time settings.

#[doc(hidden)]
#[macro_use]
pub mod helpers;

/// Definition of the log levels.
pub mod levels;
#[doc(inline)]
pub use levels::LogLevel;

/// Definition of the log record entry.
pub mod record;
#[doc(inline)]
pub use record::Record;

/// The logger core.
#[macro_use]
pub mod logger;
#[doc(inline)]
pub use logger::{init, init_with_thread, sync};

/// Collection of log handlers.
pub mod handlers;

/// Collection of log record formatters.
pub mod formatters;
<|endoftext|>


<commit_before>/*!
nphysics
========
**nphysics** is a 2 and 3-dimensional physics engine for games and animations.
It uses [ncollide](http://ncollide.org) for collision detection, and
[nalgebra](http://nalgebra.org) for vector/matrix math. 2D and 3D
implementations both share the same code!

Examples are available in the `examples2d` and `examples3d` directories. There
is also a short (outdated) [demonstration video](http://youtu.be/CANjXZ5rocI).
An on-line version of this documentation is available
[here](http://nphysics.org). Feel free to ask for help and discuss features on
the official [user forum](http://users.nphysics.org).

## Why another physics engine?
There are a lot of physics engine out there.
However having a physics engine written in Rust is much more fun than
writing bindings and has several advantages:

- it shows that Rust is suitable for soft real-time applications
- it shows how well Rust behaves with highly generic code
- it shows that there is no need to write two separate engine for 2D and 3D:
  genericity wrt the dimension is possible (modulo low level arithmetic
  specializations for each dimension).
- in a not-that-near future, C++ will die of ugliness. Then, people will
  search for a physics engine and **nphysics** will be there, proudly
  exhibiting its _Rusty_ sexyness.

## Compilation
You will need the latest release of the [Rust compiler](http://www.rust-lang.org)
and the official package manager: [Cargo](https://github.com/rust-lang/cargo).

If you want to use the 2D version of `nphysics`, add the crate named
`nphysics2d` to your dependencies:

```ignore
[dependencies]
nphysics2d = "0.8"
```

For the 3D version, add the crate named `nphysics3d`:

```ignore
[dependencies]
nphysics3d = "0.8"
```

Use `make examples` to build the demos and execute `./your_favorite_example_here --help`
to see all the cool stuffs you can do.

## Features
- Static and dynamic rigid bodies.
- Common convex primitives: cone, box, ball, cylinder.
- Concave geometries build from convex primitives (aka. compound geometries).
- Stable stacking.
- Island based sleeping (objects deactivation).
- Ray casting.
- Swept sphere based continuous collision detection.
- Ball-in-socket joint.
- FixedJoint joint.
- Sensors.

## What is missing?
**nphysics** is a very young library and needs to learn a lot of things to
become a grown up. Many missing features are because of missing features on
**ncollide**. Features missing from **nphysics** itself include:

- kinematic bodies
- efficient signaling system
- more joints, joint limits, joint motors and breakable joints.
- soft-bodies (see https://github.com/natal/roft for a draft)
- parallel pipeline
- GPU-based pipeline

## Dependencies
All dependencies are automatically cloned with a recursive clone.
The libraries needed to compile the physics engine are:

* [ncollide](http://ncollide.org): the collision detection library.
* [nalgebra](http://nalgebra.org): the linear algebra library.

The libraries needed to compile the examples are:

*/
#![cfg_attr(
  all(
    any(target_arch = "wasm32", target_arch = "asmjs"),
    feature = "wasm-bindgen-no-stdweb",
  ),
  feature(custom_attribute)
)]
#![deny(non_camel_case_types)]
#![deny(unused_parens)]
#![deny(non_upper_case_globals)]
#![deny(unused_qualifications)]
#![deny(missing_docs)]
#![deny(unused_results)]
#![warn(non_camel_case_types)]
#![allow(missing_copy_implementations)]
#![doc(html_root_url = "http://nphysics.org/rustdoc/")]

#[macro_use]
extern crate approx;
#[macro_use]
extern crate downcast;

extern crate alga;
extern crate nalgebra as na;
#[cfg(feature = "dim2")]
extern crate ncollide2d as ncollide;
#[cfg(feature = "dim3")]
extern crate ncollide3d as ncollide;
extern crate num_traits as num;
extern crate slab;

/*
 * The two following crates are pulled-in for
 * measuring time.
 */
#[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))]
extern crate time;

#[cfg(all(
  any(target_arch = "wasm32", target_arch = "asmjs"),
  feature = "stdweb",
))]
#[macro_use]
extern crate stdweb;

#[cfg(all(
  any(target_arch = "wasm32", target_arch = "asmjs"),
  feature = "wasm-bindgen-no-stdweb",
))]
extern crate wasm_bindgen;

//#[cfg(test)]
//extern crate test;

pub mod algebra;
pub mod counters;
pub mod detection;
pub mod force_generator;
pub mod joint;
pub mod object;
pub mod solver;
pub mod utils;
pub mod volumetric;
pub mod world;
// mod tests;

/// Compilation flags dependent aliases for mathematical types.
#[cfg(feature = "dim3")]
pub mod math {
  use algebra::{Force3, Inertia3, Velocity3};
  use na::{
    Dynamic, Isometry3, Matrix3, Matrix6, MatrixMN, MatrixSlice6xX, MatrixSliceMut6xX, Point3,
    Translation3, UnitQuaternion, Vector3, Vector6, U3, U6,
  };

  /// The maximum number of possible rotations and translations of a rigid body.
  pub const SPATIAL_DIM: usize = 6;
  /// The maximum number of possible rotations of a rigid body.
  pub const ANGULAR_DIM: usize = 3;
  /// The maximum number of possible translations of a rigid body.
  pub const DIM: usize = 3;

  /// The dimension of the ambiant space.
  pub type Dim = U3;

  /// The dimension of a spatial vector.
  pub type SpatialDim = U6;

  /// The dimension of the rotations.
  pub type AngularDim = U3;

  /// The point type.
  pub type Point<N> = Point3<N>;

  /// The angular vector type.
  pub type AngularVector<N> = Vector3<N>;

  /// The vector type.
  pub type Vector<N> = Vector3<N>;

  /// The vector type with dimension `SpatialDim × 1`.
  pub type SpatialVector<N> = Vector6<N>;

  /// The orientation type.
  pub type Orientation<N> = Vector3<N>;

  /// The transformation matrix type.
  pub type Isometry<N> = Isometry3<N>;

  /// The rotation matrix type.
  pub type Rotation<N> = UnitQuaternion<N>;

  /// The translation type.
  pub type Translation<N> = Translation3<N>;

  /// The velocity type combining the linear velocity and the angular velocity.
  pub type Velocity<N> = Velocity3<N>;

  /// The force type combining a linear force and a torque.
  pub type Force<N> = Force3<N>;

  /// The inertia tensor type.
  pub type AngularInertia<N> = Matrix3<N>;

  /// The inertia type.
  pub type Inertia<N> = Inertia3<N>;

  /// The inertia matrix type.
  pub type InertiaMatrix<N> = Matrix6<N>;

  /// Square matrix with dimension `SpatialDim × SpatialDim`.
  pub type SpatialMatrix<N> = Matrix6<N>;

  /// The type of a constraint jacobian in twist coordinates.
  pub type Jacobian<N> = MatrixMN<N, U6, Dynamic>;

  /// The type of a slice of the constraint jacobian in twist coordinates.
  pub type JacobianSlice<'a, N> = MatrixSlice6xX<'a, N>;

  /// The type of a mutable slice of the constraint jacobian in twist coordinates.
  pub type JacobianSliceMut<'a, N> = MatrixSliceMut6xX<'a, N>;
}

/// Compilation flags dependent aliases for mathematical types.
#[cfg(feature = "dim2")]
pub mod math {
  use algebra::{Force2, Inertia2, Velocity2};
  use na::{
    Dynamic, Isometry2, Matrix1, Matrix3, MatrixMN, MatrixSlice3xX, MatrixSliceMut3xX, Point2,
    Translation2, UnitComplex, Vector1, Vector2, Vector3, U1, U2, U3,
  };

  /// The maximum number of possible rotations and translations of a rigid body.
  pub const SPATIAL_DIM: usize = 3;
  /// The maximum number of possible rotations of a rigid body.
  pub const ANGULAR_DIM: usize = 1;
  /// The maximum number of possible translations of a rigid body.
  pub const DIM: usize = 2;

  /// The dimension of the ambiant space.
  pub type Dim = U2;

  /// The dimension of the rotation.
  pub type AngularDim = U1;

  /// The dimension of a spatial vector.
  pub type SpatialDim = U3;

  /// The point type.
  pub type Point<N> = Point2<N>;

  /// The vector type with dimension `SpatialDim × 1`.
  pub type SpatialVector<N> = Vector3<N>;

  /// The angular vector type.
  pub type AngularVector<N> = Vector1<N>;

  /// The vector type.
  pub type Vector<N> = Vector2<N>;

  /// The orientation type.
  pub type Orientation<N> = Vector1<N>;

  /// The transformation matrix type.
  pub type Isometry<N> = Isometry2<N>;

  /// The rotation matrix type.
  pub type Rotation<N> = UnitComplex<N>;

  /// The translation type.
  pub type Translation<N> = Translation2<N>;

  /// The velocity type combining the linear velocity and the angular velocity.
  pub type Velocity<N> = Velocity2<N>;

  /// The force type combining a linear force and a torque.
  pub type Force<N> = Force2<N>;

  /// The inertia tensor type.
  pub type AngularInertia<N> = Matrix1<N>;

  /// The inertia type.
  pub type Inertia<N> = Inertia2<N>;

  /// The inertia matrix type.
  pub type InertiaMatrix<N> = Matrix3<N>;

  /// Square matrix with dimension `SpatialDim × SpatialDim`.
  pub type SpatialMatrix<N> = Matrix3<N>;

  /// The type of a constraint jacobian in twist coordinates.
  pub type Jacobian<N> = MatrixMN<N, U3, Dynamic>;

  /// The type of a slice of the constraint jacobian in twist coordinates.
  pub type JacobianSlice<'a, N> = MatrixSlice3xX<'a, N>;

  /// The type of a mutable slice of the constraint jacobian in twist coordinates.
  pub type JacobianSliceMut<'a, N> = MatrixSliceMut3xX<'a, N>;
}
<commit_msg>Remove unused feature<commit_after>/*!
nphysics
========
**nphysics** is a 2 and 3-dimensional physics engine for games and animations.
It uses [ncollide](http://ncollide.org) for collision detection, and
[nalgebra](http://nalgebra.org) for vector/matrix math. 2D and 3D
implementations both share the same code!

Examples are available in the `examples2d` and `examples3d` directories. There
is also a short (outdated) [demonstration video](http://youtu.be/CANjXZ5rocI).
An on-line version of this documentation is available
[here](http://nphysics.org). Feel free to ask for help and discuss features on
the official [user forum](http://users.nphysics.org).

## Why another physics engine?
There are a lot of physics engine out there.
However having a physics engine written in Rust is much more fun than
writing bindings and has several advantages:

- it shows that Rust is suitable for soft real-time applications
- it shows how well Rust behaves with highly generic code
- it shows that there is no need to write two separate engine for 2D and 3D:
  genericity wrt the dimension is possible (modulo low level arithmetic
  specializations for each dimension).
- in a not-that-near future, C++ will die of ugliness. Then, people will
  search for a physics engine and **nphysics** will be there, proudly
  exhibiting its _Rusty_ sexyness.

## Compilation
You will need the latest release of the [Rust compiler](http://www.rust-lang.org)
and the official package manager: [Cargo](https://github.com/rust-lang/cargo).

If you want to use the 2D version of `nphysics`, add the crate named
`nphysics2d` to your dependencies:

```ignore
[dependencies]
nphysics2d = "0.8"
```

For the 3D version, add the crate named `nphysics3d`:

```ignore
[dependencies]
nphysics3d = "0.8"
```

Use `make examples` to build the demos and execute `./your_favorite_example_here --help`
to see all the cool stuffs you can do.

## Features
- Static and dynamic rigid bodies.
- Common convex primitives: cone, box, ball, cylinder.
- Concave geometries build from convex primitives (aka. compound geometries).
- Stable stacking.
- Island based sleeping (objects deactivation).
- Ray casting.
- Swept sphere based continuous collision detection.
- Ball-in-socket joint.
- FixedJoint joint.
- Sensors.

## What is missing?
**nphysics** is a very young library and needs to learn a lot of things to
become a grown up. Many missing features are because of missing features on
**ncollide**. Features missing from **nphysics** itself include:

- kinematic bodies
- efficient signaling system
- more joints, joint limits, joint motors and breakable joints.
- soft-bodies (see https://github.com/natal/roft for a draft)
- parallel pipeline
- GPU-based pipeline

## Dependencies
All dependencies are automatically cloned with a recursive clone.
The libraries needed to compile the physics engine are:

* [ncollide](http://ncollide.org): the collision detection library.
* [nalgebra](http://nalgebra.org): the linear algebra library.

The libraries needed to compile the examples are:

*/
#![deny(non_camel_case_types)]
#![deny(unused_parens)]
#![deny(non_upper_case_globals)]
#![deny(unused_qualifications)]
#![deny(missing_docs)]
#![deny(unused_results)]
#![warn(non_camel_case_types)]
#![allow(missing_copy_implementations)]
#![doc(html_root_url = "http://nphysics.org/rustdoc/")]

#[macro_use]
extern crate approx;
#[macro_use]
extern crate downcast;

extern crate alga;
extern crate nalgebra as na;
#[cfg(feature = "dim2")]
extern crate ncollide2d as ncollide;
#[cfg(feature = "dim3")]
extern crate ncollide3d as ncollide;
extern crate num_traits as num;
extern crate slab;

/*
 * The two following crates are pulled-in for
 * measuring time.
 */
#[cfg(not(any(target_arch = "wasm32", target_arch = "asmjs")))]
extern crate time;

#[cfg(all(
  any(target_arch = "wasm32", target_arch = "asmjs"),
  feature = "stdweb",
))]
#[macro_use]
extern crate stdweb;

#[cfg(all(
  any(target_arch = "wasm32", target_arch = "asmjs"),
  feature = "wasm-bindgen-no-stdweb",
))]
extern crate wasm_bindgen;

//#[cfg(test)]
//extern crate test;

pub mod algebra;
pub mod counters;
pub mod detection;
pub mod force_generator;
pub mod joint;
pub mod object;
pub mod solver;
pub mod utils;
pub mod volumetric;
pub mod world;
// mod tests;

/// Compilation flags dependent aliases for mathematical types.
#[cfg(feature = "dim3")]
pub mod math {
  use algebra::{Force3, Inertia3, Velocity3};
  use na::{
    Dynamic, Isometry3, Matrix3, Matrix6, MatrixMN, MatrixSlice6xX, MatrixSliceMut6xX, Point3,
    Translation3, UnitQuaternion, Vector3, Vector6, U3, U6,
  };

  /// The maximum number of possible rotations and translations of a rigid body.
  pub const SPATIAL_DIM: usize = 6;
  /// The maximum number of possible rotations of a rigid body.
  pub const ANGULAR_DIM: usize = 3;
  /// The maximum number of possible translations of a rigid body.
  pub const DIM: usize = 3;

  /// The dimension of the ambiant space.
  pub type Dim = U3;

  /// The dimension of a spatial vector.
  pub type SpatialDim = U6;

  /// The dimension of the rotations.
  pub type AngularDim = U3;

  /// The point type.
  pub type Point<N> = Point3<N>;

  /// The angular vector type.
  pub type AngularVector<N> = Vector3<N>;

  /// The vector type.
  pub type Vector<N> = Vector3<N>;

  /// The vector type with dimension `SpatialDim × 1`.
  pub type SpatialVector<N> = Vector6<N>;

  /// The orientation type.
  pub type Orientation<N> = Vector3<N>;

  /// The transformation matrix type.
  pub type Isometry<N> = Isometry3<N>;

  /// The rotation matrix type.
  pub type Rotation<N> = UnitQuaternion<N>;

  /// The translation type.
  pub type Translation<N> = Translation3<N>;

  /// The velocity type combining the linear velocity and the angular velocity.
  pub type Velocity<N> = Velocity3<N>;

  /// The force type combining a linear force and a torque.
  pub type Force<N> = Force3<N>;

  /// The inertia tensor type.
  pub type AngularInertia<N> = Matrix3<N>;

  /// The inertia type.
  pub type Inertia<N> = Inertia3<N>;

  /// The inertia matrix type.
  pub type InertiaMatrix<N> = Matrix6<N>;

  /// Square matrix with dimension `SpatialDim × SpatialDim`.
  pub type SpatialMatrix<N> = Matrix6<N>;

  /// The type of a constraint jacobian in twist coordinates.
  pub type Jacobian<N> = MatrixMN<N, U6, Dynamic>;

  /// The type of a slice of the constraint jacobian in twist coordinates.
  pub type JacobianSlice<'a, N> = MatrixSlice6xX<'a, N>;

  /// The type of a mutable slice of the constraint jacobian in twist coordinates.
  pub type JacobianSliceMut<'a, N> = MatrixSliceMut6xX<'a, N>;
}

/// Compilation flags dependent aliases for mathematical types.
#[cfg(feature = "dim2")]
pub mod math {
  use algebra::{Force2, Inertia2, Velocity2};
  use na::{
    Dynamic, Isometry2, Matrix1, Matrix3, MatrixMN, MatrixSlice3xX, MatrixSliceMut3xX, Point2,
    Translation2, UnitComplex, Vector1, Vector2, Vector3, U1, U2, U3,
  };

  /// The maximum number of possible rotations and translations of a rigid body.
  pub const SPATIAL_DIM: usize = 3;
  /// The maximum number of possible rotations of a rigid body.
  pub const ANGULAR_DIM: usize = 1;
  /// The maximum number of possible translations of a rigid body.
  pub const DIM: usize = 2;

  /// The dimension of the ambiant space.
  pub type Dim = U2;

  /// The dimension of the rotation.
  pub type AngularDim = U1;

  /// The dimension of a spatial vector.
  pub type SpatialDim = U3;

  /// The point type.
  pub type Point<N> = Point2<N>;

  /// The vector type with dimension `SpatialDim × 1`.
  pub type SpatialVector<N> = Vector3<N>;

  /// The angular vector type.
  pub type AngularVector<N> = Vector1<N>;

  /// The vector type.
  pub type Vector<N> = Vector2<N>;

  /// The orientation type.
  pub type Orientation<N> = Vector1<N>;

  /// The transformation matrix type.
  pub type Isometry<N> = Isometry2<N>;

  /// The rotation matrix type.
  pub type Rotation<N> = UnitComplex<N>;

  /// The translation type.
  pub type Translation<N> = Translation2<N>;

  /// The velocity type combining the linear velocity and the angular velocity.
  pub type Velocity<N> = Velocity2<N>;

  /// The force type combining a linear force and a torque.
  pub type Force<N> = Force2<N>;

  /// The inertia tensor type.
  pub type AngularInertia<N> = Matrix1<N>;

  /// The inertia type.
  pub type Inertia<N> = Inertia2<N>;

  /// The inertia matrix type.
  pub type InertiaMatrix<N> = Matrix3<N>;

  /// Square matrix with dimension `SpatialDim × SpatialDim`.
  pub type SpatialMatrix<N> = Matrix3<N>;

  /// The type of a constraint jacobian in twist coordinates.
  pub type Jacobian<N> = MatrixMN<N, U3, Dynamic>;

  /// The type of a slice of the constraint jacobian in twist coordinates.
  pub type JacobianSlice<'a, N> = MatrixSlice3xX<'a, N>;

  /// The type of a mutable slice of the constraint jacobian in twist coordinates.
  pub type JacobianSliceMut<'a, N> = MatrixSliceMut3xX<'a, N>;
}
<|endoftext|>


<commit_before>#![no_std]

/// This macros defines a single field of a bitfiled.
///
/// It must be called from an impl and will generates methods. You should not
/// call this macro directly. Use `simple_bitfiled_fields` instead.
#[macro_export]
macro_rules! simple_bitfield_field {
    ($t:ty, _, $setter:ident: $msb:expr, $lsb:expr, $count:expr) => {
        #[allow(unknown_lints)]
        #[allow(eq_op)]
        pub fn $setter(&mut self, index: usize, value: $t) {
            use $crate::BitRange;
            debug_assert!(index < $count);
            let width = $msb - $lsb + 1;
            let lsb = $lsb + index*width;
            let msb = lsb + width - 1;
            self.set_bit_range(msb, lsb, value);
        }
    };
    ($t:ty, _, $setter:ident: $msb:expr, $lsb:expr) => {
        pub fn $setter(&mut self, value: $t) {
            use $crate::BitRange;
            self.set_bit_range($msb, $lsb, value);
        }
    };
    ($t:ty, _, $setter:ident: $bit:expr) => {
        pub fn $setter(&mut self, value: bool) {
            use $crate::Bit;
            self.set_bit($bit, value);
        }
    };
    ($t:ty, $getter:ident, _: $msb:expr, $lsb:expr, $count:expr) => {
        #[allow(unknown_lints)]
        #[allow(eq_op)]
        pub fn $getter(&self, index: usize) -> $t {
            use $crate::BitRange;
            debug_assert!(index < $count);
            let width = $msb - $lsb + 1;
            let lsb = $lsb + index*width;
            let msb = lsb + width - 1;
            self.bit_range(msb, lsb)
        }
    };
    ($t:ty, $getter:ident, _: $msb:expr, $lsb:expr) => {
        pub fn $getter(&self) -> $t {
            use $crate::BitRange;
            self.bit_range($msb, $lsb)
        }
    };
    ($t:ty, $getter:ident, _: $bit:expr) => {
        pub fn $getter(&self) -> bool {
            use $crate::Bit;
            self.bit($bit)
        }
    };
    ($t:ty, $getter:ident, $setter:ident: $($exprs:expr),*) => {
        simple_bitfield_field!($t, $getter, _: $($exprs),*);
        simple_bitfield_field!($t, _, $setter: $($exprs),*);
    };
}

#[macro_export]
macro_rules! simple_bitfield_fields {
    ($t:ty;) => {};
    ($previous_default_ty:ty; $default_ty:ty; $($rest:tt)*) => {
        simple_bitfield_fields!{$default_ty; $($rest)*}
    };
    ($default_ty:ty; $t:ty, $getter:tt, $setter:tt:  $($exprs:expr),*; $($rest:tt)*) => {
        simple_bitfield_field!{$t, $getter, $setter: $($exprs),*}
        simple_bitfield_fields!{$default_ty; $($rest)*}
    };
    ($default_ty:ty; $getter:tt, $setter:tt:  $($exprs:expr),*; $($rest:tt)*) => {
        simple_bitfield_field!{$default_ty, $getter, $setter: $($exprs),*}
        simple_bitfield_fields!{$default_ty; $($rest)*}
    };
}

#[macro_export]
macro_rules! simple_bitfield_struct {
    ($(#[$attribute:meta])* struct $name:ident([$t:ty])) => {
        pub struct $name<T>(pub T);

        impl_bitrange_slice!($name, $t, u8);
        impl_bitrange_slice!($name, $t, u16);
        impl_bitrange_slice!($name, $t, u32);
        impl_bitrange_slice!($name, $t, u64);
    };
    ($(#[$attribute:meta])* struct $name:ident(MSB0 [$t:ty])) => {
        pub struct $name<T>(pub T);

        impl_bitrange_slice_msb0!($name, $t, u8);
        impl_bitrange_slice_msb0!($name, $t, u16);
        impl_bitrange_slice_msb0!($name, $t, u32);
        impl_bitrange_slice_msb0!($name, $t, u64);
    };
    ($(#[$attribute:meta])* struct $name:ident($t:ty)) => {
        $(#[$attribute])*
        pub struct $name(pub $t);

        impl<T> $crate::BitRange<T> for $name where $t: $crate::BitRange<T> {
            fn bit_range(&self, msb: usize, lsb: usize) -> T {
                self.0.bit_range(msb, lsb)
            }
            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T) {
                self.0.set_bit_range(msb, lsb, value);
            }
        }
    };
}

#[macro_export]
macro_rules! simple_bitfield {
    ($(#[$attribute:meta])* struct $name:ident([$t:ty]); $($rest:tt)*) => {
        simple_bitfield_struct!($(#[$attribute])* struct $name([$t]));

        impl<T: AsMut<[$t]> + AsRef<[$t]>> $name<T> {
            simple_bitfield_fields!{u64; $($rest)*}
        }
    };
    ($(#[$attribute:meta])* struct $name:ident(MSB0 [$t:ty]); $($rest:tt)*) => {
        simple_bitfield_struct!($(#[$attribute])* struct $name(MSB0 [$t]));

        impl<T: AsMut<[$t]> + AsRef<[$t]>> $name<T> {
            simple_bitfield_fields!{u64; $($rest)*}
        }
    };
    ($(#[$attribute:meta])* struct $name:ident($t:ty); $($rest:tt)*) => {
        simple_bitfield_struct!($(#[$attribute])* struct $name($t));

        impl $name {
            simple_bitfield_fields!{$t; $($rest)*}
         }
    };
}

#[doc(hidden)]
pub use core::mem::size_of;

/// A trait to get or set ranges of bits.
pub trait BitRange<T> {
    /// Get a range of bits.
    fn bit_range(&self, msb: usize, lsb: usize) -> T;
    /// Set a range of bits.
    fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
}

/// A trait to get or set a single bit.
pub trait Bit {
    /// Get a single bit.
    fn bit(&self, bit: usize) -> bool;

    /// Set a single bit.
    fn set_bit(&mut self, bit: usize, value: bool);
}

impl<T: BitRange<u8>> Bit for T {
    fn bit(&self, bit: usize) -> bool {
        self.bit_range(bit, bit) != 0
    }
    fn set_bit(&mut self, bit: usize, value: bool) {
        self.set_bit_range(bit, bit, value as u8);
    }
}

macro_rules! impl_bitrange_for_u {
    ($t:ty, $bitrange_ty:ty) => {
        impl BitRange<$bitrange_ty> for $t {
            #[inline]
            fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
                let bit_len = size_of::<$t>()*8;
                ((*self << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb)) as $bitrange_ty
            }

            #[inline]
            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
                let bit_len = size_of::<$t>()*8;
                let mask: $t = !(0 as $t)
                    << (bit_len - msb - 1)
                    >> (bit_len - msb - 1 + lsb)
                        << (lsb);
                *self &= !mask;
                *self |= (value as $t << lsb) & mask;
            }
        }
    }
}

impl_bitrange_for_u!{u8, u8}
impl_bitrange_for_u!{u16, u8}
impl_bitrange_for_u!{u16, u16}
impl_bitrange_for_u!{u32, u8}
impl_bitrange_for_u!{u32, u16}
impl_bitrange_for_u!{u32, u32}
impl_bitrange_for_u!{u64, u8}
impl_bitrange_for_u!{u64, u16}
impl_bitrange_for_u!{u64, u32}
impl_bitrange_for_u!{u64, u64}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_bitrange_slice {
    ($name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
        impl<T: AsMut<[$slice_ty]> + AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
            for $name<T> {
            fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
                let bit_len = $crate::size_of::<$slice_ty>()*8;
                let mut value = 0;
                for i in (lsb..msb+1).rev() {
                    value <<= 1;
                    value |= ((self.0.as_ref()[i/bit_len] >> (i%bit_len)) & 1) as $bitrange_ty;
                }
                value
            }

            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
                let bit_len = $crate::size_of::<$slice_ty>()*8;
                let mut value = value;
                for i in lsb..msb+1 {
                    self.0.as_mut()[i/bit_len] &= !(1 << (i%bit_len));
                    self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty << (i%bit_len);
                    value >>= 1;
                }
            }
        }
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_bitrange_slice_msb0 {
    ($name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
        impl<T: AsMut<[$slice_ty]> + AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
            for $name<T> {
            fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
                let bit_len = $crate::size_of::<$slice_ty>()*8;
                let mut value = 0;
                for i in lsb..msb+1 {
                    value <<= 1;
                    value |= ((self.0.as_ref()[i/bit_len] >> (bit_len - i%bit_len - 1)) & 1)
                        as $bitrange_ty;
                }
                value
            }

            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
                let bit_len = $crate::size_of::<$slice_ty>()*8;
                let mut value = value;
                for i in (lsb..msb+1).rev() {
                    self.0.as_mut()[i/bit_len] &= !(1 << (bit_len - i%bit_len - 1));
                    self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty
                        << (bit_len - i%bit_len - 1);
                    value >>= 1;
                }
            }
        }
    }
}
<commit_msg>Add attributes to slice struct<commit_after>#![no_std]

/// This macros defines a single field of a bitfiled.
///
/// It must be called from an impl and will generates methods. You should not
/// call this macro directly. Use `simple_bitfiled_fields` instead.
#[macro_export]
macro_rules! simple_bitfield_field {
    ($t:ty, _, $setter:ident: $msb:expr, $lsb:expr, $count:expr) => {
        #[allow(unknown_lints)]
        #[allow(eq_op)]
        pub fn $setter(&mut self, index: usize, value: $t) {
            use $crate::BitRange;
            debug_assert!(index < $count);
            let width = $msb - $lsb + 1;
            let lsb = $lsb + index*width;
            let msb = lsb + width - 1;
            self.set_bit_range(msb, lsb, value);
        }
    };
    ($t:ty, _, $setter:ident: $msb:expr, $lsb:expr) => {
        pub fn $setter(&mut self, value: $t) {
            use $crate::BitRange;
            self.set_bit_range($msb, $lsb, value);
        }
    };
    ($t:ty, _, $setter:ident: $bit:expr) => {
        pub fn $setter(&mut self, value: bool) {
            use $crate::Bit;
            self.set_bit($bit, value);
        }
    };
    ($t:ty, $getter:ident, _: $msb:expr, $lsb:expr, $count:expr) => {
        #[allow(unknown_lints)]
        #[allow(eq_op)]
        pub fn $getter(&self, index: usize) -> $t {
            use $crate::BitRange;
            debug_assert!(index < $count);
            let width = $msb - $lsb + 1;
            let lsb = $lsb + index*width;
            let msb = lsb + width - 1;
            self.bit_range(msb, lsb)
        }
    };
    ($t:ty, $getter:ident, _: $msb:expr, $lsb:expr) => {
        pub fn $getter(&self) -> $t {
            use $crate::BitRange;
            self.bit_range($msb, $lsb)
        }
    };
    ($t:ty, $getter:ident, _: $bit:expr) => {
        pub fn $getter(&self) -> bool {
            use $crate::Bit;
            self.bit($bit)
        }
    };
    ($t:ty, $getter:ident, $setter:ident: $($exprs:expr),*) => {
        simple_bitfield_field!($t, $getter, _: $($exprs),*);
        simple_bitfield_field!($t, _, $setter: $($exprs),*);
    };
}

#[macro_export]
macro_rules! simple_bitfield_fields {
    ($t:ty;) => {};
    ($previous_default_ty:ty; $default_ty:ty; $($rest:tt)*) => {
        simple_bitfield_fields!{$default_ty; $($rest)*}
    };
    ($default_ty:ty; $t:ty, $getter:tt, $setter:tt:  $($exprs:expr),*; $($rest:tt)*) => {
        simple_bitfield_field!{$t, $getter, $setter: $($exprs),*}
        simple_bitfield_fields!{$default_ty; $($rest)*}
    };
    ($default_ty:ty; $getter:tt, $setter:tt:  $($exprs:expr),*; $($rest:tt)*) => {
        simple_bitfield_field!{$default_ty, $getter, $setter: $($exprs),*}
        simple_bitfield_fields!{$default_ty; $($rest)*}
    };
}

#[macro_export]
macro_rules! simple_bitfield_struct {
    ($(#[$attribute:meta])* struct $name:ident([$t:ty])) => {
        $(#[$attribute])*
        pub struct $name<T>(pub T);

        impl_bitrange_slice!($name, $t, u8);
        impl_bitrange_slice!($name, $t, u16);
        impl_bitrange_slice!($name, $t, u32);
        impl_bitrange_slice!($name, $t, u64);
    };
    ($(#[$attribute:meta])* struct $name:ident(MSB0 [$t:ty])) => {
        $(#[$attribute])*
        pub struct $name<T>(pub T);

        impl_bitrange_slice_msb0!($name, $t, u8);
        impl_bitrange_slice_msb0!($name, $t, u16);
        impl_bitrange_slice_msb0!($name, $t, u32);
        impl_bitrange_slice_msb0!($name, $t, u64);
    };
    ($(#[$attribute:meta])* struct $name:ident($t:ty)) => {
        $(#[$attribute])*
        pub struct $name(pub $t);

        impl<T> $crate::BitRange<T> for $name where $t: $crate::BitRange<T> {
            fn bit_range(&self, msb: usize, lsb: usize) -> T {
                self.0.bit_range(msb, lsb)
            }
            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T) {
                self.0.set_bit_range(msb, lsb, value);
            }
        }
    };
}

#[macro_export]
macro_rules! simple_bitfield {
    ($(#[$attribute:meta])* struct $name:ident([$t:ty]); $($rest:tt)*) => {
        simple_bitfield_struct!($(#[$attribute])* struct $name([$t]));

        impl<T: AsMut<[$t]> + AsRef<[$t]>> $name<T> {
            simple_bitfield_fields!{u64; $($rest)*}
        }
    };
    ($(#[$attribute:meta])* struct $name:ident(MSB0 [$t:ty]); $($rest:tt)*) => {
        simple_bitfield_struct!($(#[$attribute])* struct $name(MSB0 [$t]));

        impl<T: AsMut<[$t]> + AsRef<[$t]>> $name<T> {
            simple_bitfield_fields!{u64; $($rest)*}
        }
    };
    ($(#[$attribute:meta])* struct $name:ident($t:ty); $($rest:tt)*) => {
        simple_bitfield_struct!($(#[$attribute])* struct $name($t));

        impl $name {
            simple_bitfield_fields!{$t; $($rest)*}
         }
    };
}

#[doc(hidden)]
pub use core::mem::size_of;

/// A trait to get or set ranges of bits.
pub trait BitRange<T> {
    /// Get a range of bits.
    fn bit_range(&self, msb: usize, lsb: usize) -> T;
    /// Set a range of bits.
    fn set_bit_range(&mut self, msb: usize, lsb: usize, value: T);
}

/// A trait to get or set a single bit.
pub trait Bit {
    /// Get a single bit.
    fn bit(&self, bit: usize) -> bool;

    /// Set a single bit.
    fn set_bit(&mut self, bit: usize, value: bool);
}

impl<T: BitRange<u8>> Bit for T {
    fn bit(&self, bit: usize) -> bool {
        self.bit_range(bit, bit) != 0
    }
    fn set_bit(&mut self, bit: usize, value: bool) {
        self.set_bit_range(bit, bit, value as u8);
    }
}

macro_rules! impl_bitrange_for_u {
    ($t:ty, $bitrange_ty:ty) => {
        impl BitRange<$bitrange_ty> for $t {
            #[inline]
            fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
                let bit_len = size_of::<$t>()*8;
                ((*self << (bit_len - msb - 1)) >> (bit_len - msb - 1 + lsb)) as $bitrange_ty
            }

            #[inline]
            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
                let bit_len = size_of::<$t>()*8;
                let mask: $t = !(0 as $t)
                    << (bit_len - msb - 1)
                    >> (bit_len - msb - 1 + lsb)
                        << (lsb);
                *self &= !mask;
                *self |= (value as $t << lsb) & mask;
            }
        }
    }
}

impl_bitrange_for_u!{u8, u8}
impl_bitrange_for_u!{u16, u8}
impl_bitrange_for_u!{u16, u16}
impl_bitrange_for_u!{u32, u8}
impl_bitrange_for_u!{u32, u16}
impl_bitrange_for_u!{u32, u32}
impl_bitrange_for_u!{u64, u8}
impl_bitrange_for_u!{u64, u16}
impl_bitrange_for_u!{u64, u32}
impl_bitrange_for_u!{u64, u64}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_bitrange_slice {
    ($name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
        impl<T: AsMut<[$slice_ty]> + AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
            for $name<T> {
            fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
                let bit_len = $crate::size_of::<$slice_ty>()*8;
                let mut value = 0;
                for i in (lsb..msb+1).rev() {
                    value <<= 1;
                    value |= ((self.0.as_ref()[i/bit_len] >> (i%bit_len)) & 1) as $bitrange_ty;
                }
                value
            }

            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
                let bit_len = $crate::size_of::<$slice_ty>()*8;
                let mut value = value;
                for i in lsb..msb+1 {
                    self.0.as_mut()[i/bit_len] &= !(1 << (i%bit_len));
                    self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty << (i%bit_len);
                    value >>= 1;
                }
            }
        }
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_bitrange_slice_msb0 {
    ($name:ident, $slice_ty:ty, $bitrange_ty:ty) => {
        impl<T: AsMut<[$slice_ty]> + AsRef<[$slice_ty]>> $crate::BitRange<$bitrange_ty>
            for $name<T> {
            fn bit_range(&self, msb: usize, lsb: usize) -> $bitrange_ty {
                let bit_len = $crate::size_of::<$slice_ty>()*8;
                let mut value = 0;
                for i in lsb..msb+1 {
                    value <<= 1;
                    value |= ((self.0.as_ref()[i/bit_len] >> (bit_len - i%bit_len - 1)) & 1)
                        as $bitrange_ty;
                }
                value
            }

            fn set_bit_range(&mut self, msb: usize, lsb: usize, value: $bitrange_ty) {
                let bit_len = $crate::size_of::<$slice_ty>()*8;
                let mut value = value;
                for i in (lsb..msb+1).rev() {
                    self.0.as_mut()[i/bit_len] &= !(1 << (bit_len - i%bit_len - 1));
                    self.0.as_mut()[i/bit_len] |= (value & 1) as $slice_ty
                        << (bit_len - i%bit_len - 1);
                    value >>= 1;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate url;
extern crate json_flex;

mod http_request;
mod command_query;
mod result_parser;

pub use http_request::*;
pub use command_query::*;
pub use result_parser::*;
<commit_msg>Export mods more rigidly<commit_after>extern crate hyper;
extern crate url;
extern crate json_flex;

mod http_request;
mod command_query;
mod result_parser;

pub use http_request::HTTPRequest;
pub use command_query::CommandQuery;
pub use result_parser::ResultParser;
<|endoftext|>


<commit_before>#[macro_use] extern crate quick_error;
#[macro_use] extern crate string_cache;
extern crate mime;
extern crate hyper;
extern crate url;
extern crate kuchiki;
extern crate image;

mod strategies;
mod util;

use image::GenericImage;
use strategies::Strategy;
use std::io::Read;
use util::AsImageFormat;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Hyper(error: hyper::Error) { from() }
        Io(error: std::io::Error) { from() }
        Image(error: image::ImageError) { from() }
        Other(msg: String) {
            description(msg)
        }
    }
}

pub struct IconScraper {
    pub document_url: url::Url,
    pub dom: Option<kuchiki::NodeRef>,
    pub icons: Vec<Icon>
}

impl IconScraper {
    pub fn from_url(url: url::Url) -> Self {
        IconScraper {
            document_url: url,
            dom: None,
            icons: vec![];
        }
    }

    pub fn fetch_document(&mut self) -> Result<(), Error> {
        let client = hyper::client::Client::new();
        let mut response = try!(client.get(self.document_url.clone()).send());
        let parser = try!(kuchiki::Html::from_stream(&mut response));
        self.dom = Some(parser.parse());
        Ok(())
    }

    pub fn fetch_icons(&mut self) {
        self.icons = strategies::LinkRelStrategy.get_guesses(&mut self)
            .into_iter()
            .chain(strategies::DefaultFaviconPathStrategy.get_guesses(&mut self).into_iter())
            .filter_map(|mut icon| if icon.fetch_dimensions().is_ok() { Some(icon) } else { None })
            .collect::<Vec<_>>();

        self.icons.sort_by(|a, b| {
            (a.width.unwrap() * a.height.unwrap())
                .cmp(&(b.width.unwrap() * b.height.unwrap()))
        });
    }

    pub fn at_least(self, width: u32, height: u32) -> Option<Icon> {
        self.icons
            .into_iter()
            .skip_while(|icon| icon.width.unwrap() < width || icon.height.unwrap() < height)
            .next()
    }

    pub fn largest(self) -> Option<Icon> {
        if self.icons.len() > 0 {
            Some(self.icons[self.icons.len() - 1])
        }
    }
}

pub struct Icon {
    pub url: url::Url,
    pub raw: Option<Vec<u8>>,
    pub mime_type: Option<mime::Mime>,
    pub width: Option<u32>,
    pub height: Option<u32>
}

impl Icon {
    pub fn from_url(url: url::Url) -> Self {
        Icon {
            url: url,
            raw: None,
            mime_type: None,
            width: None,
            height: None
        }
    }

    pub fn fetch(&mut self) -> Result<(), Error> {
        let client = hyper::client::Client::new();
        let mut response = try!(client.get(self.url.clone()).send());

        let mut bytes: Vec<u8> = vec![];
        try!(response.read_to_end(&mut bytes));
        if !response.status.is_success() {
            return Err(Error::Other(format!("Bad status code: {:?}", response.status)));
        }

        let mime_type: mime::Mime = match response.headers.get::<hyper::header::ContentType>() {
            Some(x) => x.clone().0,
            None => return Err(Error::Other("No Content-Type found.".to_owned()))
        };
        let image_format = match mime_type.as_image_format() {
            Some(x) => x,
            None => return Err(Error::Other(format!("Invalid image type: {:?}", mime_type)))
        };
        let image = try!(image::load_from_memory_with_format(&bytes, image_format));

        self.width = Some(image.width());
        self.height = Some(image.height());
        self.raw = Some(bytes);
        self.mime_type = Some(mime_type);
        Ok(())
    }

    pub fn fetch_dimensions(&mut self) -> Result<(), Error> {
        match (self.width, self.height) {
            (Some(_), Some(_)) => Ok(()),
            _ => self.fetch()
        }
    }
}
<commit_msg>Fix syntax error<commit_after>#[macro_use] extern crate quick_error;
#[macro_use] extern crate string_cache;
extern crate mime;
extern crate hyper;
extern crate url;
extern crate kuchiki;
extern crate image;

mod strategies;
mod util;

use image::GenericImage;
use strategies::Strategy;
use std::io::Read;
use util::AsImageFormat;

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        Hyper(error: hyper::Error) { from() }
        Io(error: std::io::Error) { from() }
        Image(error: image::ImageError) { from() }
        Other(msg: String) {
            description(msg)
        }
    }
}

pub struct IconScraper {
    pub document_url: url::Url,
    pub dom: Option<kuchiki::NodeRef>,
    pub icons: Vec<Icon>
}

impl IconScraper {
    pub fn from_url(url: url::Url) -> Self {
        IconScraper {
            document_url: url,
            dom: None,
            icons: vec![]
        }
    }

    pub fn fetch_document(&mut self) -> Result<(), Error> {
        let client = hyper::client::Client::new();
        let mut response = try!(client.get(self.document_url.clone()).send());
        let parser = try!(kuchiki::Html::from_stream(&mut response));
        self.dom = Some(parser.parse());
        Ok(())
    }

    pub fn fetch_icons(&mut self) {
        self.icons = strategies::LinkRelStrategy.get_guesses(&mut self)
            .into_iter()
            .chain(strategies::DefaultFaviconPathStrategy.get_guesses(&mut self).into_iter())
            .filter_map(|mut icon| if icon.fetch_dimensions().is_ok() { Some(icon) } else { None })
            .collect::<Vec<_>>();

        self.icons.sort_by(|a, b| {
            (a.width.unwrap() * a.height.unwrap())
                .cmp(&(b.width.unwrap() * b.height.unwrap()))
        });
    }

    pub fn at_least(self, width: u32, height: u32) -> Option<Icon> {
        self.icons
            .into_iter()
            .skip_while(|icon| icon.width.unwrap() < width || icon.height.unwrap() < height)
            .next()
    }

    pub fn largest(self) -> Option<Icon> {
        if self.icons.len() > 0 {
            Some(self.icons[self.icons.len() - 1])
        }
    }
}

pub struct Icon {
    pub url: url::Url,
    pub raw: Option<Vec<u8>>,
    pub mime_type: Option<mime::Mime>,
    pub width: Option<u32>,
    pub height: Option<u32>
}

impl Icon {
    pub fn from_url(url: url::Url) -> Self {
        Icon {
            url: url,
            raw: None,
            mime_type: None,
            width: None,
            height: None
        }
    }

    pub fn fetch(&mut self) -> Result<(), Error> {
        let client = hyper::client::Client::new();
        let mut response = try!(client.get(self.url.clone()).send());

        let mut bytes: Vec<u8> = vec![];
        try!(response.read_to_end(&mut bytes));
        if !response.status.is_success() {
            return Err(Error::Other(format!("Bad status code: {:?}", response.status)));
        }

        let mime_type: mime::Mime = match response.headers.get::<hyper::header::ContentType>() {
            Some(x) => x.clone().0,
            None => return Err(Error::Other("No Content-Type found.".to_owned()))
        };
        let image_format = match mime_type.as_image_format() {
            Some(x) => x,
            None => return Err(Error::Other(format!("Invalid image type: {:?}", mime_type)))
        };
        let image = try!(image::load_from_memory_with_format(&bytes, image_format));

        self.width = Some(image.width());
        self.height = Some(image.height());
        self.raw = Some(bytes);
        self.mime_type = Some(mime_type);
        Ok(())
    }

    pub fn fetch_dimensions(&mut self) -> Result<(), Error> {
        match (self.width, self.height) {
            (Some(_), Some(_)) => Ok(()),
            _ => self.fetch()
        }
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

//! A C-style `for` loop in macro form.
//!
//! This takes the form `cfor!(initialiser; condition; step { body })`.
//!
//! - `initialiser` is a statement evaluated before any iterations of
//!   the loop. Any variables declared here are scoped to the `cfor!`
//!   invocation, that is, only usable inside `condition`, `step` and
//!   `body`.
//! - `condition` is an boolean expression evaluated at the start of
//!   each iteration. If it evaluates to `false` iteration will stop.
//! - `step` is an arbitrary expression which is executed at the end
//!   of each iteration (including if `continue` is called), before
//!   `condition` is checked.
//!
//!
//! The initialiser and condition can be empty like C, but the step
//! cannot unlike C. A `for` loop with no step is identical to a
//! `while` loop.
//!
//! [*Source & issue tracker*](https://github.com/huonw/cfor/)
//!
//! # When should I use it?
//!
//! *Only* when `cfor!` is clearer than the more declarative built-in
//! [iterators](http://doc.rust-lang.org/master/std/iter/), [their
//! adaptors](http://doc.rust-lang.org/master/std/iter/trait.Iterator.html)
//! and the `for` loop. For example, the built-in iterator
//! functionality is more self-contained so there is less risk of
//! accidentally writing `i` in a condition when `j` was meant (I
//! personally get bitten by this semiregularly when writing nested
//! "2D" loops in C).
//!
//! Furthermore, the adaptor methods linked above allow [one to
//! write](http://huonw.github.io/2014/06/10/knn-rust.html) concise,
//! performant, reusable "functional" code in a way that is not
//! possible to achieve using C-style iteration.
//!
//! # How to use it?
//!
//! Add the repository as a normal cargo dependency, and include into
//! your crate with `#[phase(plugin)]`. (See examples below.)
//!
//! ```toml
//! [dependencies.cfor]
//! git = "https://github.com/huonw/cfor"
//! ```
//!
//! # Examples
//!
//! ## Simple
//!
//! A non-additive condition is not handled extremely naturally by
//! `std::iter`, but is straight-forward to handle directly.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1u; x < 0x1000; x *= 2 {
//!         println!("power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Intrabody condition
//!
//! If a condition requires some extra computation to be checked (or
//! if there is some code that should always be evaluated, even if the
//! condition will be `false` for a given iteration), the condition in
//! the `cfor` header can be omitted.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1u; ; x *= 2 {
//!         // ... setup ...
//!         println!("handling power of 2: {}", x);
//!
//!         if x < 0x1000 { break }
//!
//!         // ... further handling ...
//!         println!("handling power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Out-of-loop initialisation
//!
//! Sometimes one may wish to have access to a variable outside the
//! loop after it finishes so it has to be declared outside the loop,
//! or one may be iterating over some presupplied/-computed value so
//! there is no meaningful additional initialisation possible. The
//! initialisation expression can be safely omitted in this case.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! use std::rand;
//!
//! fn main() {
//!     let mut x = 1u16;
//!
//!     cfor!{; x < 0x1000; x *= 2 {
//!         println!("power of 2: {}", x);
//!
//!         // sometimes quit early
//!         if x > rand::random() { break }
//!     }}
//!
//!     println!("actually stopped at {}", x);
//! }
//! ```
//!
//! # Handling `continue`
//!
//! (Or, "why is the macro so complicated?")
//!
//! Special effort is made to ensure that `continue` acts correctly, a
//! naive macro defined as follows will cause `continue` to also skip
//! evaluating `step`, likely leading to undesirable behaviour like
//! infinite loops.
//!
//! ```rust
//! #![feature(macro_rules)]
//!
//! // WARNING: this is broken.
//! macro_rules! bad_cfor {
//!     ($init: stmt; $cond: expr; $step: expr $body: block) => {
//!         {
//!             $init;
//!             while $cond {
//!                 $body;
//!
//!                 $step;
//!             }
//!         }
//!     }
//! }
//!
//! fn main() {
//!     let mut true_counter = 0u;
//!
//!     bad_cfor!{let mut i = 0u; i < 10; i += 1 {
//!
//!         // manually avoid the infinite loop
//!         if true_counter >= 50 { break }
//!         true_counter += 1;
//!
//!         println!("i = {}", i);
//!         // try to skip just i == 4
//!         if i == 4 {
//!             // but this skips the i += 1 leaving us
//!             // on i == 4 forever.
//!             continue
//!         }
//!         // ...more code...
//!     }}
//! }
//! ```
//!
//! This is invoked in the same manner as `cfor!`, but, if `$body`
//! contains a `continue`, the `$step` at the end of the loop body
//! will never be evaluated.

/// A C-style `for` loop in macro form.
///
/// See crates docs for more information.
#[macro_export]
pub macro_rules! cfor {
    // for (; ...; ...) { ... }
    (; $($rest: tt)*) => {
        cfor!((); $($rest)*)
    };
    // for ($init; ; ...) { ... }
    ($init: stmt; ; $($rest: tt)*) => {
        // avoid the `while true` lint
        cfor!($init; !false; $($rest)*)
    };

    // for ($init; $cond; $step) { $body }
    ($init: stmt; $cond: expr; $step: expr $body: block) => {
        {
            $init;
            while $cond {
                let mut _first = true;
                let mut _continue = false;
                // this loop runs once, allowing us to use `break` and
                // `continue` as `goto` to skip forward to the
                // condition.
                //
                // the booleans above are very transparent to the
                // optimiser, since they are modified exactly once,
                // with nice control flow, and this this optimises to
                // be similar to C for loop.
                loop {
                    // if we *don't* hit this, there was a `break` in
                    // the body (otherwise the loop fell-through or
                    // was `continue`d.)
                    if !_first { _continue = true; break }
                    _first = false;

                    $body
                }
                if !_continue {
                    // the `if` wasn't hit, so we should propagate the
                    // `break`.
                    break
                }

                $step
            }
        }
    };
}
<commit_msg>Make the doc tests pass.<commit_after>#![feature(macro_rules)]

//! A C-style `for` loop in macro form.
//!
//! This takes the form `cfor!(initialiser; condition; step { body })`.
//!
//! - `initialiser` is a statement evaluated before any iterations of
//!   the loop. Any variables declared here are scoped to the `cfor!`
//!   invocation, that is, only usable inside `condition`, `step` and
//!   `body`.
//! - `condition` is an boolean expression evaluated at the start of
//!   each iteration. If it evaluates to `false` iteration will stop.
//! - `step` is an arbitrary expression which is executed at the end
//!   of each iteration (including if `continue` is called), before
//!   `condition` is checked.
//!
//!
//! The initialiser and condition can be empty like C, but the step
//! cannot unlike C. A `for` loop with no step is identical to a
//! `while` loop.
//!
//! [*Source & issue tracker*](https://github.com/huonw/cfor/)
//!
//! # When should I use it?
//!
//! *Only* when `cfor!` is clearer than the more declarative built-in
//! [iterators](http://doc.rust-lang.org/master/std/iter/), [their
//! adaptors](http://doc.rust-lang.org/master/std/iter/trait.Iterator.html)
//! and the `for` loop. For example, the built-in iterator
//! functionality is more self-contained so there is less risk of
//! accidentally writing `i` in a condition when `j` was meant (I
//! personally get bitten by this semiregularly when writing nested
//! "2D" loops in C).
//!
//! Furthermore, the adaptor methods linked above allow [one to
//! write](http://huonw.github.io/2014/06/10/knn-rust.html) concise,
//! performant, reusable "functional" code in a way that is not
//! possible to achieve using C-style iteration.
//!
//! # How to use it?
//!
//! Add the repository as a normal cargo dependency, and include into
//! your crate with `#[phase(plugin)]`. (See examples below.)
//!
//! ```toml
//! [dependencies.cfor]
//! git = "https://github.com/huonw/cfor"
//! ```
//!
//! # Examples
//!
//! ## Simple
//!
//! A non-additive condition is not handled extremely naturally by
//! `std::iter`, but is straight-forward to handle directly.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1u; x < 0x1000; x *= 2 {
//!         println!("power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Intrabody condition
//!
//! If a condition requires some extra computation to be checked (or
//! if there is some code that should always be evaluated, even if the
//! condition will be `false` for a given iteration), the condition in
//! the `cfor` header can be omitted.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! fn main() {
//!     cfor!{let mut x = 1u; ; x *= 2 {
//!         // ... setup ...
//!         println!("handling power of 2: {}", x);
//!
//!         if x < 0x1000 { break }
//!
//!         // ... further handling ...
//!         println!("handling power of 2: {}", x);
//!     }}
//! }
//! ```
//!
//! ## Out-of-loop initialisation
//!
//! Sometimes one may wish to have access to a variable outside the
//! loop after it finishes so it has to be declared outside the loop,
//! or one may be iterating over some presupplied/-computed value so
//! there is no meaningful additional initialisation possible. The
//! initialisation expression can be safely omitted in this case.
//!
//! ```rust
//! #![feature(phase)]
//! #[phase(plugin)] extern crate cfor;
//!
//! use std::rand;
//!
//! fn main() {
//!     let mut x = 1u16;
//!
//!     cfor!{; x < 0x1000; x *= 2 {
//!         println!("power of 2: {}", x);
//!
//!         // sometimes quit early
//!         if x > rand::random() { break }
//!     }}
//!
//!     println!("actually stopped at {}", x);
//! }
//! ```
//!
//! # Handling `continue`
//!
//! (Or, "why is the macro so complicated?")
//!
//! Special effort is made to ensure that `continue` acts correctly, a
//! naive macro defined as follows will cause `continue` to also skip
//! evaluating `step`, likely leading to undesirable behaviour like
//! infinite loops.
//!
//! ```rust
//! #![feature(macro_rules)]
//!
//! # // avoid our crate being inserted automatically, which gets in
//! # // the way of the feature above.
//! # #![feature(phase)] #[phase(plugin)] extern crate cfor;
//! #
//! // WARNING: this is broken.
//! macro_rules! bad_cfor {
//!     ($init: stmt; $cond: expr; $step: expr $body: block) => {
//!         {
//!             $init;
//!             while $cond {
//!                 $body;
//!
//!                 $step;
//!             }
//!         }
//!     }
//! }
//!
//! fn main() {
//!     let mut true_counter = 0u;
//!
//!     bad_cfor!{let mut i = 0u; i < 10; i += 1 {
//!
//!         // manually avoid the infinite loop
//!         if true_counter >= 50 { break }
//!         true_counter += 1;
//!
//!         println!("i = {}", i);
//!         // try to skip just i == 4
//!         if i == 4 {
//!             // but this skips the i += 1 leaving us
//!             // on i == 4 forever.
//!             continue
//!         }
//!         // ...more code...
//!     }}
//! }
//! ```
//!
//! This is invoked in the same manner as `cfor!`, but, if `$body`
//! contains a `continue`, the `$step` at the end of the loop body
//! will never be evaluated.

/// A C-style `for` loop in macro form.
///
/// See crates docs for more information.
#[macro_export]
pub macro_rules! cfor {
    // for (; ...; ...) { ... }
    (; $($rest: tt)*) => {
        cfor!((); $($rest)*)
    };
    // for ($init; ; ...) { ... }
    ($init: stmt; ; $($rest: tt)*) => {
        // avoid the `while true` lint
        cfor!($init; !false; $($rest)*)
    };

    // for ($init; $cond; $step) { $body }
    ($init: stmt; $cond: expr; $step: expr $body: block) => {
        {
            $init;
            while $cond {
                let mut _first = true;
                let mut _continue = false;
                // this loop runs once, allowing us to use `break` and
                // `continue` as `goto` to skip forward to the
                // condition.
                //
                // the booleans above are very transparent to the
                // optimiser, since they are modified exactly once,
                // with nice control flow, and this this optimises to
                // be similar to C for loop.
                loop {
                    // if we *don't* hit this, there was a `break` in
                    // the body (otherwise the loop fell-through or
                    // was `continue`d.)
                    if !_first { _continue = true; break }
                    _first = false;

                    $body
                }
                if !_continue {
                    // the `if` wasn't hit, so we should propagate the
                    // `break`.
                    break
                }

                $step
            }
        }
    };
}
<|endoftext|>


<commit_before>//! This crate provides an iterator adaptor that yields sliding windows into the elements of the wrapped Iterator.
//!
//! Note that this adaptor does **NOT** clone the whole window on every call to `next()`.
//!
//! As a consequence it violates the Iterator protocol slightly. It is not possible to have two Windows into the data
//! available at the same time. This is checked during runtime. If this check fails, the Adaptor panicks in ```next()```.
//! More information can be found in the section [Panics](#panics).
//!
//! There are some options regarding the constructor for Storage, which affect performance greatly.
//! Consult the [docs for Storage](struct.Storage.html) for details.
//!
//! Iterator element type is `Window<'a, Self::Item>`.
//!
//! Note: `Window<'a, Self::Item>` dereferences to `&'a [Self::Item]` or `&'a mut [Self::Item]`
//!
//! This iterator is *fused*.
//!
//! # Example:
//!
//! ```
//! use sliding_windows::IterExt;
//! use sliding_windows::Storage;
//!
//! let iter = 0..5;
//! let mut storage: Storage<u32> = Storage::optimized(&iter, 3);
//! let windowed_iter = iter.sliding_windows(&mut storage);
//! let output: Vec<Vec<u32>> = windowed_iter.map(|x| From::from(&x[..])).collect();
//! let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]];
//!
//! assert_eq!(output, expected);
//! ```
//!
//! It's also possible to reuse an allocation for `Storage` via the `Into` trait.
//!
//! # Example:
//!
//! ```
//! use sliding_windows::IterExt;
//! use sliding_windows::Storage;
//!
//! let previous_alloca = vec![0u32; 3]; // length doesn't have to be equal to window_size
//! let mut storage: Storage<u32> = Storage::from_vec(previous_alloca, 3);
//! let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]];
//!
//! // extra scope so that windowed_iter doesn't outlive storage.into() call
//! {
//!     let windowed_iter = (0..5).sliding_windows(&mut storage);
//!     let output: Vec<Vec<u32>> = windowed_iter.map(|x| From::from(&x[..])).collect();
//!     assert_eq!(output, expected);
//! }
//!
//! let reusing_alloca: Vec<u32> = storage.into();
//! // keep using allocation of storage
//!
//! ```
//!
//! ### Panics:
//!
//! As this iterator reuses the allocation for the yielded `Window`, no two instances of `Window`
//! belonging to the same iterator may exist simultaneously. As noted above this is checked at runtime.
//!
//! ```
//! use sliding_windows::IterExt;
//! use sliding_windows::Storage;
//!
//! let mut storage: Storage<u32> = Storage::new(3);
//! let mut windowed_iter = (0..5).sliding_windows(&mut storage);
//!
//! // extra scope so that a doesn't live until the for loop
//! {
//!     let a = windowed_iter.next();
//!     //let b = windowed_iter.next(); => this would PANIC
//! }
//!
//! // looping for example is fine though
//! for _ in windowed_iter {
//!     // blah
//! }
//! ```
//!
//! # Mutable Window:
//!
//! Window does not only dereference to an immutable slice of `Self::Item`, it also dereferences
//! to a mutable slice of `Self::Item`. Items of the mutable slice may be mutated freely.
//!
//! However be aware that changes made to the items in the Window are persistent through calls to `next()`.

mod sliding_windows;
#[cfg(test)]
mod tests;

pub use sliding_windows::{
    Storage, Adaptor };

pub trait IterExt: Iterator {
    fn sliding_windows(self, storage: &mut Storage<Self::Item>)
        -> Adaptor<Self>
        where Self: Sized
    {
        Adaptor::new(self, storage)
    }
}

impl<T: ?Sized> IterExt for T where T: Iterator { }
<commit_msg>fix docs<commit_after>//! This crate provides an iterator adaptor that yields sliding windows into the elements of the wrapped Iterator.
//!
//! Note that this adaptor does **NEVER** clone any element for huge speed gains.
//!
//! As a consequence it violates the Iterator protocol slightly. It is not possible to have two Windows into the data
//! available at the same time. This is checked during runtime. If this check fails, the Adaptor panicks in ```next()```.
//! More information can be found in the section [Panics](#panics).
//!
//! There are some options regarding the constructor for Storage, which allow reuse of an allocation.
//! Consult the [docs for Storage](struct.Storage.html) for details.
//!
//! Iterator element type is `Window<'a, Self::Item>`.
//!
//! Note: `Window<'a, Self::Item>` implements `iter()` and `iter_mut()`, which return Iterators over the elements of the `Window`.
//!
//! This iterator is *fused*.
//!
//! # Example:
//!
//! ```
//! use sliding_windows::IterExt;
//! use sliding_windows::Storage;
//!
//! let iter = 0..5;
//! let mut storage: Storage<u32> = Storage::new(3);
//! let windowed_iter = iter.sliding_windows(&mut storage);
//! let output: Vec<Vec<u32>> = windowed_iter.map(|x| x.iter().map(|&x| x).collect()).collect();
//! let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]];
//!
//! assert_eq!(output, expected);
//! ```
//!
//! It's also possible to reuse an allocation for `Storage` via the `Into` trait.
//!
//! # Example:
//!
//! ```
//! use sliding_windows::IterExt;
//! use sliding_windows::Storage;
//!
//! let previous_alloca = vec![0u32; 3]; // length doesn't have to be equal to window_size
//! let mut storage: Storage<u32> = Storage::from_vec(previous_alloca, 3);
//! let expected: &[&[u32]] = &[&[0,1,2], &[1,2,3], &[2,3,4]];
//!
//! // extra scope so that windowed_iter doesn't outlive storage.into() call
//! {
//!     let windowed_iter = (0..5).sliding_windows(&mut storage);
//!     let output: Vec<Vec<u32>> = windowed_iter.map(|x| x.iter().map(|&x| x).collect()).collect();
//!     assert_eq!(output, expected);
//! }
//!
//! let reusing_alloca: Vec<u32> = storage.into();
//! // keep using allocation of storage
//!
//! ```
//!
//! ### Panics:
//!
//! As this iterator reuses the allocation for the yielded `Window`, no two instances of `Window`
//! belonging to the same iterator may exist simultaneously. As noted above this is checked at runtime.
//!
//! ```
//! use sliding_windows::IterExt;
//! use sliding_windows::Storage;
//!
//! let mut storage: Storage<u32> = Storage::new(3);
//! let mut windowed_iter = (0..5).sliding_windows(&mut storage);
//!
//! // extra scope so that a doesn't live until the for loop
//! {
//!     let a = windowed_iter.next();
//!     //let b = windowed_iter.next(); => this would PANIC
//! }
//!
//! // looping for example is fine though
//! for _ in windowed_iter {
//!     // blah
//! }
//! ```
//!
//! # Mutable Window:
//!
//! There is an implementation of an Iterator over `&'a mut T` for `Window<'a, T>`. It can be obtained
//! by calling `iter_mut()`. For more information see [`Window<'a, T>`](struct.Window.html).
//!
//! However be aware that changes made to the items in the Window are persistent through calls to `next()`.

mod sliding_windows;
#[cfg(test)]
mod tests;

pub use sliding_windows::{
    Storage, Adaptor };

pub trait IterExt: Iterator {
    fn sliding_windows(self, storage: &mut Storage<Self::Item>)
        -> Adaptor<Self>
        where Self: Sized
    {
        Adaptor::new(self, storage)
    }
}

impl<T: ?Sized> IterExt for T where T: Iterator { }
<|endoftext|>