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

/*!
 * A simple map based on a vector for small integer keys. Space requirements
 * are O(highest integer key).
 */
#[forbid(deprecated_mode)];

use core::container::{Container, Mutable, Map, Set};
use core::dvec::DVec;
use core::ops;
use core::option::{Some, None};
use core::option;
use core::prelude::*;

// FIXME (#2347): Should not be @; there's a bug somewhere in rustc that
// requires this to be.
struct SmallIntMap_<T> {
    v: DVec<Option<T>>,
}

pub enum SmallIntMap<T> {
    SmallIntMap_(@SmallIntMap_<T>)
}

/// Create a smallintmap
pub fn mk<T: Copy>() -> SmallIntMap<T> {
    let v = DVec();
    SmallIntMap_(@SmallIntMap_ { v: v } )
}

/**
 * Add a value to the map. If the map already contains a value for
 * the specified key then the original value is replaced.
 */
#[inline(always)]
pub fn insert<T: Copy>(self: SmallIntMap<T>, key: uint, val: T) {
    //io::println(fmt!("%?", key));
    self.v.grow_set_elt(key, &None, Some(val));
}

/**
 * Get the value for the specified key. If the key does not exist
 * in the map then returns none
 */
pub pure fn find<T: Copy>(self: SmallIntMap<T>, key: uint) -> Option<T> {
    if key < self.v.len() { return self.v.get_elt(key); }
    return None::<T>;
}

/**
 * Get the value for the specified key
 *
 * # Failure
 *
 * If the key does not exist in the map
 */
pub pure fn get<T: Copy>(self: SmallIntMap<T>, key: uint) -> T {
    match find(self, key) {
      None => {
        error!("smallintmap::get(): key not present");
        die!();
      }
      Some(move v) => return v
    }
}

/// Returns true if the map contains a value for the specified key
pub pure fn contains_key<T: Copy>(self: SmallIntMap<T>, key: uint) -> bool {
    return !find(self, key).is_none();
}

impl<V> SmallIntMap<V>: Container {
    /// Return the number of elements in the map
    pure fn len(&self) -> uint {
        let mut sz = 0u;
        for self.v.each |item| {
            match *item {
              Some(_) => sz += 1u,
              _ => ()
            }
        }
        sz
    }

    /// Return true if the map contains no elements
    pure fn is_empty(&self) -> bool { self.len() == 0 }
}

/// Implements the map::map interface for smallintmap
impl<V: Copy> SmallIntMap<V> {
    #[inline(always)]
    fn insert(key: uint, value: V) -> bool {
        let exists = contains_key(self, key);
        insert(self, key, value);
        return !exists;
    }
    fn remove(key: uint) -> bool {
        if key >= self.v.len() {
            return false;
        }
        let old = self.v.get_elt(key);
        self.v.set_elt(key, None);
        old.is_some()
    }
    fn clear() {
        self.v.set(~[]);
    }
    pure fn contains_key(key: uint) -> bool {
        contains_key(self, key)
    }
    pure fn contains_key_ref(key: &uint) -> bool {
        contains_key(self, *key)
    }
    pure fn get(key: uint) -> V { get(self, key) }
    pure fn find(key: uint) -> Option<V> { find(self, key) }

    fn update_with_key(key: uint, val: V, ff: fn(uint, V, V) -> V) -> bool {
        match self.find(key) {
            None            => return self.insert(key, val),
            Some(copy orig) => return self.insert(key, ff(key, orig, val)),
        }
    }

    fn update(key: uint, newval: V, ff: fn(V, V) -> V) -> bool {
        return self.update_with_key(key, newval, |_k, v, v1| ff(v,v1));
    }

    pure fn each(it: fn(key: uint, value: V) -> bool) {
        self.each_ref(|k, v| it(*k, *v))
    }
    pure fn each_key(it: fn(key: uint) -> bool) {
        self.each_ref(|k, _v| it(*k))
    }
    pure fn each_value(it: fn(value: V) -> bool) {
        self.each_ref(|_k, v| it(*v))
    }
    pure fn each_ref(it: fn(key: &uint, value: &V) -> bool) {
        let mut idx = 0u, l = self.v.len();
        while idx < l {
            match self.v.get_elt(idx) {
              Some(ref elt) => if !it(&idx, elt) { break },
              None => ()
            }
            idx += 1u;
        }
    }
    pure fn each_key_ref(blk: fn(key: &uint) -> bool) {
        self.each_ref(|k, _v| blk(k))
    }
    pure fn each_value_ref(blk: fn(value: &V) -> bool) {
        self.each_ref(|_k, v| blk(v))
    }
}

impl<V: Copy> SmallIntMap<V>: ops::Index<uint, V> {
    pure fn index(&self, key: uint) -> V {
        unsafe {
            get(*self, key)
        }
    }
}

#[cfg(test)]
mod tests {
    use smallintmap::{mk, SmallIntMap};

    use core::option::None;

    #[test]
    fn test_len() {
        let mut map = mk();
        assert map.len() == 0;
        assert map.is_empty();
        map.insert(5, 20);
        assert map.len() == 1;
        assert !map.is_empty();
        map.insert(11, 12);
        assert map.len() == 2;
        assert !map.is_empty();
        map.insert(14, 22);
        assert map.len() == 3;
        assert !map.is_empty();
    }

    #[test]
    fn test_insert_with_key() {
        let map: SmallIntMap<uint> = mk();

        // given a new key, initialize it with this new count, given
        // given an existing key, add more to its count
        fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        fn addMoreToCount_simple(v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        // count integers
        map.update(3, 1, addMoreToCount_simple);
        map.update_with_key(9, 1, addMoreToCount);
        map.update(3, 7, addMoreToCount_simple);
        map.update_with_key(5, 3, addMoreToCount);
        map.update_with_key(3, 2, addMoreToCount);

        // check the total counts
        assert map.find(3).get() == 10;
        assert map.find(5).get() == 3;
        assert map.find(9).get() == 1;

        // sadly, no sevens were counted
        assert None == map.find(7);
    }
}
<commit_msg>implement container::Mutable for SmallIntMap<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!
 * A simple map based on a vector for small integer keys. Space requirements
 * are O(highest integer key).
 */
#[forbid(deprecated_mode)];

use core::container::{Container, Mutable, Map, Set};
use core::dvec::DVec;
use core::ops;
use core::option::{Some, None};
use core::option;
use core::prelude::*;

// FIXME (#2347): Should not be @; there's a bug somewhere in rustc that
// requires this to be.
struct SmallIntMap_<T> {
    v: DVec<Option<T>>,
}

pub enum SmallIntMap<T> {
    SmallIntMap_(@SmallIntMap_<T>)
}

/// Create a smallintmap
pub fn mk<T: Copy>() -> SmallIntMap<T> {
    let v = DVec();
    SmallIntMap_(@SmallIntMap_ { v: v } )
}

/**
 * Add a value to the map. If the map already contains a value for
 * the specified key then the original value is replaced.
 */
#[inline(always)]
pub fn insert<T: Copy>(self: SmallIntMap<T>, key: uint, val: T) {
    //io::println(fmt!("%?", key));
    self.v.grow_set_elt(key, &None, Some(val));
}

/**
 * Get the value for the specified key. If the key does not exist
 * in the map then returns none
 */
pub pure fn find<T: Copy>(self: SmallIntMap<T>, key: uint) -> Option<T> {
    if key < self.v.len() { return self.v.get_elt(key); }
    return None::<T>;
}

/**
 * Get the value for the specified key
 *
 * # Failure
 *
 * If the key does not exist in the map
 */
pub pure fn get<T: Copy>(self: SmallIntMap<T>, key: uint) -> T {
    match find(self, key) {
      None => {
        error!("smallintmap::get(): key not present");
        die!();
      }
      Some(move v) => return v
    }
}

/// Returns true if the map contains a value for the specified key
pub pure fn contains_key<T: Copy>(self: SmallIntMap<T>, key: uint) -> bool {
    return !find(self, key).is_none();
}

impl<V> SmallIntMap<V>: Container {
    /// Return the number of elements in the map
    pure fn len(&self) -> uint {
        let mut sz = 0u;
        for self.v.each |item| {
            match *item {
              Some(_) => sz += 1u,
              _ => ()
            }
        }
        sz
    }

    /// Return true if the map contains no elements
    pure fn is_empty(&self) -> bool { self.len() == 0 }
}

impl<V> SmallIntMap<V>: Mutable {
    fn clear(&mut self) { self.v.set(~[]) }
}

/// Implements the map::map interface for smallintmap
impl<V: Copy> SmallIntMap<V> {
    #[inline(always)]
    fn insert(key: uint, value: V) -> bool {
        let exists = contains_key(self, key);
        insert(self, key, value);
        return !exists;
    }
    fn remove(key: uint) -> bool {
        if key >= self.v.len() {
            return false;
        }
        let old = self.v.get_elt(key);
        self.v.set_elt(key, None);
        old.is_some()
    }
    pure fn contains_key(key: uint) -> bool {
        contains_key(self, key)
    }
    pure fn contains_key_ref(key: &uint) -> bool {
        contains_key(self, *key)
    }
    pure fn get(key: uint) -> V { get(self, key) }
    pure fn find(key: uint) -> Option<V> { find(self, key) }

    fn update_with_key(key: uint, val: V, ff: fn(uint, V, V) -> V) -> bool {
        match self.find(key) {
            None            => return self.insert(key, val),
            Some(copy orig) => return self.insert(key, ff(key, orig, val)),
        }
    }

    fn update(key: uint, newval: V, ff: fn(V, V) -> V) -> bool {
        return self.update_with_key(key, newval, |_k, v, v1| ff(v,v1));
    }

    pure fn each(it: fn(key: uint, value: V) -> bool) {
        self.each_ref(|k, v| it(*k, *v))
    }
    pure fn each_key(it: fn(key: uint) -> bool) {
        self.each_ref(|k, _v| it(*k))
    }
    pure fn each_value(it: fn(value: V) -> bool) {
        self.each_ref(|_k, v| it(*v))
    }
    pure fn each_ref(it: fn(key: &uint, value: &V) -> bool) {
        let mut idx = 0u, l = self.v.len();
        while idx < l {
            match self.v.get_elt(idx) {
              Some(ref elt) => if !it(&idx, elt) { break },
              None => ()
            }
            idx += 1u;
        }
    }
    pure fn each_key_ref(blk: fn(key: &uint) -> bool) {
        self.each_ref(|k, _v| blk(k))
    }
    pure fn each_value_ref(blk: fn(value: &V) -> bool) {
        self.each_ref(|_k, v| blk(v))
    }
}

impl<V: Copy> SmallIntMap<V>: ops::Index<uint, V> {
    pure fn index(&self, key: uint) -> V {
        unsafe {
            get(*self, key)
        }
    }
}

#[cfg(test)]
mod tests {
    use smallintmap::{mk, SmallIntMap};

    use core::option::None;

    #[test]
    fn test_len() {
        let mut map = mk();
        assert map.len() == 0;
        assert map.is_empty();
        map.insert(5, 20);
        assert map.len() == 1;
        assert !map.is_empty();
        map.insert(11, 12);
        assert map.len() == 2;
        assert !map.is_empty();
        map.insert(14, 22);
        assert map.len() == 3;
        assert !map.is_empty();
    }

    #[test]
    fn test_clear() {
        let mut map = mk();
        map.insert(5, 20);
        map.insert(11, 12);
        map.insert(14, 22);
        map.clear();
        assert map.is_empty();
        assert map.find(5).is_none();
        assert map.find(11).is_none();
        assert map.find(14).is_none();
    }

    #[test]
    fn test_insert_with_key() {
        let map: SmallIntMap<uint> = mk();

        // given a new key, initialize it with this new count, given
        // given an existing key, add more to its count
        fn addMoreToCount(_k: uint, v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        fn addMoreToCount_simple(v0: uint, v1: uint) -> uint {
            v0 + v1
        }

        // count integers
        map.update(3, 1, addMoreToCount_simple);
        map.update_with_key(9, 1, addMoreToCount);
        map.update(3, 7, addMoreToCount_simple);
        map.update_with_key(5, 3, addMoreToCount);
        map.update_with_key(3, 2, addMoreToCount);

        // check the total counts
        assert map.find(3).get() == 10;
        assert map.find(5).get() == 3;
        assert map.find(9).get() == 1;

        // sadly, no sevens were counted
        assert None == map.find(7);
    }
}
<|endoftext|>


<commit_before>//! Construction of householder elementary reflections.

use num::Zero;
use alga::general::Complex;
use allocator::Allocator;
use base::{DefaultAllocator, MatrixMN, MatrixN, Unit, Vector, VectorN};
use dimension::Dim;
use storage::{Storage, StorageMut};

use geometry::Reflection;

/// Replaces `column` by the axis of the householder reflection that transforms `column` into
/// `(+/-|column|, 0, ..., 0)`.
///
/// The unit-length axis is output to `column`. Returns what would be the first component of
/// `column` after reflection and `false` if no reflection was necessary.
#[doc(hidden)]
#[inline(always)]
pub fn reflection_axis_mut<N: Complex, D: Dim, S: StorageMut<N, D>>(
    column: &mut Vector<N, D, S>,
) -> (N, bool) {
    let reflection_sq_norm = column.norm_squared();
    let reflection_norm = reflection_sq_norm.sqrt();

    let factor;
    let signed_norm;

    unsafe {
        let (modulus, sign) = column.vget_unchecked(0).to_exp();
        signed_norm = sign.scale(reflection_norm);
        factor = (reflection_sq_norm + modulus * reflection_norm) * ::convert(2.0);
        *column.vget_unchecked_mut(0) += signed_norm;
    };

    if !factor.is_zero() {
        column.unscale_mut(factor.sqrt());
        (-signed_norm, true)
    } else {
        (-signed_norm, false)
    }
}

/// Uses an householder reflection to zero out the `icol`-th column, starting with the `shift + 1`-th
/// subdiagonal element.
#[doc(hidden)]
pub fn clear_column_unchecked<N: Complex, R: Dim, C: Dim>(
    matrix: &mut MatrixMN<N, R, C>,
    diag_elt: &mut N,
    icol: usize,
    shift: usize,
    bilateral: Option<&mut VectorN<N, R>>,
) where
    DefaultAllocator: Allocator<N, R, C> + Allocator<N, R>,
{
    let (mut left, mut right) = matrix.columns_range_pair_mut(icol, icol + 1..);
    let mut axis = left.rows_range_mut(icol + shift..);

    let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis);
    *diag_elt = reflection_norm;

    if not_zero {
        let refl = Reflection::new(Unit::new_unchecked(axis), N::zero());
        let sign = reflection_norm.signum();
        if let Some(mut work) = bilateral {
            refl.reflect_rows_with_sign(&mut right, &mut work, sign);
        }
        refl.reflect_with_sign(&mut right.rows_range_mut(icol + shift..), sign.conjugate());
    }
}

/// Uses an householder reflection to zero out the `irow`-th row, ending before the `shift + 1`-th
/// superdiagonal element.
#[doc(hidden)]
pub fn clear_row_unchecked<N: Complex, R: Dim, C: Dim>(
    matrix: &mut MatrixMN<N, R, C>,
    diag_elt: &mut N,
    axis_packed: &mut VectorN<N, C>,
    work: &mut VectorN<N, R>,
    irow: usize,
    shift: usize,
) where
    DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> + Allocator<N, C>,
{
    let (mut top, mut bottom) = matrix.rows_range_pair_mut(irow, irow + 1..);
    let mut axis = axis_packed.rows_range_mut(irow + shift..);
    axis.tr_copy_from(&top.columns_range(irow + shift..));

    let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis);
    axis.conjugate_mut(); // So that reflect_rows actually cancels the first row.
    *diag_elt = reflection_norm;

    if not_zero {
        let refl = Reflection::new(Unit::new_unchecked(axis), N::zero());
        refl.reflect_rows_with_sign(
            &mut bottom.columns_range_mut(irow + shift..),
            &mut work.rows_range_mut(irow + 1..),
            reflection_norm.signum().conjugate(),
        );
        top.columns_range_mut(irow + shift..)
            .tr_copy_from(&refl.axis());
    } else {
        top.columns_range_mut(irow + shift..).tr_copy_from(&axis);
    }
}

/// Computes the orthogonal transformation described by the elementary reflector axii stored on
/// the lower-diagonal element of the given matrix.
/// matrices.
#[doc(hidden)]
pub fn assemble_q<N: Complex, D: Dim>(m: &MatrixN<N, D>, signs: &[N]) -> MatrixN<N, D>
where DefaultAllocator: Allocator<N, D, D> {
    assert!(m.is_square());
    let dim = m.data.shape().0;

    // NOTE: we could build the identity matrix and call p_mult on it.
    // Instead we don't so that we take in account the matrix sparseness.
    let mut res = MatrixN::identity_generic(dim, dim);

    for i in (0..dim.value() - 1).rev() {
        let axis = m.slice_range(i + 1.., i);
        let refl = Reflection::new(Unit::new_unchecked(axis), N::zero());

        let mut res_rows = res.slice_range_mut(i + 1.., i..);
        refl.reflect_with_sign(&mut res_rows, signs[i].signum());
    }

    res
}
<commit_msg>Final SVD fix.<commit_after>//! Construction of householder elementary reflections.

use num::Zero;
use alga::general::Complex;
use allocator::Allocator;
use base::{DefaultAllocator, MatrixMN, MatrixN, Unit, Vector, VectorN};
use dimension::Dim;
use storage::{Storage, StorageMut};

use geometry::Reflection;

/// Replaces `column` by the axis of the householder reflection that transforms `column` into
/// `(+/-|column|, 0, ..., 0)`.
///
/// The unit-length axis is output to `column`. Returns what would be the first component of
/// `column` after reflection and `false` if no reflection was necessary.
#[doc(hidden)]
#[inline(always)]
pub fn reflection_axis_mut<N: Complex, D: Dim, S: StorageMut<N, D>>(
    column: &mut Vector<N, D, S>,
) -> (N, bool) {
    let reflection_sq_norm = column.norm_squared();
    let reflection_norm = reflection_sq_norm.sqrt();

    let factor;
    let signed_norm;

    unsafe {
        let (modulus, sign) = column.vget_unchecked(0).to_exp();
        signed_norm = sign.scale(reflection_norm);
        factor = (reflection_sq_norm + modulus * reflection_norm) * ::convert(2.0);
        *column.vget_unchecked_mut(0) += signed_norm;
    };

    if !factor.is_zero() {
        column.unscale_mut(factor.sqrt());
        (-signed_norm, true)
    } else {
        // FIXME: not sure why we don't have a - sign here.
        (signed_norm, false)
    }
}

/// Uses an householder reflection to zero out the `icol`-th column, starting with the `shift + 1`-th
/// subdiagonal element.
#[doc(hidden)]
pub fn clear_column_unchecked<N: Complex, R: Dim, C: Dim>(
    matrix: &mut MatrixMN<N, R, C>,
    diag_elt: &mut N,
    icol: usize,
    shift: usize,
    bilateral: Option<&mut VectorN<N, R>>,
) where
    DefaultAllocator: Allocator<N, R, C> + Allocator<N, R>,
{
    let (mut left, mut right) = matrix.columns_range_pair_mut(icol, icol + 1..);
    let mut axis = left.rows_range_mut(icol + shift..);

    let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis);
    *diag_elt = reflection_norm;

    if not_zero {
        let refl = Reflection::new(Unit::new_unchecked(axis), N::zero());
        let sign = reflection_norm.signum();
        if let Some(mut work) = bilateral {
            refl.reflect_rows_with_sign(&mut right, &mut work, sign);
        }
        refl.reflect_with_sign(&mut right.rows_range_mut(icol + shift..), sign.conjugate());
    }
}

/// Uses an householder reflection to zero out the `irow`-th row, ending before the `shift + 1`-th
/// superdiagonal element.
#[doc(hidden)]
pub fn clear_row_unchecked<N: Complex, R: Dim, C: Dim>(
    matrix: &mut MatrixMN<N, R, C>,
    diag_elt: &mut N,
    axis_packed: &mut VectorN<N, C>,
    work: &mut VectorN<N, R>,
    irow: usize,
    shift: usize,
) where
    DefaultAllocator: Allocator<N, R, C> + Allocator<N, R> + Allocator<N, C>,
{
    let (mut top, mut bottom) = matrix.rows_range_pair_mut(irow, irow + 1..);
    let mut axis = axis_packed.rows_range_mut(irow + shift..);
    axis.tr_copy_from(&top.columns_range(irow + shift..));

    let (reflection_norm, not_zero) = reflection_axis_mut(&mut axis);
    axis.conjugate_mut(); // So that reflect_rows actually cancels the first row.
    *diag_elt = reflection_norm;

    if not_zero {
        let refl = Reflection::new(Unit::new_unchecked(axis), N::zero());
        refl.reflect_rows_with_sign(
            &mut bottom.columns_range_mut(irow + shift..),
            &mut work.rows_range_mut(irow + 1..),
            reflection_norm.signum().conjugate(),
        );
        top.columns_range_mut(irow + shift..)
            .tr_copy_from(&refl.axis());
    } else {
        top.columns_range_mut(irow + shift..).tr_copy_from(&axis);
    }
}

/// Computes the orthogonal transformation described by the elementary reflector axii stored on
/// the lower-diagonal element of the given matrix.
/// matrices.
#[doc(hidden)]
pub fn assemble_q<N: Complex, D: Dim>(m: &MatrixN<N, D>, signs: &[N]) -> MatrixN<N, D>
where DefaultAllocator: Allocator<N, D, D> {
    assert!(m.is_square());
    let dim = m.data.shape().0;

    // NOTE: we could build the identity matrix and call p_mult on it.
    // Instead we don't so that we take in account the matrix sparseness.
    let mut res = MatrixN::identity_generic(dim, dim);

    for i in (0..dim.value() - 1).rev() {
        let axis = m.slice_range(i + 1.., i);
        let refl = Reflection::new(Unit::new_unchecked(axis), N::zero());

        let mut res_rows = res.slice_range_mut(i + 1.., i..);
        refl.reflect_with_sign(&mut res_rows, signs[i].signum());
    }

    res
}
<|endoftext|>


<commit_before>//! This is the module that contains the error types used in `neli`
//!
//! There are three main types:
//! * `NlError` - typically socket errors
//! * `DeError` - Error while deserializing
//! * `SerError` - Error while serializing
//!
//! Additionally there is one other type: `Nlmsgerr`. This type is returned at the protocol level
//! by netlink sockets when an error has been returned in response to the given request.
//!
//! # Design decisions
//!
//! `NlError` can either be created with a custom `String` message or using three variants, one for
//! no ACK received, one for a bad PID that does not correspond to that assigned to the socket, or
//! one for a bad sequence number that does not correspond to the request sequence number.

use std;
use std::error::Error;
use std::fmt::{self, Display};
use std::io;
use std::str;
use std::string;

use buffering::{StreamReadBuffer, StreamWriteBuffer};
use libc;

use consts::NlType;
use nl::{NlEmpty, Nlmsghdr};
use Nl;

macro_rules! try_err_compat {
    ( $err_name:ident, $( $from_err_name:path ),* ) => {
        $(
            impl From<$from_err_name> for $err_name {
                fn from(v: $from_err_name) -> Self {
                    $err_name::new(v.description())
                }
            }
        )*
    }
}

/// Struct representing netlink packets containing errors
pub struct Nlmsgerr<T> {
    /// Error code
    pub error: libc::c_int,
    /// Packet header for request that failed
    pub nlmsg: Nlmsghdr<T, NlEmpty>,
}

impl<T> Nl for Nlmsgerr<T>
where
    T: NlType,
{
    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.error.serialize(mem)?;
        self.nlmsg.serialize(mem)?;
        self.pad(mem)?;
        Ok(())
    }

    fn deserialize<B>(mem: &mut StreamReadBuffer<B>) -> Result<Self, DeError>
    where
        B: AsRef<[u8]>,
    {
        let nlmsg = Nlmsgerr {
            error: libc::c_int::deserialize(mem)?,
            nlmsg: Nlmsghdr::<T, NlEmpty>::deserialize(mem)?,
        };
        nlmsg.strip(mem)?;
        Ok(nlmsg)
    }

    fn size(&self) -> usize {
        self.error.size() + self.nlmsg.size()
    }
}

/// Netlink protocol error
#[derive(Debug)]
pub enum NlError {
    /// Type indicating a message from a converted error
    Msg(String),
    /// No ack was received when `NlmF::Ack` was specified in the request
    NoAck,
    /// The sequence number for the response did not match the request
    BadSeq,
    /// Incorrect PID socket identifier in received message
    BadPid,
}

try_err_compat!(NlError, io::Error, SerError, DeError);

impl NlError {
    /// Create new error from `&str`
    pub fn new(s: &str) -> Self {
        NlError::Msg(s.to_string())
    }
}

/// Netlink protocol error
impl Display for NlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let msg = match *self {
            NlError::Msg(ref msg) => msg,
            NlError::NoAck => "No ack received",
            NlError::BadSeq => "Sequence number does not match the request",
            NlError::BadPid => "PID does not match the socket",
        };
        write!(f, "{}", msg)
    }
}

impl Error for NlError {
    fn description(&self) -> &str {
        match *self {
            NlError::Msg(ref msg) => msg.as_str(),
            NlError::NoAck => "No ack received",
            NlError::BadSeq => "Sequence number does not match the request",
            NlError::BadPid => "PID does not match the socket",
        }
    }
}

/// Serialization error
#[derive(Debug)]
pub struct SerError(String);

impl SerError {
    /// Create a new error with the given message as description
    pub fn new<T: ToString>(msg: T) -> Self {
        SerError(msg.to_string())
    }
}

try_err_compat!(SerError, io::Error);

impl Display for SerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Error for SerError {
    fn description(&self) -> &str {
        self.0.as_str()
    }
}

/// Deserialization error
#[derive(Debug)]
pub struct DeError(String);

impl DeError {
    /// Create new error from `&str`
    pub fn new(s: &str) -> Self {
        DeError(s.to_string())
    }
}

try_err_compat!(
    DeError,
    io::Error,
    str::Utf8Error,
    string::FromUtf8Error,
    std::ffi::FromBytesWithNulError
);

impl Display for DeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Error for DeError {
    fn description(&self) -> &str {
        self.0.as_str()
    }
}
<commit_msg>Nlmsgerr can implement debug<commit_after>//! This is the module that contains the error types used in `neli`
//!
//! There are three main types:
//! * `NlError` - typically socket errors
//! * `DeError` - Error while deserializing
//! * `SerError` - Error while serializing
//!
//! Additionally there is one other type: `Nlmsgerr`. This type is returned at the protocol level
//! by netlink sockets when an error has been returned in response to the given request.
//!
//! # Design decisions
//!
//! `NlError` can either be created with a custom `String` message or using three variants, one for
//! no ACK received, one for a bad PID that does not correspond to that assigned to the socket, or
//! one for a bad sequence number that does not correspond to the request sequence number.

use std;
use std::error::Error;
use std::fmt::{self, Display};
use std::io;
use std::str;
use std::string;

use buffering::{StreamReadBuffer, StreamWriteBuffer};
use libc;

use consts::NlType;
use nl::{NlEmpty, Nlmsghdr};
use Nl;

macro_rules! try_err_compat {
    ( $err_name:ident, $( $from_err_name:path ),* ) => {
        $(
            impl From<$from_err_name> for $err_name {
                fn from(v: $from_err_name) -> Self {
                    $err_name::new(v.description())
                }
            }
        )*
    }
}

/// Struct representing netlink packets containing errors
#[derive(Debug)]
pub struct Nlmsgerr<T> {
    /// Error code
    pub error: libc::c_int,
    /// Packet header for request that failed
    pub nlmsg: Nlmsghdr<T, NlEmpty>,
}

impl<T> Nl for Nlmsgerr<T>
where
    T: NlType,
{
    fn serialize(&self, mem: &mut StreamWriteBuffer) -> Result<(), SerError> {
        self.error.serialize(mem)?;
        self.nlmsg.serialize(mem)?;
        self.pad(mem)?;
        Ok(())
    }

    fn deserialize<B>(mem: &mut StreamReadBuffer<B>) -> Result<Self, DeError>
    where
        B: AsRef<[u8]>,
    {
        let nlmsg = Nlmsgerr {
            error: libc::c_int::deserialize(mem)?,
            nlmsg: Nlmsghdr::<T, NlEmpty>::deserialize(mem)?,
        };
        nlmsg.strip(mem)?;
        Ok(nlmsg)
    }

    fn size(&self) -> usize {
        self.error.size() + self.nlmsg.size()
    }
}

/// Netlink protocol error
#[derive(Debug)]
pub enum NlError {
    /// Type indicating a message from a converted error
    Msg(String),
    /// No ack was received when `NlmF::Ack` was specified in the request
    NoAck,
    /// The sequence number for the response did not match the request
    BadSeq,
    /// Incorrect PID socket identifier in received message
    BadPid,
}

try_err_compat!(NlError, io::Error, SerError, DeError);

impl NlError {
    /// Create new error from `&str`
    pub fn new(s: &str) -> Self {
        NlError::Msg(s.to_string())
    }
}

/// Netlink protocol error
impl Display for NlError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let msg = match *self {
            NlError::Msg(ref msg) => msg,
            NlError::NoAck => "No ack received",
            NlError::BadSeq => "Sequence number does not match the request",
            NlError::BadPid => "PID does not match the socket",
        };
        write!(f, "{}", msg)
    }
}

impl Error for NlError {
    fn description(&self) -> &str {
        match *self {
            NlError::Msg(ref msg) => msg.as_str(),
            NlError::NoAck => "No ack received",
            NlError::BadSeq => "Sequence number does not match the request",
            NlError::BadPid => "PID does not match the socket",
        }
    }
}

/// Serialization error
#[derive(Debug)]
pub struct SerError(String);

impl SerError {
    /// Create a new error with the given message as description
    pub fn new<T: ToString>(msg: T) -> Self {
        SerError(msg.to_string())
    }
}

try_err_compat!(SerError, io::Error);

impl Display for SerError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Error for SerError {
    fn description(&self) -> &str {
        self.0.as_str()
    }
}

/// Deserialization error
#[derive(Debug)]
pub struct DeError(String);

impl DeError {
    /// Create new error from `&str`
    pub fn new(s: &str) -> Self {
        DeError(s.to_string())
    }
}

try_err_compat!(
    DeError,
    io::Error,
    str::Utf8Error,
    string::FromUtf8Error,
    std::ffi::FromBytesWithNulError
);

impl Display for DeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl Error for DeError {
    fn description(&self) -> &str {
        self.0.as_str()
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use std::str;

use duct::cmd;
use git2::{Config, Error, Repository};
use log::debug;
use shellexpand;

/// Convert a domain string into a configuration slug
fn slugify_domain(domain: &str) -> String {
    str::replace(domain, ".", "|")
}

/// Get the URL of the given remote
pub fn get_remote_url(remote: &str) -> String {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    let remote = repo.find_remote(remote).unwrap();
    String::from(remote.url().unwrap())
}

/// Get a value fom the repository config
pub fn get_repo_info(repo_field: &str) -> Result<String, Error> {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    let cfg = repo.config().unwrap();
    cfg.get_string(repo_field)
}

/// Get a value for the given project-local git-req config
pub fn get_config(field_name: &str) -> Option<String> {
    let key = format!("req.{}", field_name);
    match get_repo_info(&key) {
        Ok(val) => Some(val),
        Err(_) => None,
    }
}

/// Set a value for the project-local git-req configuration
pub fn set_config(field_name: &str, value: &str) {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    let mut cfg = repo.config().unwrap();
    cfg.set_str(&format!("req.{}", field_name), value).unwrap();
}

/// Delete the entry for the project-local git-req config field with the provided name
pub fn delete_config(field_name: &str) {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    let mut cfg = repo.config().unwrap();
    cfg.remove(&format!("req.{}", field_name)).unwrap();
}

/// Get a value for the given global git-req config
pub fn get_req_config(domain: &str, field: &str) -> Option<String> {
    let slug = slugify_domain(domain);
    let cfg = Config::open(&Path::new(
        &shellexpand::tilde("~/.gitreqconfig").to_string(),
    ))
    .unwrap();
    match cfg.get_string(&format!("req.{}.{}", slug, field)) {
        Ok(val) => Some(val),
        Err(_) => None,
    }
}

/// Set a value for the global git-req configuration
pub fn set_req_config(domain: &str, field: &str, value: &str) {
    let slug = slugify_domain(domain);
    let mut cfg = Config::open(&Path::new(
        &shellexpand::tilde("~/.gitreqconfig").to_string(),
    ))
    .unwrap();
    cfg.set_str(&format!("req.{}.{}", slug, field), value)
        .unwrap();
}

/// Clear the value for the lobal git-req configuration
pub fn delete_req_config(domain: &str, field: &str) -> Result<(), Error> {
    let slug = slugify_domain(domain);
    let mut cfg = Config::open(&Path::new(
        &shellexpand::tilde("~/.gitreqconfig").to_string(),
    ))
    .unwrap();
    cfg.remove(&format!("req.{}.{}", slug, field))
}

/// Check out a branch by name
pub fn checkout_branch(remote_branch_name: &str, local_branch_name: &str) -> Result<bool, String> {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    // Fetch the remote branch if there's no local branch with the correct name
    if repo.revparse_single(local_branch_name).is_err() {
        cmd!(
            "git",
            "fetch",
            "origin",
            &format!("{}:{}", remote_branch_name, local_branch_name)
        )
        .run()
        .unwrap();
        if repo.revparse_single(&local_branch_name).is_err() {
            return Err(format!(
                "Could not find remote branch: {}",
                local_branch_name
            ));
        }
    }
    debug!("Checking out branch!");
    match cmd!("git", "checkout", local_branch_name).run() {
        Ok(_) => Ok(true),
        Err(err) => Err(format!("Could not check out local branch: {}", err))
    }
}
<commit_msg>Address rustfmt warning.<commit_after>use std::path::Path;
use std::str;

use duct::cmd;
use git2::{Config, Error, Repository};
use log::debug;
use shellexpand;

/// Convert a domain string into a configuration slug
fn slugify_domain(domain: &str) -> String {
    str::replace(domain, ".", "|")
}

/// Get the URL of the given remote
pub fn get_remote_url(remote: &str) -> String {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    let remote = repo.find_remote(remote).unwrap();
    String::from(remote.url().unwrap())
}

/// Get a value fom the repository config
pub fn get_repo_info(repo_field: &str) -> Result<String, Error> {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    let cfg = repo.config().unwrap();
    cfg.get_string(repo_field)
}

/// Get a value for the given project-local git-req config
pub fn get_config(field_name: &str) -> Option<String> {
    let key = format!("req.{}", field_name);
    match get_repo_info(&key) {
        Ok(val) => Some(val),
        Err(_) => None,
    }
}

/// Set a value for the project-local git-req configuration
pub fn set_config(field_name: &str, value: &str) {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    let mut cfg = repo.config().unwrap();
    cfg.set_str(&format!("req.{}", field_name), value).unwrap();
}

/// Delete the entry for the project-local git-req config field with the provided name
pub fn delete_config(field_name: &str) {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    let mut cfg = repo.config().unwrap();
    cfg.remove(&format!("req.{}", field_name)).unwrap();
}

/// Get a value for the given global git-req config
pub fn get_req_config(domain: &str, field: &str) -> Option<String> {
    let slug = slugify_domain(domain);
    let cfg = Config::open(&Path::new(
        &shellexpand::tilde("~/.gitreqconfig").to_string(),
    ))
    .unwrap();
    match cfg.get_string(&format!("req.{}.{}", slug, field)) {
        Ok(val) => Some(val),
        Err(_) => None,
    }
}

/// Set a value for the global git-req configuration
pub fn set_req_config(domain: &str, field: &str, value: &str) {
    let slug = slugify_domain(domain);
    let mut cfg = Config::open(&Path::new(
        &shellexpand::tilde("~/.gitreqconfig").to_string(),
    ))
    .unwrap();
    cfg.set_str(&format!("req.{}.{}", slug, field), value)
        .unwrap();
}

/// Clear the value for the lobal git-req configuration
pub fn delete_req_config(domain: &str, field: &str) -> Result<(), Error> {
    let slug = slugify_domain(domain);
    let mut cfg = Config::open(&Path::new(
        &shellexpand::tilde("~/.gitreqconfig").to_string(),
    ))
    .unwrap();
    cfg.remove(&format!("req.{}.{}", slug, field))
}

/// Check out a branch by name
pub fn checkout_branch(remote_branch_name: &str, local_branch_name: &str) -> Result<bool, String> {
    let repo = Repository::open_from_env().expect("Couldn't find repository");
    // Fetch the remote branch if there's no local branch with the correct name
    if repo.revparse_single(local_branch_name).is_err() {
        cmd!(
            "git",
            "fetch",
            "origin",
            &format!("{}:{}", remote_branch_name, local_branch_name)
        )
        .run()
        .unwrap();
        if repo.revparse_single(&local_branch_name).is_err() {
            return Err(format!(
                "Could not find remote branch: {}",
                local_branch_name
            ));
        }
    }
    debug!("Checking out branch!");
    match cmd!("git", "checkout", local_branch_name).run() {
        Ok(_) => Ok(true),
        Err(err) => Err(format!("Could not check out local branch: {}", err)),
    }
}
<|endoftext|>


<commit_before>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.2.1"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Assert Equal Size
//!
//! When performing operations such as pointer casts or dealing with [`usize`]
//! versus [`u64`] versus [`u32`], the size of your types matter. This is where
//! [`assert_eq_size`] comes into play. Types provided as arguments to
//! [`assert_eq_size`] are ensured to be the same size at compile-time. If the
//! types differ in size, the code will fail to compile.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! // Can be declared outside of a function if labeled
//! assert_eq_size!(bytes; (u8, u8), u16);
//!
//! // Fails to compile (same label):
//! // assert_eq_size!(bytes; u8, u8);
//!
//! fn main() {
//!     assert_eq_size!([u8; 4], (u16, u16), u32);
//!
//!     // Produces a compilation failure:
//!     // assert_eq_size!(u32, u8);
//! }
//! ```
//!
//! Similar to [`assert_eq_size`], there is [`assert_eq_size_val`]. Instead of
//! specifying types to compare, values' sizes can be directly compared against
//! each other.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! let x = 42u8;
//! let y = true;
//!
//! assert_eq_size_val!(x, y);
//! # }
//! ```
//! [`assert_eq_size_val`] doesn't consume its arguments and thus works for
//! non-[`Clone`]able values.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! struct Buffer([u8; 256]);
//!
//! let buf = Buffer([0; 256]);
//! let val = [0u64; 32];
//!
//! assert_eq_size_val!(buf, val);
//!
//! // `buf` and `val` can be used here
//! # }
//! ```
//!
//! Rather than dereference a pointer to achieve the same effect as
//! [`assert_eq_size_val`], there is also the option of [`assert_eq_size_ptr`].
//!
//! # Assert Constant Expression
//!
//! Constant expressions can be ensured to have certain properties via
//! [`const_assert`]. If the expression evaluates to `false`, the file will fail
//! to compile. This is synonymous to [`static_assert` in C++][static_assert].
//!
//! As a [limitation](#limitations), a unique label is required if the macro is
//! used outside of a function.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//!
//! const_assert!(NUM * NUM == 1024);
//! # }
//! ```
//!
//! As a shorthand for `const_assert!(a == b)`, there's [`const_assert_eq`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! const TWO: usize = 2;
//! const_assert_eq!(two; TWO * TWO, TWO + TWO, 4);
//!
//! // Fails to compile (same label):
//! // const_assert_eq!(two; TWO, TWO);
//!
//! fn main() {
//!     const NUM: usize = 32;
//!     const_assert_eq!(NUM + NUM, 64);
//! }
//! ```
//!
//! # Assert Object Safety
//!
//! Sometimes changes are made to traits that prevent them from being used in
//! the context of an object. Such a case would be adding a generic method and
//! forgetting to add `where Self: Sized` after it. If left unnoticed, that
//! mistake will end up affecting crate users and break compatibility.
//!
//! [`assert_obj_safe`] is here to save you from those troubles:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! assert_obj_safe!(basic; Send, Sync, AsRef<str>);
//!
//! trait MySafeTrait {}
//!
//! trait MyUnsafeTrait {
//!     fn generic<T>();
//! }
//!
//! fn main() {
//!     assert_obj_safe!(MySafeTrait);
//!
//!     // Produces a compilation failure:
//!     // assert_obj_safe!(MyUnsafeTrait);
//! }
//! ```
//!
//! # Assert Trait `impl`
//!
//! To ensure types implement [`Send`], [`Sync`], and other traits, there's
//! [`assert_impl`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! assert_impl!(str; String, Send, Sync, From<&'static str>);
//! assert_impl!(vec; Box<[u8]>, Into<Vec<u8>>);
//!
//! fn main() {
//!     // Produces a compilation failure:
//!     // `*const u8` cannot be sent between threads safely
//!     // assert_impl!(*const u8, Send);
//! }
//! ```
//!
//! # Limitations
//!
//! Due to implementation details, the following can only be used normally from
//! within the context of a function:
//!
//! - [`assert_eq_size`]
//! - [`assert_obj_safe`]
//! - [`const_assert`]
//! - [`const_assert_eq`]
//!
//! To use these macros in other contexts, a unique label must be provided.
//!
//! If you want to read up about this and provide feedback, see
//! [the related issue on GitHub][issue1].
//!
//! [issue1]: https://github.com/nvzqz/static-assertions-rs/issues/1
//! [crate]: https://crates.io/crates/static_assertions
//! [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
//! [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//! [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
//! [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
//! [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
//! [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
//! [`assert_eq_size_val`]: macro.assert_eq_size_val.html
//! [`assert_eq_size_ptr`]: macro.assert_eq_size_ptr.html
//! [`assert_eq_size`]: macro.assert_eq_size.html
//! [`assert_obj_safe`]: macro.assert_obj_safe.html
//! [`assert_impl`]: macro.assert_impl.html
//! [`const_assert`]: macro.const_assert.html
//! [`const_assert_eq`]: macro.const_assert_eq.html

#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the types have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// struct Byte(u8);
///
/// assert_eq_size!(pair; (u16, u16), [u16; 2], [u8; 4]);
///
/// // Fails to compile (same label):
/// // assert_eq_size!(pair; u8, u8);
///
/// fn main() {
///     assert_eq_size!(Byte, u8);
///
///     // Supports unlimited arguments:
///     assert_eq_size!([Byte; 4], [u16; 2], u32);
///
///     // Produces a compilation failure:
///     // assert_eq_size!(Byte, u16);
/// }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            $(forget::<$xs>(transmute(uninitialized::<$x>()));)+
        }
    };
    ($label:ident; $x:ty, $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_eq_size!($x, $($xs),+) }
    };
}

/// Asserts at compile-time that the values pointed to have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// fn operation(x: &(u32, u32), y: &[u16; 4]) {
///     assert_eq_size_ptr!(x, y);
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! assert_eq_size_ptr {
    ($x:expr, $($xs:expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read($x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
///
/// // Fails to compile:
/// // assert_eq_size_val!(x, 0u32);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+) => {
        assert_eq_size_ptr!(&$x, $(&$xs),+);
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// const_assert!(2 + 2 == 4);
///
/// const FIVE: usize = 5;
/// const_assert!(FIVE - FIVE == 0);
///
/// // Produces a compilation failure:
/// // const_assert!(1 >= 2);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert {
    ($($xs:expr),+) => {
        let _ = [(); 0 - (!($($xs)&&+) as usize)];
    };
    ($label:ident; $($xs:expr),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { const_assert!($($xs),+); }
    };
}

/// Asserts at compile-time that the constants are equal in value.
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+) => {
        const_assert!($($x == $xs),+);
    };
    ($label:ident; $x:expr, $($xs:expr),+) => {
        const_assert!($label; $($x == $xs),+);
    };
}

/// Asserts at compile-time that the traits are object-safe.
///
/// This is useful for when changes are made to a trait that accidentally
/// prevent it from being used as an object.
#[macro_export]
macro_rules! assert_obj_safe {
    ($($xs:ty),+) => {
        $(let _: Option<&$xs> = None;)+
    };
    ($label:ident; $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_obj_safe!($($xs),+); }
    };
}

/// Asserts at compile-time that the type implements the given traits.
#[macro_export]
macro_rules! assert_impl {
    (
        $x:ty,
        $(
            $y:ident
            $(< $($args:ty),+ $(,)* >)*
        ),+
    ) => {
        $({
            fn assert_impl<T: ?Sized + $y $(< $($args),+ >)* >() {}
            assert_impl::<$x>();
        })+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_impl!($($xs)+); }
    };
}
<commit_msg>Use static slice in assert_impl doc<commit_after>//! Compile-time assertions to ensure that invariants are met.
//!
//! # Usage
//!
//! This crate is available [on crates.io][crate] and can be used by adding the
//! following to your project's `Cargo.toml`:
//!
//! ```toml
//! [dependencies]
//! static_assertions = "0.2.1"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! #[macro_use]
//! extern crate static_assertions;
//! # fn main() {}
//! ```
//!
//! # Assert Equal Size
//!
//! When performing operations such as pointer casts or dealing with [`usize`]
//! versus [`u64`] versus [`u32`], the size of your types matter. This is where
//! [`assert_eq_size`] comes into play. Types provided as arguments to
//! [`assert_eq_size`] are ensured to be the same size at compile-time. If the
//! types differ in size, the code will fail to compile.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! // Can be declared outside of a function if labeled
//! assert_eq_size!(bytes; (u8, u8), u16);
//!
//! // Fails to compile (same label):
//! // assert_eq_size!(bytes; u8, u8);
//!
//! fn main() {
//!     assert_eq_size!([u8; 4], (u16, u16), u32);
//!
//!     // Produces a compilation failure:
//!     // assert_eq_size!(u32, u8);
//! }
//! ```
//!
//! Similar to [`assert_eq_size`], there is [`assert_eq_size_val`]. Instead of
//! specifying types to compare, values' sizes can be directly compared against
//! each other.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! let x = 42u8;
//! let y = true;
//!
//! assert_eq_size_val!(x, y);
//! # }
//! ```
//! [`assert_eq_size_val`] doesn't consume its arguments and thus works for
//! non-[`Clone`]able values.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! struct Buffer([u8; 256]);
//!
//! let buf = Buffer([0; 256]);
//! let val = [0u64; 32];
//!
//! assert_eq_size_val!(buf, val);
//!
//! // `buf` and `val` can be used here
//! # }
//! ```
//!
//! Rather than dereference a pointer to achieve the same effect as
//! [`assert_eq_size_val`], there is also the option of [`assert_eq_size_ptr`].
//!
//! # Assert Constant Expression
//!
//! Constant expressions can be ensured to have certain properties via
//! [`const_assert`]. If the expression evaluates to `false`, the file will fail
//! to compile. This is synonymous to [`static_assert` in C++][static_assert].
//!
//! As a [limitation](#limitations), a unique label is required if the macro is
//! used outside of a function.
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! # fn main() {
//! const NUM: usize = 32;
//!
//! const_assert!(NUM * NUM == 1024);
//! # }
//! ```
//!
//! As a shorthand for `const_assert!(a == b)`, there's [`const_assert_eq`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! const TWO: usize = 2;
//! const_assert_eq!(two; TWO * TWO, TWO + TWO, 4);
//!
//! // Fails to compile (same label):
//! // const_assert_eq!(two; TWO, TWO);
//!
//! fn main() {
//!     const NUM: usize = 32;
//!     const_assert_eq!(NUM + NUM, 64);
//! }
//! ```
//!
//! # Assert Object Safety
//!
//! Sometimes changes are made to traits that prevent them from being used in
//! the context of an object. Such a case would be adding a generic method and
//! forgetting to add `where Self: Sized` after it. If left unnoticed, that
//! mistake will end up affecting crate users and break compatibility.
//!
//! [`assert_obj_safe`] is here to save you from those troubles:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! assert_obj_safe!(basic; Send, Sync, AsRef<str>);
//!
//! trait MySafeTrait {}
//!
//! trait MyUnsafeTrait {
//!     fn generic<T>();
//! }
//!
//! fn main() {
//!     assert_obj_safe!(MySafeTrait);
//!
//!     // Produces a compilation failure:
//!     // assert_obj_safe!(MyUnsafeTrait);
//! }
//! ```
//!
//! # Assert Trait `impl`
//!
//! To ensure types implement [`Send`], [`Sync`], and other traits, there's
//! [`assert_impl`]:
//!
//! ```
//! # #[macro_use]
//! # extern crate static_assertions;
//! assert_impl!(str; String, Send, Sync, From<&'static str>);
//! assert_impl!(vec; &'static [u8], Into<Vec<u8>>);
//!
//! fn main() {
//!     // Produces a compilation failure:
//!     // `*const u8` cannot be sent between threads safely
//!     // assert_impl!(*const u8, Send);
//! }
//! ```
//!
//! # Limitations
//!
//! Due to implementation details, the following can only be used normally from
//! within the context of a function:
//!
//! - [`assert_eq_size`]
//! - [`assert_obj_safe`]
//! - [`const_assert`]
//! - [`const_assert_eq`]
//!
//! To use these macros in other contexts, a unique label must be provided.
//!
//! If you want to read up about this and provide feedback, see
//! [the related issue on GitHub][issue1].
//!
//! [issue1]: https://github.com/nvzqz/static-assertions-rs/issues/1
//! [crate]: https://crates.io/crates/static_assertions
//! [static_assert]: http://en.cppreference.com/w/cpp/language/static_assert
//! [`Clone`]: https://doc.rust-lang.org/std/clone/trait.Clone.html
//! [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
//! [`usize`]: https://doc.rust-lang.org/std/primitive.usize.html
//! [`u64`]: https://doc.rust-lang.org/std/primitive.u64.html
//! [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html
//! [`assert_eq_size_val`]: macro.assert_eq_size_val.html
//! [`assert_eq_size_ptr`]: macro.assert_eq_size_ptr.html
//! [`assert_eq_size`]: macro.assert_eq_size.html
//! [`assert_obj_safe`]: macro.assert_obj_safe.html
//! [`assert_impl`]: macro.assert_impl.html
//! [`const_assert`]: macro.const_assert.html
//! [`const_assert_eq`]: macro.const_assert_eq.html

#![no_std]

#[doc(hidden)]
pub extern crate core as _core;

/// Asserts at compile-time that the types have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// struct Byte(u8);
///
/// assert_eq_size!(pair; (u16, u16), [u16; 2], [u8; 4]);
///
/// // Fails to compile (same label):
/// // assert_eq_size!(pair; u8, u8);
///
/// fn main() {
///     assert_eq_size!(Byte, u8);
///
///     // Supports unlimited arguments:
///     assert_eq_size!([Byte; 4], [u16; 2], u32);
///
///     // Produces a compilation failure:
///     // assert_eq_size!(Byte, u16);
/// }
/// ```
#[macro_export]
macro_rules! assert_eq_size {
    ($x:ty, $($xs:ty),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::mem::{forget, transmute, uninitialized};
            $(forget::<$xs>(transmute(uninitialized::<$x>()));)+
        }
    };
    ($label:ident; $x:ty, $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_eq_size!($x, $($xs),+) }
    };
}

/// Asserts at compile-time that the values pointed to have equal sizes.
///
/// This especially is useful for when coercing pointers between different types
/// and ensuring the underlying values are the same size.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// fn operation(x: &(u32, u32), y: &[u16; 4]) {
///     assert_eq_size_ptr!(x, y);
/// }
/// # fn main() {}
/// ```
#[macro_export]
macro_rules! assert_eq_size_ptr {
    ($x:expr, $($xs:expr),+) => {
        #[allow(unused_unsafe)]
        unsafe {
            use $crate::_core::{mem, ptr};
            let mut copy = ptr::read($x);
            $(ptr::write(&mut copy, mem::transmute(ptr::read($xs)));)+
            mem::forget(copy);
        }
    }
}

/// Asserts at compile-time that the values have equal sizes.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// struct Byte(u8);
///
/// let x = 10u8;
/// let y = Byte(42); // Works for non-cloneable types
///
/// assert_eq_size_val!(x, y);
/// assert_eq_size_val!(x, y, 0u8);
///
/// // Fails to compile:
/// // assert_eq_size_val!(x, 0u32);
/// # }
/// ```
#[macro_export]
macro_rules! assert_eq_size_val {
    ($x:expr, $($xs:expr),+) => {
        assert_eq_size_ptr!(&$x, $(&$xs),+);
    }
}

/// Asserts at compile-time that the constant expression evaluates to `true`.
///
/// # Example
///
/// ```
/// # #[macro_use]
/// # extern crate static_assertions;
/// # fn main() {
/// const_assert!(2 + 2 == 4);
///
/// const FIVE: usize = 5;
/// const_assert!(FIVE - FIVE == 0);
///
/// // Produces a compilation failure:
/// // const_assert!(1 >= 2);
/// # }
/// ```
#[macro_export]
macro_rules! const_assert {
    ($($xs:expr),+) => {
        let _ = [(); 0 - (!($($xs)&&+) as usize)];
    };
    ($label:ident; $($xs:expr),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { const_assert!($($xs),+); }
    };
}

/// Asserts at compile-time that the constants are equal in value.
#[macro_export]
macro_rules! const_assert_eq {
    ($x:expr, $($xs:expr),+) => {
        const_assert!($($x == $xs),+);
    };
    ($label:ident; $x:expr, $($xs:expr),+) => {
        const_assert!($label; $($x == $xs),+);
    };
}

/// Asserts at compile-time that the traits are object-safe.
///
/// This is useful for when changes are made to a trait that accidentally
/// prevent it from being used as an object.
#[macro_export]
macro_rules! assert_obj_safe {
    ($($xs:ty),+) => {
        $(let _: Option<&$xs> = None;)+
    };
    ($label:ident; $($xs:ty),+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_obj_safe!($($xs),+); }
    };
}

/// Asserts at compile-time that the type implements the given traits.
#[macro_export]
macro_rules! assert_impl {
    (
        $x:ty,
        $(
            $y:ident
            $(< $($args:ty),+ $(,)* >)*
        ),+
    ) => {
        $({
            fn assert_impl<T: ?Sized + $y $(< $($args),+ >)* >() {}
            assert_impl::<$x>();
        })+
    };
    ($label:ident; $($xs:tt)+) => {
        #[allow(dead_code, non_snake_case)]
        fn $label() { assert_impl!($($xs)+); }
    };
}
<|endoftext|>


<commit_before>// Module for parsing ISO Base Media Format aka video/mp4 streams.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

/// Basic ISO box structure.
pub struct BoxHeader {
    /// Four character box type
pub name: u32,
    /// Size of the box in bytes
pub size: u64,
    /// Offset to the start of the contained data (or header size).
pub offset: u64,
}

/// File type box 'ftyp'.
pub struct FileTypeBox {
    name: u32,
    size: u64,
    major_brand: u32,
    minor_version: u32,
    compatible_brands: Vec<u32>,
}

/// Movie header box 'mvhd'.
pub struct MovieHeaderBox {
    pub name: u32,
    pub size: u64,
    pub timescale: u32,
    pub duration: u64,
    // Ignore other fields.
}

pub struct TrackHeaderBox {
    pub name: u32,
    pub size: u64,
    pub track_id: u32,
    pub duration: u64,
    pub width: u32,
    pub height: u32,
}

extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{Read, Result, Seek, SeekFrom, Take};
use std::io::Cursor;

/// Parse a box out of a data buffer.
pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Result<BoxHeader> {
    let tmp_size = try!(src.read_u32::<BigEndian>());
    let name = try!(src.read_u32::<BigEndian>());
    let size = match tmp_size {
        1 => try!(src.read_u64::<BigEndian>()),
        _ => tmp_size as u64,
    };
    assert!(size >= 8);
    if tmp_size == 1 {
        assert!(size >= 16);
    }
    let offset = match tmp_size {
        1 => 4 + 4 + 8,
        _ => 4 + 4,
    };
    assert!(offset <= size);
    Ok(BoxHeader{
      name: name,
      size: size,
      offset: offset,
    })
}

/// Parse the extra header fields for a full box.
fn read_fullbox_extra<T: ReadBytesExt>(src: &mut T) -> (u8, u32) {
    let version = src.read_u8().unwrap();
    let flags_a = src.read_u8().unwrap();
    let flags_b = src.read_u8().unwrap();
    let flags_c = src.read_u8().unwrap();
    (version, (flags_a as u32) << 16 |
              (flags_b as u32) <<  8 |
              (flags_c as u32))
}

/// Skip over the contents of a box.
pub fn skip_box_content<T: ReadBytesExt + Seek>
  (src: &mut T, header: &BoxHeader)
  -> std::io::Result<u64>
{
    src.seek(SeekFrom::Current((header.size - header.offset) as i64))
}

/// Helper to construct a Take over the contents of a box.
fn limit<'a, T: Read>(f: &'a mut T, h: &BoxHeader) -> Take<&'a mut T> {
    f.take(h.size - h.offset)
}

/// Helper to construct a Cursor over the contents of a box.
fn recurse<T: Read>(f: &mut T, h: &BoxHeader) {
    println!("{} -- recursing", h);
    // FIXME: I couldn't figure out how to do this without copying.
    // We use Seek on the Read we return in skip_box_content, but
    // that trait isn't implemented for a Take like our limit()
    // returns. Slurping the buffer and wrapping it in a Cursor
    // functions as a work around.
    let buf: Vec<u8> = limit(f, &h)
        .bytes()
        .map(|u| u.unwrap())
        .collect();
    let mut content = Cursor::new(buf);
    loop {
        read_box(&mut content).unwrap();
    }
    println!("{} -- end", h);
}

/// Read the contents of a box, including sub boxes.
/// Right now it just prints the box value rather than
/// returning anything.
pub fn read_box<T: Read + Seek>(f: &mut T) -> Result<()> {
    read_box_header(f).and_then(|h| {
        match &(fourcc_to_string(h.name))[..] {
            "ftyp" => {
                let mut content = limit(f, &h);
                let ftyp = read_ftyp(&mut content, &h).unwrap();
                println!("{}", ftyp);
            },
            "moov" => recurse(f, &h),
            "mvhd" => {
                let mut content = limit(f, &h);
                let mvhd = read_mvhd(&mut content, &h).unwrap();
                println!("  {}", mvhd);
            },
            "trak" => recurse(f, &h),
            "tkhd" => {
                let mut content = limit(f, &h);
                let tkhd = read_tkhd(&mut content, &h).unwrap();
                println!("  {}", tkhd);
            },
            _ => {
                // Skip the contents of unknown chunks.
                println!("{} (skipped)", h);
                skip_box_content(f, &h).unwrap();
            },
        };
        Ok(()) // and_then needs a Result to return.
    })
}

/// Entry point for C language callers.
/// Take a buffer and call read_box() on it.
#[no_mangle]
pub unsafe extern fn read_box_from_buffer(buffer: *const u8, size: usize) -> bool {
    use std::slice;
    use std::thread;

    // Validate arguments from C.
    if buffer.is_null() || size < 8 {
        return false;
    }

    // Wrap the buffer we've been give in a slice.
    let b = slice::from_raw_parts(buffer, size);
    let mut c = Cursor::new(b);

    // Parse in a subthread.
    let task = thread::spawn(move || {
        read_box(&mut c).unwrap();
    });
    // Catch any panics.
    task.join().is_ok()
}

/// Parse an ftype box.
pub fn read_ftyp<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Option<FileTypeBox> {
    let major = src.read_u32::<BigEndian>().unwrap();
    let minor = src.read_u32::<BigEndian>().unwrap();
    let brand_count = (head.size - 8 - 8) /4;
    let mut brands = Vec::new();
    for _ in 0..brand_count {
        brands.push(src.read_u32::<BigEndian>().unwrap());
    }
    Some(FileTypeBox{
        name: head.name,
        size: head.size,
        major_brand: major,
        minor_version: minor,
        compatible_brands: brands,
    })
}

/// Parse an mvhd box.
pub fn read_mvhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Option<MovieHeaderBox> {
    let (version, _) = read_fullbox_extra(src);
    match version {
        1 => {
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 16];
            let r = src.read(&mut skip).unwrap();
            assert!(r == skip.len());
        },
        0 => {
            // 32 bit creation and modification times.
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 8];
            let r = src.read(&mut skip).unwrap();
            assert!(r == skip.len());
        },
        _ => panic!("invalid mhdr version"),
    }
    let timescale = src.read_u32::<BigEndian>().unwrap();
    let duration = match version {
        1 => src.read_u64::<BigEndian>().unwrap(),
        0 => src.read_u32::<BigEndian>().unwrap() as u64,
        _ => panic!("invalid mhdr version"),
    };
    // Skip remaining fields.
    let mut skip: Vec<u8> = vec![0; 80];
    let r = src.read(&mut skip).unwrap();
    assert!(r == skip.len());
    Some(MovieHeaderBox {
        name: head.name,
        size: head.size,
        timescale: timescale,
        duration: duration,
    })
}

/// Parse a tkhd box.
pub fn read_tkhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Option<TrackHeaderBox> {
    let (version, flags) = read_fullbox_extra(src);
    if flags & 0x1u32 == 0 || flags & 0x2u32 == 0 {
        // Track is disabled.
        return None;
    }
    match version {
        1 => {
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 16];
            let r = src.read(&mut skip).unwrap();
            assert!(r == skip.len());
        },
        0 => {
            // 32 bit creation and modification times.
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 8];
            let r = src.read(&mut skip).unwrap();
            assert!(r == skip.len());
        },
        _ => panic!("invalid tkhd version"),
    }
    let track_id = src.read_u32::<BigEndian>().unwrap();
    let _reserved = src.read_u32::<BigEndian>().unwrap();
    assert!(_reserved == 0);
    let duration = match version {
        1 => {
            src.read_u64::<BigEndian>().unwrap()
        },
        0 => src.read_u32::<BigEndian>().unwrap() as u64,
        _ => panic!("invalid tkhd version"),
    };
    let _reserved = src.read_u32::<BigEndian>().unwrap();
    let _reserved = src.read_u32::<BigEndian>().unwrap();
    // Skip uninterested fields.
    let mut skip: Vec<u8> = vec![0; 44];
    let r = src.read(&mut skip).unwrap();
    assert!(r == skip.len());
    let width = src.read_u32::<BigEndian>().unwrap();
    let height = src.read_u32::<BigEndian>().unwrap();
    Some(TrackHeaderBox {
        name: head.name,
        size: head.size,
        track_id: track_id,
        duration: duration,
        width: width,
        height: height,
    })
}

/// Convert the iso box type or other 4-character value to a string.
fn fourcc_to_string(name: u32) -> String {
    let u32_to_vec = |u| {
        vec!((u >> 24 & 0xffu32) as u8,
             (u >> 16 & 0xffu32) as u8,
             (u >>  8 & 0xffu32) as u8,
             (u & 0xffu32) as u8)
    };
    let name_bytes = u32_to_vec(name);
    String::from_utf8_lossy(&name_bytes).into_owned()
}

use std::fmt;
impl fmt::Display for BoxHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "'{}' {} bytes", fourcc_to_string(self.name), self.size)
    }
}

impl fmt::Display for FileTypeBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        let brand = fourcc_to_string(self.major_brand);
        write!(f, "'{}' {} bytes '{}' v{}", name, self.size,
            brand, self.minor_version)
    }
}

impl fmt::Display for MovieHeaderBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        write!(f, "'{}' {} bytes duration {}s", name, self.size,
            (self.duration as f64)/(self.timescale as f64))
    }
}

use std::u16;
impl fmt::Display for TrackHeaderBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        // Dimensions are 16.16 fixed-point.
        let base = u16::MAX as f64 + 1.0;
        let width = (self.width as f64) / base;
        let height = (self.height as f64) / base;
        write!(f, "'{}' {} bytes duration {} id {} {}x{}",
            name, self.size, self.duration, self.track_id,
            width, height)
    }
}

#[test]
fn test_read_box_header() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 8];  // minimal box length
    write!(&mut test, "test").unwrap(); // box type
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1952805748);
    assert_eq!(parsed.size, 8);
    println!("box {}", parsed);
}

#[test]
fn test_read_box_header_long() {
    use std::io::Cursor;
    let mut test: Vec<u8> = vec![0, 0, 0, 1]; // long box extension code
    test.extend("long".to_string().into_bytes()); // box type
    test.extend(vec![0, 0, 0, 0, 0, 0, 16, 0]); // 64 bit size
    // Skip generating box content.
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1819242087);
    assert_eq!(parsed.size, 4096);
    println!("box {}", parsed);
}

#[test]
fn test_read_ftyp() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 24]; // size
    write!(&mut test, "ftyp").unwrap(); // type
    write!(&mut test, "mp42").unwrap(); // major brand
    test.extend(vec![0, 0, 0, 0]);      // minor version
    write!(&mut test, "isom").unwrap(); // compatible brands...
    write!(&mut test, "mp42").unwrap();
    assert_eq!(test.len(), 24);

    let mut stream = Cursor::new(test);
    let header = read_box_header(&mut stream).unwrap();
    let parsed = read_ftyp(&mut stream, &header).unwrap();
    assert_eq!(parsed.name, 1718909296);
    assert_eq!(parsed.size, 24);
    assert_eq!(parsed.major_brand, 1836069938);
    assert_eq!(parsed.minor_version, 0);
    assert_eq!(parsed.compatible_brands.len(), 2);
    println!("box {}", parsed);
}
<commit_msg>Wrap long declaration.<commit_after>// Module for parsing ISO Base Media Format aka video/mp4 streams.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

/// Basic ISO box structure.
pub struct BoxHeader {
    /// Four character box type
pub name: u32,
    /// Size of the box in bytes
pub size: u64,
    /// Offset to the start of the contained data (or header size).
pub offset: u64,
}

/// File type box 'ftyp'.
pub struct FileTypeBox {
    name: u32,
    size: u64,
    major_brand: u32,
    minor_version: u32,
    compatible_brands: Vec<u32>,
}

/// Movie header box 'mvhd'.
pub struct MovieHeaderBox {
    pub name: u32,
    pub size: u64,
    pub timescale: u32,
    pub duration: u64,
    // Ignore other fields.
}

pub struct TrackHeaderBox {
    pub name: u32,
    pub size: u64,
    pub track_id: u32,
    pub duration: u64,
    pub width: u32,
    pub height: u32,
}

extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{Read, Result, Seek, SeekFrom, Take};
use std::io::Cursor;

/// Parse a box out of a data buffer.
pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Result<BoxHeader> {
    let tmp_size = try!(src.read_u32::<BigEndian>());
    let name = try!(src.read_u32::<BigEndian>());
    let size = match tmp_size {
        1 => try!(src.read_u64::<BigEndian>()),
        _ => tmp_size as u64,
    };
    assert!(size >= 8);
    if tmp_size == 1 {
        assert!(size >= 16);
    }
    let offset = match tmp_size {
        1 => 4 + 4 + 8,
        _ => 4 + 4,
    };
    assert!(offset <= size);
    Ok(BoxHeader{
      name: name,
      size: size,
      offset: offset,
    })
}

/// Parse the extra header fields for a full box.
fn read_fullbox_extra<T: ReadBytesExt>(src: &mut T) -> (u8, u32) {
    let version = src.read_u8().unwrap();
    let flags_a = src.read_u8().unwrap();
    let flags_b = src.read_u8().unwrap();
    let flags_c = src.read_u8().unwrap();
    (version, (flags_a as u32) << 16 |
              (flags_b as u32) <<  8 |
              (flags_c as u32))
}

/// Skip over the contents of a box.
pub fn skip_box_content<T: ReadBytesExt + Seek>
  (src: &mut T, header: &BoxHeader)
  -> std::io::Result<u64>
{
    src.seek(SeekFrom::Current((header.size - header.offset) as i64))
}

/// Helper to construct a Take over the contents of a box.
fn limit<'a, T: Read>(f: &'a mut T, h: &BoxHeader) -> Take<&'a mut T> {
    f.take(h.size - h.offset)
}

/// Helper to construct a Cursor over the contents of a box.
fn recurse<T: Read>(f: &mut T, h: &BoxHeader) {
    println!("{} -- recursing", h);
    // FIXME: I couldn't figure out how to do this without copying.
    // We use Seek on the Read we return in skip_box_content, but
    // that trait isn't implemented for a Take like our limit()
    // returns. Slurping the buffer and wrapping it in a Cursor
    // functions as a work around.
    let buf: Vec<u8> = limit(f, &h)
        .bytes()
        .map(|u| u.unwrap())
        .collect();
    let mut content = Cursor::new(buf);
    loop {
        read_box(&mut content).unwrap();
    }
    println!("{} -- end", h);
}

/// Read the contents of a box, including sub boxes.
/// Right now it just prints the box value rather than
/// returning anything.
pub fn read_box<T: Read + Seek>(f: &mut T) -> Result<()> {
    read_box_header(f).and_then(|h| {
        match &(fourcc_to_string(h.name))[..] {
            "ftyp" => {
                let mut content = limit(f, &h);
                let ftyp = read_ftyp(&mut content, &h).unwrap();
                println!("{}", ftyp);
            },
            "moov" => recurse(f, &h),
            "mvhd" => {
                let mut content = limit(f, &h);
                let mvhd = read_mvhd(&mut content, &h).unwrap();
                println!("  {}", mvhd);
            },
            "trak" => recurse(f, &h),
            "tkhd" => {
                let mut content = limit(f, &h);
                let tkhd = read_tkhd(&mut content, &h).unwrap();
                println!("  {}", tkhd);
            },
            _ => {
                // Skip the contents of unknown chunks.
                println!("{} (skipped)", h);
                skip_box_content(f, &h).unwrap();
            },
        };
        Ok(()) // and_then needs a Result to return.
    })
}

/// Entry point for C language callers.
/// Take a buffer and call read_box() on it.
#[no_mangle]
pub unsafe extern fn read_box_from_buffer(buffer: *const u8, size: usize)
  -> bool {
    use std::slice;
    use std::thread;

    // Validate arguments from C.
    if buffer.is_null() || size < 8 {
        return false;
    }

    // Wrap the buffer we've been give in a slice.
    let b = slice::from_raw_parts(buffer, size);
    let mut c = Cursor::new(b);

    // Parse in a subthread.
    let task = thread::spawn(move || {
        read_box(&mut c).unwrap();
    });
    // Catch any panics.
    task.join().is_ok()
}

/// Parse an ftype box.
pub fn read_ftyp<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Option<FileTypeBox> {
    let major = src.read_u32::<BigEndian>().unwrap();
    let minor = src.read_u32::<BigEndian>().unwrap();
    let brand_count = (head.size - 8 - 8) /4;
    let mut brands = Vec::new();
    for _ in 0..brand_count {
        brands.push(src.read_u32::<BigEndian>().unwrap());
    }
    Some(FileTypeBox{
        name: head.name,
        size: head.size,
        major_brand: major,
        minor_version: minor,
        compatible_brands: brands,
    })
}

/// Parse an mvhd box.
pub fn read_mvhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Option<MovieHeaderBox> {
    let (version, _) = read_fullbox_extra(src);
    match version {
        1 => {
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 16];
            let r = src.read(&mut skip).unwrap();
            assert!(r == skip.len());
        },
        0 => {
            // 32 bit creation and modification times.
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 8];
            let r = src.read(&mut skip).unwrap();
            assert!(r == skip.len());
        },
        _ => panic!("invalid mhdr version"),
    }
    let timescale = src.read_u32::<BigEndian>().unwrap();
    let duration = match version {
        1 => src.read_u64::<BigEndian>().unwrap(),
        0 => src.read_u32::<BigEndian>().unwrap() as u64,
        _ => panic!("invalid mhdr version"),
    };
    // Skip remaining fields.
    let mut skip: Vec<u8> = vec![0; 80];
    let r = src.read(&mut skip).unwrap();
    assert!(r == skip.len());
    Some(MovieHeaderBox {
        name: head.name,
        size: head.size,
        timescale: timescale,
        duration: duration,
    })
}

/// Parse a tkhd box.
pub fn read_tkhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Option<TrackHeaderBox> {
    let (version, flags) = read_fullbox_extra(src);
    if flags & 0x1u32 == 0 || flags & 0x2u32 == 0 {
        // Track is disabled.
        return None;
    }
    match version {
        1 => {
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 16];
            let r = src.read(&mut skip).unwrap();
            assert!(r == skip.len());
        },
        0 => {
            // 32 bit creation and modification times.
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 8];
            let r = src.read(&mut skip).unwrap();
            assert!(r == skip.len());
        },
        _ => panic!("invalid tkhd version"),
    }
    let track_id = src.read_u32::<BigEndian>().unwrap();
    let _reserved = src.read_u32::<BigEndian>().unwrap();
    assert!(_reserved == 0);
    let duration = match version {
        1 => {
            src.read_u64::<BigEndian>().unwrap()
        },
        0 => src.read_u32::<BigEndian>().unwrap() as u64,
        _ => panic!("invalid tkhd version"),
    };
    let _reserved = src.read_u32::<BigEndian>().unwrap();
    let _reserved = src.read_u32::<BigEndian>().unwrap();
    // Skip uninterested fields.
    let mut skip: Vec<u8> = vec![0; 44];
    let r = src.read(&mut skip).unwrap();
    assert!(r == skip.len());
    let width = src.read_u32::<BigEndian>().unwrap();
    let height = src.read_u32::<BigEndian>().unwrap();
    Some(TrackHeaderBox {
        name: head.name,
        size: head.size,
        track_id: track_id,
        duration: duration,
        width: width,
        height: height,
    })
}

/// Convert the iso box type or other 4-character value to a string.
fn fourcc_to_string(name: u32) -> String {
    let u32_to_vec = |u| {
        vec!((u >> 24 & 0xffu32) as u8,
             (u >> 16 & 0xffu32) as u8,
             (u >>  8 & 0xffu32) as u8,
             (u & 0xffu32) as u8)
    };
    let name_bytes = u32_to_vec(name);
    String::from_utf8_lossy(&name_bytes).into_owned()
}

use std::fmt;
impl fmt::Display for BoxHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "'{}' {} bytes", fourcc_to_string(self.name), self.size)
    }
}

impl fmt::Display for FileTypeBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        let brand = fourcc_to_string(self.major_brand);
        write!(f, "'{}' {} bytes '{}' v{}", name, self.size,
            brand, self.minor_version)
    }
}

impl fmt::Display for MovieHeaderBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        write!(f, "'{}' {} bytes duration {}s", name, self.size,
            (self.duration as f64)/(self.timescale as f64))
    }
}

use std::u16;
impl fmt::Display for TrackHeaderBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        // Dimensions are 16.16 fixed-point.
        let base = u16::MAX as f64 + 1.0;
        let width = (self.width as f64) / base;
        let height = (self.height as f64) / base;
        write!(f, "'{}' {} bytes duration {} id {} {}x{}",
            name, self.size, self.duration, self.track_id,
            width, height)
    }
}

#[test]
fn test_read_box_header() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 8];  // minimal box length
    write!(&mut test, "test").unwrap(); // box type
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1952805748);
    assert_eq!(parsed.size, 8);
    println!("box {}", parsed);
}

#[test]
fn test_read_box_header_long() {
    use std::io::Cursor;
    let mut test: Vec<u8> = vec![0, 0, 0, 1]; // long box extension code
    test.extend("long".to_string().into_bytes()); // box type
    test.extend(vec![0, 0, 0, 0, 0, 0, 16, 0]); // 64 bit size
    // Skip generating box content.
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1819242087);
    assert_eq!(parsed.size, 4096);
    println!("box {}", parsed);
}

#[test]
fn test_read_ftyp() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 24]; // size
    write!(&mut test, "ftyp").unwrap(); // type
    write!(&mut test, "mp42").unwrap(); // major brand
    test.extend(vec![0, 0, 0, 0]);      // minor version
    write!(&mut test, "isom").unwrap(); // compatible brands...
    write!(&mut test, "mp42").unwrap();
    assert_eq!(test.len(), 24);

    let mut stream = Cursor::new(test);
    let header = read_box_header(&mut stream).unwrap();
    let parsed = read_ftyp(&mut stream, &header).unwrap();
    assert_eq!(parsed.name, 1718909296);
    assert_eq!(parsed.size, 24);
    assert_eq!(parsed.major_brand, 1836069938);
    assert_eq!(parsed.minor_version, 0);
    assert_eq!(parsed.compatible_brands.len(), 2);
    println!("box {}", parsed);
}
<|endoftext|>


<commit_before>use itertools::Itertools;
use std::fmt::Debug;
use quickcheck::quickcheck;

struct Unspecialized<I>(I);
impl<I> Iterator for Unspecialized<I>
where
    I: Iterator,
{
    type Item = I::Item;

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
where
    V: Eq + Debug,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
    F: Fn(Box<dyn Iterator<Item = IterItem> + 'a>) -> V,
{
    assert_eq!(
        mapper(Box::new(Unspecialized(iterator.clone()))),
        mapper(Box::new(iterator.clone()))
    )
}

fn test_specializations<IterItem, Iter>(
    it: &Iter,
) where
    IterItem: Eq + Debug + Clone,
    Iter: Iterator<Item = IterItem> + Clone,
{
    check_specialized(it, |i| i.count());
    check_specialized(it, |i| i.last());
    check_specialized(it, |i| i.collect::<Vec<_>>());
    check_specialized(it, |i| {
        let mut parameters_from_fold = vec![];
        let fold_result = i.fold(vec![], |mut acc, v: IterItem| {
            parameters_from_fold.push((acc.clone(), v.clone()));
            acc.push(v);
            acc
        });
        (parameters_from_fold, fold_result)
    });
    check_specialized(it, |mut i| {
        let mut parameters_from_all = vec![];
        let first = i.next();
        let all_result = i.all(|x| {
            parameters_from_all.push(x.clone());
            Some(x)==first
        });
        (parameters_from_all, all_result)
    });
    let size = it.clone().count();
    for n in 0..size + 2 {
        check_specialized(it, |mut i| i.nth(n));
    }
    // size_hint is a bit harder to check
    let mut it_sh = it.clone();
    for n in 0..size + 2 {
        let len = it_sh.clone().count();
        let (min, max) = it_sh.size_hint();
        assert_eq!(size - n.min(size), len);
        assert!(min <= len);
        if let Some(max) = max {
            assert!(len <= max);
        }
        it_sh.next();
    }
}

quickcheck! {
    fn put_back_qc(test_vec: Vec<i32>) -> () {
        test_specializations(&itertools::put_back(test_vec.iter()));
        let mut pb = itertools::put_back(test_vec.into_iter());
        pb.put_back(1);
        test_specializations(&pb);
    }
}

quickcheck! {
    fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () {
        test_specializations(&i1.into_iter().merge_join_by(i2.into_iter(), std::cmp::Ord::cmp));
    }
}
<commit_msg>Canonicalize special cases of `map` (4) test specializations<commit_after>use itertools::Itertools;
use std::fmt::Debug;
use quickcheck::quickcheck;

struct Unspecialized<I>(I);
impl<I> Iterator for Unspecialized<I>
where
    I: Iterator,
{
    type Item = I::Item;

    #[inline(always)]
    fn next(&mut self) -> Option<Self::Item> {
        self.0.next()
    }
}

fn check_specialized<'a, V, IterItem, Iter, F>(iterator: &Iter, mapper: F)
where
    V: Eq + Debug,
    Iter: Iterator<Item = IterItem> + Clone + 'a,
    F: Fn(Box<dyn Iterator<Item = IterItem> + 'a>) -> V,
{
    assert_eq!(
        mapper(Box::new(Unspecialized(iterator.clone()))),
        mapper(Box::new(iterator.clone()))
    )
}

fn test_specializations<IterItem, Iter>(
    it: &Iter,
) where
    IterItem: Eq + Debug + Clone,
    Iter: Iterator<Item = IterItem> + Clone,
{
    check_specialized(it, |i| i.count());
    check_specialized(it, |i| i.last());
    check_specialized(it, |i| i.collect::<Vec<_>>());
    check_specialized(it, |i| {
        let mut parameters_from_fold = vec![];
        let fold_result = i.fold(vec![], |mut acc, v: IterItem| {
            parameters_from_fold.push((acc.clone(), v.clone()));
            acc.push(v);
            acc
        });
        (parameters_from_fold, fold_result)
    });
    check_specialized(it, |mut i| {
        let mut parameters_from_all = vec![];
        let first = i.next();
        let all_result = i.all(|x| {
            parameters_from_all.push(x.clone());
            Some(x)==first
        });
        (parameters_from_all, all_result)
    });
    let size = it.clone().count();
    for n in 0..size + 2 {
        check_specialized(it, |mut i| i.nth(n));
    }
    // size_hint is a bit harder to check
    let mut it_sh = it.clone();
    for n in 0..size + 2 {
        let len = it_sh.clone().count();
        let (min, max) = it_sh.size_hint();
        assert_eq!(size - n.min(size), len);
        assert!(min <= len);
        if let Some(max) = max {
            assert!(len <= max);
        }
        it_sh.next();
    }
}

quickcheck! {
    fn put_back_qc(test_vec: Vec<i32>) -> () {
        test_specializations(&itertools::put_back(test_vec.iter()));
        let mut pb = itertools::put_back(test_vec.into_iter());
        pb.put_back(1);
        test_specializations(&pb);
    }
}

quickcheck! {
    fn merge_join_by_qc(i1: Vec<usize>, i2: Vec<usize>) -> () {
        test_specializations(&i1.into_iter().merge_join_by(i2.into_iter(), std::cmp::Ord::cmp));
    }
}

quickcheck! {
    fn map_into(v: Vec<u8>) -> () {
        test_specializations(&v.into_iter().map_into::<u32>());
    }
}

quickcheck! {
    fn map_ok(v: Vec<Result<u8, char>>) -> () {
        test_specializations(&v.into_iter().map_ok(|u| u.checked_add(1)));
    }
}
<|endoftext|>