<commit_before>// Copyright (c) 2019, Ben Boeckel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use crate::keytypes::User;
use crate::{KeyPermissions, Permission};

use super::utils;
use super::utils::kernel::*;

#[test]
fn invalid_key_chown() {
    let mut key = utils::invalid_key();
    let err = key.chown(*UID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_key_chgrp() {
    let mut key = utils::invalid_key();
    let err = key.chgrp(*GID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_key_chmod() {
    let mut key = utils::invalid_key();
    let err = key.set_permissions(Permission::POSSESSOR_VIEW).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_keyring_chown() {
    let mut keyring = utils::invalid_key();
    let err = keyring.chown(*UID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_keyring_chgrp() {
    let mut keyring = utils::invalid_key();
    let err = keyring.chgrp(*GID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_keyring_chmod() {
    let mut keyring = utils::invalid_keyring();
    let err = keyring.set_permissions(Permission::empty()).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_key_permissions() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("invalid_key_permissions", payload)
        .unwrap();

    let err = key
        .set_permissions_raw(KeyPermissions::max_value())
        .unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_keyring_permissions() {
    let mut keyring = utils::new_test_keyring();

    let err = keyring
        .set_permissions_raw(KeyPermissions::max_value())
        .unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn unlinked_key_chown() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("unlinked_key_chown", payload)
        .unwrap();

    keyring.unlink_key(&key).unwrap();
    utils::wait_for_key_gc(&key);

    let err = key.chown(*UID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::ENOKEY));
}

#[test]
fn unlinked_key_chgrp() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("unlinked_key_chgrp", payload)
        .unwrap();

    keyring.unlink_key(&key).unwrap();
    utils::wait_for_key_gc(&key);

    let err = key.chgrp(*GID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::ENOKEY));
}

#[test]
fn unlinked_key_chmod() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("unlinked_key_chmod", payload)
        .unwrap();

    keyring.unlink_key(&key).unwrap();
    utils::wait_for_key_gc(&key);

    let err = key.set_permissions(Permission::POSSESSOR_VIEW).unwrap_err();
    assert_eq!(err, errno::Errno(libc::ENOKEY));
}

#[test]
fn chown_keyring() {
    let mut keyring = utils::new_test_keyring();

    if *UID == 0 {
        keyring.chown(1).unwrap();
        keyring.chown(0).unwrap();
    } else {
        let err = keyring.chown(1).unwrap_err();
        assert_eq!(err, errno::Errno(libc::EACCES));
    }
}

#[test]
fn chown_key() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring.add_key::<User, _, _>("chown_key", payload).unwrap();

    if *UID == 0 {
        key.chown(1).unwrap();
        key.chown(0).unwrap();
    } else {
        let err = key.chown(1).unwrap_err();
        assert_eq!(err, errno::Errno(libc::EACCES));
    }
}

#[test]
fn set_each_permission_bit() {
    let permission_bits = [
        Permission::OTHER_VIEW,
        Permission::OTHER_READ,
        Permission::OTHER_WRITE,
        Permission::OTHER_SEARCH,
        Permission::OTHER_LINK,
        Permission::OTHER_SET_ATTRIBUTE,
        Permission::GROUP_VIEW,
        Permission::GROUP_READ,
        Permission::GROUP_WRITE,
        Permission::GROUP_SEARCH,
        Permission::GROUP_LINK,
        Permission::GROUP_SET_ATTRIBUTE,
        Permission::USER_VIEW,
        Permission::USER_READ,
        Permission::USER_WRITE,
        Permission::USER_SEARCH,
        Permission::USER_LINK,
        Permission::USER_SET_ATTRIBUTE,
        Permission::POSSESSOR_VIEW,
        Permission::POSSESSOR_READ,
        Permission::POSSESSOR_WRITE,
        Permission::POSSESSOR_SEARCH,
        Permission::POSSESSOR_LINK,
        Permission::POSSESSOR_SET_ATTRIBUTE,
    ];
    let required_permissions = Permission::USER_SET_ATTRIBUTE | Permission::USER_VIEW;

    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("set_each_permission_bit", payload)
        .unwrap();

    for permission_bit in &permission_bits {
        let perms = required_permissions | *permission_bit;
        key.set_permissions(perms).unwrap();
        let description = key.description().unwrap();
        assert_eq!(perms, description.perms);
    }
}

#[test]
fn cannot_view_via_group() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("cannot_view_via_group", payload)
        .unwrap();

    let perms = Permission::GROUP_ALL | Permission::USER_SET_ATTRIBUTE;
    key.set_permissions(perms).unwrap();

    let err = key.read().unwrap_err();
    assert_eq!(err, errno::Errno(libc::EACCES));
}

#[test]
fn cannot_view_via_other() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("cannot_view_via_other", payload)
        .unwrap();

    let perms = Permission::OTHER_ALL | Permission::USER_SET_ATTRIBUTE;
    key.set_permissions(perms).unwrap();

    let err = key.read().unwrap_err();
    assert_eq!(err, errno::Errno(libc::EACCES));
}

#[test]
fn remove_setattr() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("remove_setattr", payload)
        .unwrap();

    let perms = Permission::all()
        - (Permission::POSSESSOR_SET_ATTRIBUTE
            | Permission::USER_SET_ATTRIBUTE
            | Permission::GROUP_SET_ATTRIBUTE
            | Permission::OTHER_SET_ATTRIBUTE);
    key.set_permissions(perms).unwrap();

    let err = key.set_permissions(Permission::all()).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EACCES));
}
<commit_msg>tests/permitting: allow root not having chown permission too<commit_after>// Copyright (c) 2019, Ben Boeckel
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//     * Redistributions of source code must retain the above copyright notice,
//       this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above copyright notice,
//       this list of conditions and the following disclaimer in the documentation
//       and/or other materials provided with the distribution.
//     * Neither the name of this project nor the names of its contributors
//       may be used to endorse or promote products derived from this software
//       without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use crate::keytypes::User;
use crate::{KeyPermissions, Permission};

use super::utils;
use super::utils::kernel::*;

#[test]
fn invalid_key_chown() {
    let mut key = utils::invalid_key();
    let err = key.chown(*UID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_key_chgrp() {
    let mut key = utils::invalid_key();
    let err = key.chgrp(*GID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_key_chmod() {
    let mut key = utils::invalid_key();
    let err = key.set_permissions(Permission::POSSESSOR_VIEW).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_keyring_chown() {
    let mut keyring = utils::invalid_key();
    let err = keyring.chown(*UID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_keyring_chgrp() {
    let mut keyring = utils::invalid_key();
    let err = keyring.chgrp(*GID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_keyring_chmod() {
    let mut keyring = utils::invalid_keyring();
    let err = keyring.set_permissions(Permission::empty()).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_key_permissions() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("invalid_key_permissions", payload)
        .unwrap();

    let err = key
        .set_permissions_raw(KeyPermissions::max_value())
        .unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn invalid_keyring_permissions() {
    let mut keyring = utils::new_test_keyring();

    let err = keyring
        .set_permissions_raw(KeyPermissions::max_value())
        .unwrap_err();
    assert_eq!(err, errno::Errno(libc::EINVAL));
}

#[test]
fn unlinked_key_chown() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("unlinked_key_chown", payload)
        .unwrap();

    keyring.unlink_key(&key).unwrap();
    utils::wait_for_key_gc(&key);

    let err = key.chown(*UID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::ENOKEY));
}

#[test]
fn unlinked_key_chgrp() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("unlinked_key_chgrp", payload)
        .unwrap();

    keyring.unlink_key(&key).unwrap();
    utils::wait_for_key_gc(&key);

    let err = key.chgrp(*GID).unwrap_err();
    assert_eq!(err, errno::Errno(libc::ENOKEY));
}

#[test]
fn unlinked_key_chmod() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("unlinked_key_chmod", payload)
        .unwrap();

    keyring.unlink_key(&key).unwrap();
    utils::wait_for_key_gc(&key);

    let err = key.set_permissions(Permission::POSSESSOR_VIEW).unwrap_err();
    assert_eq!(err, errno::Errno(libc::ENOKEY));
}

#[test]
fn chown_keyring() {
    let mut keyring = utils::new_test_keyring();

    if *UID == 0 {
        match keyring.chown(1) {
            // If that worked, make sure we can move it back.
            Ok(_) => keyring.chown(0).unwrap(),
            // Otherwise, we got the right error.
            Err(err) => assert_eq!(err, errno::Errno(libc::EACCES)),
        }
    } else {
        let err = keyring.chown(1).unwrap_err();
        assert_eq!(err, errno::Errno(libc::EACCES));
    }
}

#[test]
fn chown_key() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring.add_key::<User, _, _>("chown_key", payload).unwrap();

    if *UID == 0 {
        match key.chown(1) {
            // If that worked, make sure we can move it back.
            Ok(_) => key.chown(0).unwrap(),
            // Otherwise, we got the right error.
            Err(err) => assert_eq!(err, errno::Errno(libc::EACCES)),
        }
        let err = key.chown(1).unwrap_err();
        assert_eq!(err, errno::Errno(libc::EACCES));
    }
}

#[test]
fn set_each_permission_bit() {
    let permission_bits = [
        Permission::OTHER_VIEW,
        Permission::OTHER_READ,
        Permission::OTHER_WRITE,
        Permission::OTHER_SEARCH,
        Permission::OTHER_LINK,
        Permission::OTHER_SET_ATTRIBUTE,
        Permission::GROUP_VIEW,
        Permission::GROUP_READ,
        Permission::GROUP_WRITE,
        Permission::GROUP_SEARCH,
        Permission::GROUP_LINK,
        Permission::GROUP_SET_ATTRIBUTE,
        Permission::USER_VIEW,
        Permission::USER_READ,
        Permission::USER_WRITE,
        Permission::USER_SEARCH,
        Permission::USER_LINK,
        Permission::USER_SET_ATTRIBUTE,
        Permission::POSSESSOR_VIEW,
        Permission::POSSESSOR_READ,
        Permission::POSSESSOR_WRITE,
        Permission::POSSESSOR_SEARCH,
        Permission::POSSESSOR_LINK,
        Permission::POSSESSOR_SET_ATTRIBUTE,
    ];
    let required_permissions = Permission::USER_SET_ATTRIBUTE | Permission::USER_VIEW;

    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("set_each_permission_bit", payload)
        .unwrap();

    for permission_bit in &permission_bits {
        let perms = required_permissions | *permission_bit;
        key.set_permissions(perms).unwrap();
        let description = key.description().unwrap();
        assert_eq!(perms, description.perms);
    }
}

#[test]
fn cannot_view_via_group() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("cannot_view_via_group", payload)
        .unwrap();

    let perms = Permission::GROUP_ALL | Permission::USER_SET_ATTRIBUTE;
    key.set_permissions(perms).unwrap();

    let err = key.read().unwrap_err();
    assert_eq!(err, errno::Errno(libc::EACCES));
}

#[test]
fn cannot_view_via_other() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("cannot_view_via_other", payload)
        .unwrap();

    let perms = Permission::OTHER_ALL | Permission::USER_SET_ATTRIBUTE;
    key.set_permissions(perms).unwrap();

    let err = key.read().unwrap_err();
    assert_eq!(err, errno::Errno(libc::EACCES));
}

#[test]
fn remove_setattr() {
    let mut keyring = utils::new_test_keyring();
    let payload = "payload".as_bytes();
    let mut key = keyring
        .add_key::<User, _, _>("remove_setattr", payload)
        .unwrap();

    let perms = Permission::all()
        - (Permission::POSSESSOR_SET_ATTRIBUTE
            | Permission::USER_SET_ATTRIBUTE
            | Permission::GROUP_SET_ATTRIBUTE
            | Permission::OTHER_SET_ATTRIBUTE);
    key.set_permissions(perms).unwrap();

    let err = key.set_permissions(Permission::all()).unwrap_err();
    assert_eq!(err, errno::Errno(libc::EACCES));
}
<|endoftext|>


<commit_before>//! Traits giving structural informations on linear algebra objects or the space they live in.

use std::num::{Zero, Bounded};
use std::slice::{Items, MutItems};
use traits::operations::{RMul, LMul, ScalarAdd, ScalarSub, Axpy};
use traits::geometry::{Dot, Norm, UniformSphereSample, Orig};

/// Traits of objects which can be created from an object of type `T`.
pub trait Cast<T> {
    /// Converts an element of type `T` to an element of type `Self`.
    fn from(t: T) -> Self;
}

/// Trait of matrices.
///
/// A matrix has rows and columns and are able to multiply them.
pub trait Mat<R, C> : Row<R> + Col<C> + RMul<R> + LMul<C> { }

impl<M: Row<R> + Col<C> + RMul<R> + LMul<C>, R, C> Mat<R, C> for M {
}

/// Trait for constructing the identity matrix
pub trait Eye {
    /// Return the identity matrix of specified dimension
    fn new_identity(dim: uint) -> Self;
}

// XXX: we keep ScalarAdd and ScalarSub here to avoid trait impl conflict (overriding) between the
// different Add/Sub traits. This is _so_ unfortunate…

// FIXME: return an iterator instead
/// Traits of objects which can form a basis (typically vectors).
pub trait Basis {
    /// Iterates through the canonical basis of the space in which this object lives.
    fn canonical_basis(|Self| -> bool);

    /// Iterates through a basis of the subspace orthogonal to `self`.
    fn orthonormal_subspace_basis(&Self, |Self| -> bool);
}

/// Trait to access rows of a matrix or a vector.
pub trait Row<R> {
    /// The number of column of `self`.
    fn nrows(&self) -> uint;
    /// Reads the `i`-th row of `self`.
    fn row(&self, i: uint) -> R;
    /// Writes the `i`-th row of `self`.
    fn set_row(&mut self, i: uint, R);

    // FIXME: add iterators on rows: this could be a very good way to generalize _and_ optimize
    // a lot of operations.
}

/// Trait to access columns of a matrix or vector.
pub trait Col<C> {
    /// The number of column of this matrix or vector.
    fn ncols(&self) -> uint;

    /// Reads the `i`-th column of `self`.
    fn col(&self, i: uint) -> C;

    /// Writes the `i`-th column of `self`.
    fn set_col(&mut self, i: uint, C);

    // FIXME: add iterators on columns: this could be a very good way to generalize _and_ optimize
    // a lot of operations.
}

/// Trait to access part of a column of a matrix
pub trait ColSlice<C> {
    /// Returns a view to a slice of a column of a matrix.
    fn col_slice(&self, col_id: uint, row_start: uint, row_end: uint) -> C;
}

/// Trait to access part of a row of a matrix
pub trait RowSlice<R> {
    /// Returns a view to a slice of a row of a matrix.
    fn row_slice(&self, row_id: uint, col_start: uint, col_end: uint) -> R;
}

/// Trait of objects having a spacial dimension known at compile time.
pub trait Dim {
    /// The dimension of the object.
    fn dim(unused_self: Option<Self>) -> uint;
}

/// Trait to get the diagonal of square matrices.
pub trait Diag<V> {
    /// Creates a new matrix with the given diagonal.
    fn from_diag(diag: &V) -> Self;

    /// Sets the diagonal of this matrix.
    fn set_diag(&mut self, diag: &V);

    /// The diagonal of this matrix.
    fn diag(&self) -> V;
}

// FIXME: this trait should not be on nalgebra.
// however, it is needed because std::ops::Index is (strangely) to poor: it
// does not have a function to set values.
// Also, using Index with tuples crashes.
/// This is a workaround of current Rust limitations.
///
/// It exists because the `Index` trait cannot be used to express write access.
/// Thus, this is the same as the `Index` trait but without the syntactic sugar and with a method
/// to write to a specific index.
pub trait Indexable<Index, Res> {
    /// Reads the `i`-th element of `self`.
    fn at(&self, i: Index) -> Res;
    /// Writes to the `i`-th element of `self`.
    fn set(&mut self, i: Index, Res);
    /// Swaps the `i`-th element of `self` with its `j`-th element.
    fn swap(&mut self, i: Index, j: Index);

    /// Returns the shape of the iterable range.
    fn shape(&self) -> Index;

    /// Reads the `i`-th element of `self`.
    ///
    /// `i` is not checked.
    unsafe fn unsafe_at(&self, i: Index) -> Res;
    /// Writes to the `i`-th element of `self`.
    ///
    /// `i` is not checked.
    unsafe fn unsafe_set(&mut self, i: Index, Res);
}

/// This is a workaround of current Rust limitations.
///
/// Traits of objects which can be iterated through like a vector.
pub trait Iterable<N> {
    /// Gets a vector-like read-only iterator.
    fn iter<'l>(&'l self) -> Items<'l, N>;
}

/// This is a workaround of current Rust limitations.
///
/// Traits of mutable objects which can be iterated through like a vector.
pub trait IterableMut<N> {
    /// Gets a vector-like read-write iterator.
    fn iter_mut<'l>(&'l mut self) -> MutItems<'l, N>;
}

/*
 * Vec related traits.
 */
/// Trait that relates a point of an affine space to a vector of the associated vector space.
#[deprecated = "This will be removed in the future. Use point + vector operations instead."]
pub trait VecAsPnt<P> {
    /// Converts this point to its associated vector.
    fn to_pnt(self) -> P;

    /// Converts a reference to this point to a reference to its associated vector.
    fn as_pnt<'a>(&'a self) -> &'a P;
}

/// Trait grouping most common operations on vectors.
pub trait AnyVec<N>: Dim + Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + PartialEq + Mul<N, Self>
                     + Div<N, Self> + Dot<N> + Axpy<N> {
}

/// Trait of vector with components implementing the `Float` trait.
pub trait FloatVec<N: Float>: AnyVec<N> + Norm<N> {
}

/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on vectors.
pub trait AnyVecExt<N>: AnyVec<N> + Indexable<uint, N> + Index<uint, N> + IndexMut<uint, N> +
                        Iterable<N> + UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded
{ }

/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on vectors.
pub trait FloatVecExt<N: Float>: FloatVec<N> + AnyVecExt<N> + Basis { }

impl<N, V: Dim + Sub<V, V> + Add<V, V> + Neg<V> + Zero + PartialEq + Mul<N, V> + Div<N, V> + Dot<N> + Axpy<N>>
AnyVec<N> for V { }

impl<N: Float, V: AnyVec<N> + Norm<N>> FloatVec<N> for V { }

impl<N,
     V: AnyVec<N> + Indexable<uint, N> + Index<uint, N> + IndexMut<uint, N> + Iterable<N> +
        UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded>
AnyVecExt<N> for V { }

impl<N: Float, V: FloatVec<N> + AnyVecExt<N> + Basis> FloatVecExt<N> for V { }

/*
 * Pnt related traits.
 */
/// Trait that relates a point of an affine space to a vector of the associated vector space.
pub trait PntAsVec<V> {
    /// Converts this point to its associated vector.
    fn to_vec(self) -> V;

    /// Converts a reference to this point to a reference to its associated vector.
    fn as_vec<'a>(&'a self) -> &'a V;

    // NOTE: this is used in some places to overcome some limitations untill the trait reform is
    // done on rustc.
    /// Sets the coordinates of this point to match those of a given vector.
    fn set_coords(&mut self, coords: V);
}

/// Trait grouping most common operations on points.
// XXX: the vector space element `V` should be an associated type. Though this would prevent V from
// having bounds (they are not supported yet). So, for now, we will just use a type parameter.
pub trait AnyPnt<N, V>:
          PntAsVec<V> + Dim + Sub<Self, V> + Orig + Neg<Self> + PartialEq + Mul<N, Self> +
          Div<N, Self> + Add<V, Self> { // FIXME: + Sub<V, Self>
}

/// Trait of points with components implementing the `Float` trait.
pub trait FloatPnt<N: Float, V: Norm<N>>: AnyPnt<N, V> {
    /// Computes the square distance between two points.
    #[inline]
    fn sqdist(a: &Self, b: &Self) -> N {
        Norm::sqnorm(&(*a - *b))
    }

    /// Computes the distance between two points.
    #[inline]
    fn dist(a: &Self, b: &Self) -> N {
        Norm::norm(&(*a - *b))
    }
}

/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on points.
pub trait AnyPntExt<N, V>: AnyPnt<N, V> + Indexable<uint, N> + Index<uint, N> + IndexMut<uint, N> +
                           Iterable<N> + ScalarAdd<N> + ScalarSub<N> + Bounded + Axpy<N>
{ }

/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on points.
pub trait FloatPntExt<N: Float, V: Norm<N>> : FloatPnt<N, V> + AnyPntExt<N, V> { }

impl<N, V, P: PntAsVec<V> + Dim + Sub<P, V> + Add<V, P> + Orig + Neg<P> + PartialEq + Mul<N, P> + Div<N, P>>
AnyPnt<N, V> for P { }
impl<N: Float, V: Norm<N>, P: AnyPnt<N, V>> FloatPnt<N, V> for P { }
impl<N, V, P: AnyPnt<N, V> + Indexable<uint, N> + Index<uint, N> + IndexMut<uint, N> + Iterable<N> + ScalarAdd<N> + ScalarSub<N> + Bounded + Axpy<N>>
AnyPntExt<N, V> for P { }
impl<N: Float, V: Norm<N>, P: FloatPnt<N, V> + AnyPntExt<N, V>> FloatPntExt<N, V> for P { }
<commit_msg>Make `AnyVec` inherit from `Basis`.<commit_after>//! Traits giving structural informations on linear algebra objects or the space they live in.

use std::num::{Zero, Bounded};
use std::slice::{Items, MutItems};
use traits::operations::{RMul, LMul, ScalarAdd, ScalarSub, Axpy};
use traits::geometry::{Dot, Norm, UniformSphereSample, Orig};

/// Traits of objects which can be created from an object of type `T`.
pub trait Cast<T> {
    /// Converts an element of type `T` to an element of type `Self`.
    fn from(t: T) -> Self;
}

/// Trait of matrices.
///
/// A matrix has rows and columns and are able to multiply them.
pub trait Mat<R, C> : Row<R> + Col<C> + RMul<R> + LMul<C> { }

impl<M: Row<R> + Col<C> + RMul<R> + LMul<C>, R, C> Mat<R, C> for M {
}

/// Trait for constructing the identity matrix
pub trait Eye {
    /// Return the identity matrix of specified dimension
    fn new_identity(dim: uint) -> Self;
}

// XXX: we keep ScalarAdd and ScalarSub here to avoid trait impl conflict (overriding) between the
// different Add/Sub traits. This is _so_ unfortunate…

// FIXME: return an iterator instead
/// Traits of objects which can form a basis (typically vectors).
pub trait Basis {
    /// Iterates through the canonical basis of the space in which this object lives.
    fn canonical_basis(|Self| -> bool);

    /// Iterates through a basis of the subspace orthogonal to `self`.
    fn orthonormal_subspace_basis(&Self, |Self| -> bool);
}

/// Trait to access rows of a matrix or a vector.
pub trait Row<R> {
    /// The number of column of `self`.
    fn nrows(&self) -> uint;
    /// Reads the `i`-th row of `self`.
    fn row(&self, i: uint) -> R;
    /// Writes the `i`-th row of `self`.
    fn set_row(&mut self, i: uint, R);

    // FIXME: add iterators on rows: this could be a very good way to generalize _and_ optimize
    // a lot of operations.
}

/// Trait to access columns of a matrix or vector.
pub trait Col<C> {
    /// The number of column of this matrix or vector.
    fn ncols(&self) -> uint;

    /// Reads the `i`-th column of `self`.
    fn col(&self, i: uint) -> C;

    /// Writes the `i`-th column of `self`.
    fn set_col(&mut self, i: uint, C);

    // FIXME: add iterators on columns: this could be a very good way to generalize _and_ optimize
    // a lot of operations.
}

/// Trait to access part of a column of a matrix
pub trait ColSlice<C> {
    /// Returns a view to a slice of a column of a matrix.
    fn col_slice(&self, col_id: uint, row_start: uint, row_end: uint) -> C;
}

/// Trait to access part of a row of a matrix
pub trait RowSlice<R> {
    /// Returns a view to a slice of a row of a matrix.
    fn row_slice(&self, row_id: uint, col_start: uint, col_end: uint) -> R;
}

/// Trait of objects having a spacial dimension known at compile time.
pub trait Dim {
    /// The dimension of the object.
    fn dim(unused_self: Option<Self>) -> uint;
}

/// Trait to get the diagonal of square matrices.
pub trait Diag<V> {
    /// Creates a new matrix with the given diagonal.
    fn from_diag(diag: &V) -> Self;

    /// Sets the diagonal of this matrix.
    fn set_diag(&mut self, diag: &V);

    /// The diagonal of this matrix.
    fn diag(&self) -> V;
}

// FIXME: this trait should not be on nalgebra.
// however, it is needed because std::ops::Index is (strangely) to poor: it
// does not have a function to set values.
// Also, using Index with tuples crashes.
/// This is a workaround of current Rust limitations.
///
/// It exists because the `Index` trait cannot be used to express write access.
/// Thus, this is the same as the `Index` trait but without the syntactic sugar and with a method
/// to write to a specific index.
pub trait Indexable<Index, Res> {
    /// Reads the `i`-th element of `self`.
    fn at(&self, i: Index) -> Res;
    /// Writes to the `i`-th element of `self`.
    fn set(&mut self, i: Index, Res);
    /// Swaps the `i`-th element of `self` with its `j`-th element.
    fn swap(&mut self, i: Index, j: Index);

    /// Returns the shape of the iterable range.
    fn shape(&self) -> Index;

    /// Reads the `i`-th element of `self`.
    ///
    /// `i` is not checked.
    unsafe fn unsafe_at(&self, i: Index) -> Res;
    /// Writes to the `i`-th element of `self`.
    ///
    /// `i` is not checked.
    unsafe fn unsafe_set(&mut self, i: Index, Res);
}

/// This is a workaround of current Rust limitations.
///
/// Traits of objects which can be iterated through like a vector.
pub trait Iterable<N> {
    /// Gets a vector-like read-only iterator.
    fn iter<'l>(&'l self) -> Items<'l, N>;
}

/// This is a workaround of current Rust limitations.
///
/// Traits of mutable objects which can be iterated through like a vector.
pub trait IterableMut<N> {
    /// Gets a vector-like read-write iterator.
    fn iter_mut<'l>(&'l mut self) -> MutItems<'l, N>;
}

/*
 * Vec related traits.
 */
/// Trait that relates a point of an affine space to a vector of the associated vector space.
#[deprecated = "This will be removed in the future. Use point + vector operations instead."]
pub trait VecAsPnt<P> {
    /// Converts this point to its associated vector.
    fn to_pnt(self) -> P;

    /// Converts a reference to this point to a reference to its associated vector.
    fn as_pnt<'a>(&'a self) -> &'a P;
}

/// Trait grouping most common operations on vectors.
pub trait AnyVec<N>: Dim + Sub<Self, Self> + Add<Self, Self> + Neg<Self> + Zero + PartialEq + Mul<N, Self>
                     + Div<N, Self> + Dot<N> + Axpy<N> + Basis {
}

/// Trait of vector with components implementing the `Float` trait.
pub trait FloatVec<N: Float>: AnyVec<N> + Norm<N> {
}

/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on vectors.
pub trait AnyVecExt<N>: AnyVec<N> + Indexable<uint, N> + Index<uint, N> + IndexMut<uint, N> +
                        Iterable<N> + UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded
{ }

/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on vectors.
pub trait FloatVecExt<N: Float>: FloatVec<N> + AnyVecExt<N> { }

impl<N, V: Dim + Sub<V, V> + Add<V, V> + Neg<V> + Zero + PartialEq + Mul<N, V> + Div<N, V> + Dot<N> + Axpy<N> + Basis>
AnyVec<N> for V { }

impl<N: Float, V: AnyVec<N> + Norm<N>> FloatVec<N> for V { }

impl<N,
     V: AnyVec<N> + Indexable<uint, N> + Index<uint, N> + IndexMut<uint, N> + Iterable<N> +
        UniformSphereSample + ScalarAdd<N> + ScalarSub<N> + Bounded>
AnyVecExt<N> for V { }

impl<N: Float, V: FloatVec<N> + AnyVecExt<N>> FloatVecExt<N> for V { }

/*
 * Pnt related traits.
 */
/// Trait that relates a point of an affine space to a vector of the associated vector space.
pub trait PntAsVec<V> {
    /// Converts this point to its associated vector.
    fn to_vec(self) -> V;

    /// Converts a reference to this point to a reference to its associated vector.
    fn as_vec<'a>(&'a self) -> &'a V;

    // NOTE: this is used in some places to overcome some limitations untill the trait reform is
    // done on rustc.
    /// Sets the coordinates of this point to match those of a given vector.
    fn set_coords(&mut self, coords: V);
}

/// Trait grouping most common operations on points.
// XXX: the vector space element `V` should be an associated type. Though this would prevent V from
// having bounds (they are not supported yet). So, for now, we will just use a type parameter.
pub trait AnyPnt<N, V>:
          PntAsVec<V> + Dim + Sub<Self, V> + Orig + Neg<Self> + PartialEq + Mul<N, Self> +
          Div<N, Self> + Add<V, Self> { // FIXME: + Sub<V, Self>
}

/// Trait of points with components implementing the `Float` trait.
pub trait FloatPnt<N: Float, V: Norm<N>>: AnyPnt<N, V> {
    /// Computes the square distance between two points.
    #[inline]
    fn sqdist(a: &Self, b: &Self) -> N {
        Norm::sqnorm(&(*a - *b))
    }

    /// Computes the distance between two points.
    #[inline]
    fn dist(a: &Self, b: &Self) -> N {
        Norm::norm(&(*a - *b))
    }
}

/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on points.
pub trait AnyPntExt<N, V>: AnyPnt<N, V> + Indexable<uint, N> + Index<uint, N> + IndexMut<uint, N> +
                           Iterable<N> + ScalarAdd<N> + ScalarSub<N> + Bounded + Axpy<N>
{ }

/// Trait grouping uncommon, low-level and borderline (from the mathematical point of view)
/// operations on points.
pub trait FloatPntExt<N: Float, V: Norm<N>> : FloatPnt<N, V> + AnyPntExt<N, V> { }

impl<N, V, P: PntAsVec<V> + Dim + Sub<P, V> + Add<V, P> + Orig + Neg<P> + PartialEq + Mul<N, P> + Div<N, P>>
AnyPnt<N, V> for P { }
impl<N: Float, V: Norm<N>, P: AnyPnt<N, V>> FloatPnt<N, V> for P { }
impl<N, V, P: AnyPnt<N, V> + Indexable<uint, N> + Index<uint, N> + IndexMut<uint, N> + Iterable<N> + ScalarAdd<N> + ScalarSub<N> + Bounded + Axpy<N>>
AnyPntExt<N, V> for P { }
impl<N: Float, V: Norm<N>, P: FloatPnt<N, V> + AnyPntExt<N, V>> FloatPntExt<N, V> for P { }
<|endoftext|>


<commit_before>use std::env;
use std::io::{stderr, Write};
use std::path::{Path};
use std::process::exit;
use std::fs::metadata;
use std::os::unix::fs::MetadataExt;

use libc::getuid;
use unshare::Command;

use options::build_mode::build_mode;
use config::find_config;
use config::read_settings::read_settings;
use argparse::{ArgumentParser, Store, List, Collect, Print, StoreFalse};
use super::path_util::ToRelative;
use self::wrap::Wrapper;

mod list;
mod user;
mod network;
mod supervisor;
mod underscore;
mod build;
mod wrap;
mod pack;

pub fn run() -> i32 {
    let mut err = stderr();
    let mut cname = "".to_string();
    let mut args = vec!();
    let mut set_env = Vec::<String>::new();
    let mut propagate_env = Vec::<String>::new();
    let mut bmode = Default::default();
    let mut owner_check = true;
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("
            Runs a command in container, optionally builds container if that
            does not exists or outdated.

            Run `vagga` without arguments to see the list of commands.
            ");
        ap.add_option(&["-V", "--version"],
            Print(env!("VAGGA_VERSION").to_string()),
            "Show vagga version and exit");
        ap.refer(&mut set_env)
          .add_option(&["-E", "--env", "--environ"], Collect,
                "Set environment variable for running command")
          .metavar("NAME=VALUE");
        ap.refer(&mut propagate_env)
          .add_option(&["-e", "--use-env"], Collect,
                "Propagate variable VAR into command environment")
          .metavar("VAR");
        ap.refer(&mut owner_check)
          .add_option(&["--ignore-owner-check"], StoreFalse,
                "Ignore checking owner of the project directory");
        build_mode(&mut ap, &mut bmode);
        ap.refer(&mut cname)
          .add_argument("command", Store,
                "A vagga command to run");
        ap.refer(&mut args)
          .add_argument("args", List,
                "Arguments for the command");
        ap.stop_on_first_argument(true);
        ap.silence_double_dash(false);
        match ap.parse_args() {
            Ok(()) => {}
            Err(0) => return 0,
            Err(_) => return 122,
        }
    }

    let workdir = env::current_dir().unwrap();

    let (config, cfg_dir) = match find_config(&workdir) {
        Ok(tup) => tup,
        Err(e) => {
            writeln!(&mut err, "{}", e).ok();
            return 126;
        }
    };

    if &cname[..] == "_network" {
        args.insert(0, "vagga _network".to_string());
        return ::network::run(args);
    }

    if owner_check {
        let uid = unsafe { getuid() };
        match metadata(&cfg_dir) {
            Ok(ref stat) if stat.uid() == uid  => {}
            Ok(_) => {
                if uid == 0 {
                    writeln!(&mut err, "You should not run vagga as root \
                        (see http://bit.ly/err_root)").ok();
                    return 122;
                } else {
                    warn!("You are running vagga as a user \
                        different from the owner of project directory. \
                        You may not have needed permissions \
                        (see http://bit.ly/err_root)");
                }
            }
            Err(e) => {
                writeln!(&mut err, "Can't stat {:?}: {}", cfg_dir, e).ok();
                return 126;
            }
        }
    }

    let (_ext_settings, int_settings) = match read_settings(&cfg_dir)
    {
        Ok(tup) => tup,
        Err(e) => {
            writeln!(&mut err, "{}", e).ok();
            return 126;
        }
    };
    let int_workdir = workdir.rel_to(&cfg_dir)
                             .unwrap_or(&Path::new("."));

    for k in propagate_env.into_iter() {
        if k.chars().find(|&c| c == '=').is_some() {
            writeln!(&mut err, "Environment variable name \
                (for option `-e`/`--use-env`) \
                can't contain equals `=` character. \
                To set key-value pair use `-E`/`--environ` option").ok();
            return 126;
        } else {
            env::set_var(&("VAGGAENV_".to_string() + &k[..]),
                env::var_os(&k).unwrap_or(From::from("")));
        }
    }
    for pair in set_env.into_iter() {
        let mut pairiter = pair[..].splitn(2, '=');
        let key = "VAGGAENV_".to_string() + pairiter.next().unwrap();
        if let Some(value) = pairiter.next() {
            env::set_var(&key, value.to_string());
        } else {
            env::remove_var(&key);
        }
    }

    let result:Result<i32, String> = match &cname[..] {
        "" => {
            writeln!(&mut err, "Available commands:").ok();
            for (k, cmd) in config.commands.iter() {
                write!(&mut err, "    {}", k).ok();
                match cmd.description() {
                    Some(ref val) => {
                        if k.len() > 19 {
                            write!(&mut err, "\n                        ").ok();
                        } else {
                            for _ in k.len()..19 {
                                err.write_all(b" ").ok();
                            }
                            err.write_all(b" ").ok();
                        }
                        err.write_all(val[..].as_bytes()).ok();
                    }
                    None => {}
                }
                err.write_all(b"\n").ok();
            }
            return 127;
        }
        "_create_netns" => {
            network::create_netns(&config, args)
        }
        "_destroy_netns" => {
            network::destroy_netns(&config, args)
        }
        "_list" => {
            list::print_list(&config, args)
        }
        "_build_shell" | "_clean" | "_version_hash" => {
            let mut cmd: Command = Wrapper::new(None, &int_settings);
            cmd.workdir(&int_workdir);
            cmd.userns();
            cmd.arg(cname).args(&args);
            cmd.run()
        }
        "_build" => {
            build::build_command(&int_settings, args)
        }
        "_run" => {
            underscore::run_command(&int_settings, &int_workdir, args, bmode)
        }
        "_run_in_netns" => {
            underscore::run_in_netns(&int_settings, &int_workdir, cname, args,
                bmode)
        }
        "_pack_image" => {
            pack::pack_command(&int_settings, args)
        }
        _ => {
            user::run_user_command(&config, &int_settings,
                &int_workdir, cname, args, bmode)
        }
    };

    match result {
        Ok(rc) => {
            return rc;
        }
        Err(text) =>  {
            writeln!(&mut err, "{}", text).ok();
            return 121;
        }
    }
}

pub fn main() {
    let val = run();
    exit(val);
}
<commit_msg>Dispatch vagga _network earlier<commit_after>use std::env;
use std::io::{stderr, Write};
use std::path::{Path};
use std::process::exit;
use std::fs::metadata;
use std::os::unix::fs::MetadataExt;

use libc::getuid;
use unshare::Command;

use options::build_mode::build_mode;
use config::find_config;
use config::read_settings::read_settings;
use argparse::{ArgumentParser, Store, List, Collect, Print, StoreFalse};
use super::path_util::ToRelative;
use self::wrap::Wrapper;

mod list;
mod user;
mod network;
mod supervisor;
mod underscore;
mod build;
mod wrap;
mod pack;

pub fn run() -> i32 {
    let mut err = stderr();
    let mut cname = "".to_string();
    let mut args = vec!();
    let mut set_env = Vec::<String>::new();
    let mut propagate_env = Vec::<String>::new();
    let mut bmode = Default::default();
    let mut owner_check = true;
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("
            Runs a command in container, optionally builds container if that
            does not exists or outdated.

            Run `vagga` without arguments to see the list of commands.
            ");
        ap.add_option(&["-V", "--version"],
            Print(env!("VAGGA_VERSION").to_string()),
            "Show vagga version and exit");
        ap.refer(&mut set_env)
          .add_option(&["-E", "--env", "--environ"], Collect,
                "Set environment variable for running command")
          .metavar("NAME=VALUE");
        ap.refer(&mut propagate_env)
          .add_option(&["-e", "--use-env"], Collect,
                "Propagate variable VAR into command environment")
          .metavar("VAR");
        ap.refer(&mut owner_check)
          .add_option(&["--ignore-owner-check"], StoreFalse,
                "Ignore checking owner of the project directory");
        build_mode(&mut ap, &mut bmode);
        ap.refer(&mut cname)
          .add_argument("command", Store,
                "A vagga command to run");
        ap.refer(&mut args)
          .add_argument("args", List,
                "Arguments for the command");
        ap.stop_on_first_argument(true);
        ap.silence_double_dash(false);
        match ap.parse_args() {
            Ok(()) => {}
            Err(0) => return 0,
            Err(_) => return 122,
        }
    }

    if &cname[..] == "_network" {
        args.insert(0, "vagga _network".to_string());
        return ::network::run(args);
    }

    let workdir = env::current_dir().unwrap();

    let (config, cfg_dir) = match find_config(&workdir) {
        Ok(tup) => tup,
        Err(e) => {
            writeln!(&mut err, "{}", e).ok();
            return 126;
        }
    };

    if owner_check {
        let uid = unsafe { getuid() };
        match metadata(&cfg_dir) {
            Ok(ref stat) if stat.uid() == uid  => {}
            Ok(_) => {
                if uid == 0 {
                    writeln!(&mut err, "You should not run vagga as root \
                        (see http://bit.ly/err_root)").ok();
                    return 122;
                } else {
                    warn!("You are running vagga as a user \
                        different from the owner of project directory. \
                        You may not have needed permissions \
                        (see http://bit.ly/err_root)");
                }
            }
            Err(e) => {
                writeln!(&mut err, "Can't stat {:?}: {}", cfg_dir, e).ok();
                return 126;
            }
        }
    }

    let (_ext_settings, int_settings) = match read_settings(&cfg_dir)
    {
        Ok(tup) => tup,
        Err(e) => {
            writeln!(&mut err, "{}", e).ok();
            return 126;
        }
    };
    let int_workdir = workdir.rel_to(&cfg_dir)
                             .unwrap_or(&Path::new("."));

    for k in propagate_env.into_iter() {
        if k.chars().find(|&c| c == '=').is_some() {
            writeln!(&mut err, "Environment variable name \
                (for option `-e`/`--use-env`) \
                can't contain equals `=` character. \
                To set key-value pair use `-E`/`--environ` option").ok();
            return 126;
        } else {
            env::set_var(&("VAGGAENV_".to_string() + &k[..]),
                env::var_os(&k).unwrap_or(From::from("")));
        }
    }
    for pair in set_env.into_iter() {
        let mut pairiter = pair[..].splitn(2, '=');
        let key = "VAGGAENV_".to_string() + pairiter.next().unwrap();
        if let Some(value) = pairiter.next() {
            env::set_var(&key, value.to_string());
        } else {
            env::remove_var(&key);
        }
    }

    let result:Result<i32, String> = match &cname[..] {
        "" => {
            writeln!(&mut err, "Available commands:").ok();
            for (k, cmd) in config.commands.iter() {
                write!(&mut err, "    {}", k).ok();
                match cmd.description() {
                    Some(ref val) => {
                        if k.len() > 19 {
                            write!(&mut err, "\n                        ").ok();
                        } else {
                            for _ in k.len()..19 {
                                err.write_all(b" ").ok();
                            }
                            err.write_all(b" ").ok();
                        }
                        err.write_all(val[..].as_bytes()).ok();
                    }
                    None => {}
                }
                err.write_all(b"\n").ok();
            }
            return 127;
        }
        "_create_netns" => {
            network::create_netns(&config, args)
        }
        "_destroy_netns" => {
            network::destroy_netns(&config, args)
        }
        "_list" => {
            list::print_list(&config, args)
        }
        "_build_shell" | "_clean" | "_version_hash" => {
            let mut cmd: Command = Wrapper::new(None, &int_settings);
            cmd.workdir(&int_workdir);
            cmd.userns();
            cmd.arg(cname).args(&args);
            cmd.run()
        }
        "_build" => {
            build::build_command(&int_settings, args)
        }
        "_run" => {
            underscore::run_command(&int_settings, &int_workdir, args, bmode)
        }
        "_run_in_netns" => {
            underscore::run_in_netns(&int_settings, &int_workdir, cname, args,
                bmode)
        }
        "_pack_image" => {
            pack::pack_command(&int_settings, args)
        }
        _ => {
            user::run_user_command(&config, &int_settings,
                &int_workdir, cname, args, bmode)
        }
    };

    match result {
        Ok(rc) => {
            return rc;
        }
        Err(text) =>  {
            writeln!(&mut err, "{}", text).ok();
            return 121;
        }
    }
}

pub fn main() {
    let val = run();
    exit(val);
}
<|endoftext|>


<commit_before>use std::mem;

use libc::{c_char, c_void, strcmp, uint32_t};

use raw;

use Compositor;
use Display;
use Seat;
use Shell;
use Shm;

pub struct Registry {
    ptr: *mut raw::wl_registry,
    compositor: Option<Compositor>,
    seat: Option<Seat>,
    shell: Option<Shell>,
    shm: Option<Shm>,
}

#[allow(unused_variables)]
extern fn global(
    data: *mut c_void,
    registry: *mut raw::wl_registry,
    name: uint32_t,
    interface: *const c_char,
    version: uint32_t
) {
    unsafe {
        let r: &mut Registry = mem::transmute(data);
        if strcmp(interface, raw::wl_compositor_interface.name) == 0 {
            let ptr = raw::wl_registry_bind(
                registry,
                name,
                & raw::wl_compositor_interface,
                version
            );
            let compositor = Compositor::from_ptr(
                ptr as *mut raw::wl_compositor
            );
            r.compositor = Some(compositor);
        }
        else if strcmp(interface, raw::wl_seat_interface.name) == 0 {
            let ptr = raw::wl_registry_bind(
                registry,
                name,
                & raw::wl_seat_interface,
                version
            );
            let seat = Seat::from_ptr(
                ptr as *mut raw::wl_seat
            );
            r.seat = Some(seat);
        }
        else if strcmp(interface, raw::wl_shell_interface.name) == 0 {
            let ptr = raw::wl_registry_bind(
                registry,
                name,
                & raw::wl_shell_interface,
                version
            );
            let shell = Shell::from_ptr(
                ptr as *mut raw::wl_shell
            );
            r.shell = Some(shell);
        }
        else if strcmp(interface, raw::wl_shm_interface.name) == 0 {
            let ptr = raw::wl_registry_bind(
                registry,
                name,
                & raw::wl_shm_interface,
                version
            );
            let shm = Shm::from_ptr(
                ptr as *mut raw::wl_shm
            );
            r.shm = Some(shm);
        }
    }
}

#[allow(unused_variables)]
extern fn global_remove(
    data: *mut c_void,
    registry: *mut raw::wl_registry,
    name: uint32_t
) {
    panic!("unhandled registry global_remove");
}

static REGISTRY_LISTENER: raw::wl_registry_listener =
    raw::wl_registry_listener {
        global: global,
        global_remove: global_remove
    };

impl Registry {
    pub fn new(display: &mut Display) -> Registry {
        unsafe {
            let ptr = raw::wl_display_get_registry(display.to_ptr());
            let mut r = Registry {
                ptr: ptr,
                compositor: None,
                seat: None,
                shell: None,
                shm: None,
            };
            raw::wl_registry_add_listener(
                ptr,
                &REGISTRY_LISTENER,
                mem::transmute(&mut r)
            );
            display.roundtrip();
            r
        }
    }
    pub fn get_compositor(&mut self) -> &mut Compositor {
        match self.compositor {
            Some(ref mut c) => c,
            None => panic!("compositor not set"),
        }
    }
    pub fn get_seat(&mut self) -> &mut Seat {
        match self.seat {
            Some(ref mut s) => s,
            None => panic!("seat not set"),
        }
    }
    pub fn get_shell(&mut self) -> &mut Shell {
        match self.shell {
            Some(ref mut s) => s,
            None => panic!("shell not set"),
        }
    }
    pub fn get_shm(&mut self) -> &mut Shm {
        match self.shm {
            Some(ref mut s) => s,
            None => panic!("shell not set"),
        }
    }
}

impl Drop for Registry {
    fn drop(&mut self) {
        unsafe {
            raw::wl_registry_destroy(self.ptr);
        }
    }
}
<commit_msg>Readd debug message<commit_after>use std::c_str;
use std::mem;

use libc::{c_char, c_void, strcmp, uint32_t};

use raw;

use Compositor;
use Display;
use Seat;
use Shell;
use Shm;

pub struct Registry {
    ptr: *mut raw::wl_registry,
    compositor: Option<Compositor>,
    seat: Option<Seat>,
    shell: Option<Shell>,
    shm: Option<Shm>,
}

#[allow(unused_variables)]
extern fn global(
    data: *mut c_void,
    registry: *mut raw::wl_registry,
    name: uint32_t,
    interface: *const c_char,
    version: uint32_t
) {
    unsafe {
        let r: &mut Registry = mem::transmute(data);
        if strcmp(interface, raw::wl_compositor_interface.name) == 0 {
            let ptr = raw::wl_registry_bind(
                registry,
                name,
                & raw::wl_compositor_interface,
                version
            );
            let compositor = Compositor::from_ptr(
                ptr as *mut raw::wl_compositor
            );
            r.compositor = Some(compositor);
        }
        else if strcmp(interface, raw::wl_seat_interface.name) == 0 {
            let ptr = raw::wl_registry_bind(
                registry,
                name,
                & raw::wl_seat_interface,
                version
            );
            let seat = Seat::from_ptr(
                ptr as *mut raw::wl_seat
            );
            r.seat = Some(seat);
        }
        else if strcmp(interface, raw::wl_shell_interface.name) == 0 {
            let ptr = raw::wl_registry_bind(
                registry,
                name,
                & raw::wl_shell_interface,
                version
            );
            let shell = Shell::from_ptr(
                ptr as *mut raw::wl_shell
            );
            r.shell = Some(shell);
        }
        else if strcmp(interface, raw::wl_shm_interface.name) == 0 {
            let ptr = raw::wl_registry_bind(
                registry,
                name,
                & raw::wl_shm_interface,
                version
            );
            let shm = Shm::from_ptr(
                ptr as *mut raw::wl_shm
            );
            r.shm = Some(shm);
        }
        let interface_c_str = c_str::CString::new(interface, false);
        let interface_str = interface_c_str.as_str().unwrap();
        println!("wl_registry.global name={} interface={} version={}",
                 name, interface_str, version);
    }
}

#[allow(unused_variables)]
extern fn global_remove(
    data: *mut c_void,
    registry: *mut raw::wl_registry,
    name: uint32_t
) {
    println!("wl_registry.global_remove name = {}", name);
    unimplemented!();
}

static REGISTRY_LISTENER: raw::wl_registry_listener =
    raw::wl_registry_listener {
        global: global,
        global_remove: global_remove
    };

impl Registry {
    pub fn new(display: &mut Display) -> Registry {
        unsafe {
            let ptr = raw::wl_display_get_registry(display.to_ptr());
            let mut r = Registry {
                ptr: ptr,
                compositor: None,
                seat: None,
                shell: None,
                shm: None,
            };
            raw::wl_registry_add_listener(
                ptr,
                &REGISTRY_LISTENER,
                mem::transmute(&mut r)
            );
            display.roundtrip();
            r
        }
    }
    pub fn get_compositor(&mut self) -> &mut Compositor {
        match self.compositor {
            Some(ref mut c) => c,
            None => panic!("compositor not set"),
        }
    }
    pub fn get_seat(&mut self) -> &mut Seat {
        match self.seat {
            Some(ref mut s) => s,
            None => panic!("seat not set"),
        }
    }
    pub fn get_shell(&mut self) -> &mut Shell {
        match self.shell {
            Some(ref mut s) => s,
            None => panic!("shell not set"),
        }
    }
    pub fn get_shm(&mut self) -> &mut Shm {
        match self.shm {
            Some(ref mut s) => s,
            None => panic!("shell not set"),
        }
    }
}

impl Drop for Registry {
    fn drop(&mut self) {
        unsafe {
            raw::wl_registry_destroy(self.ptr);
        }
    }
}
<|endoftext|>


<commit_before>use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::net::get_host_addresses;
use std::io::{Buffer, Reader, Writer, IoResult, BufferedStream, standard_error};
use std::io;
use std::collections::TreeMap;
use std::mem;
use url::Url;

#[cfg(test)]
use test::Bencher;
#[cfg(test)]
use serialize::json::ToJson;

use nonce::Nonce;
use message::{WSMessage, WSHeader, WS_FIN, WS_OPCTRL, WS_OPCODE, WS_OPCONT, WS_MASK, WS_LEN, WS_LEN16, WS_LEN64};
use stream::NetworkStream;

pub struct WebSocket<S = NetworkStream> {
    stream: Option<BufferedStream<S>>,
    connected: bool,
    pub remote_addr: Option<SocketAddr>,
    pub url: Url,
    use_ssl: bool,
}

impl WebSocket {
    pub fn new(url: Url) -> IoResult<WebSocket> {
        let addr = match try!(url.domain()
            .map(|h| get_host_addresses(h)
                 .map(|v| v.move_iter().find(|&a| {
                     match a {
                         Ipv4Addr(..) => true,
                         _ => false
                     }
                 })))
            .unwrap_or(Err(standard_error(io::InvalidInput)))) {
                Some(a) => a,
                None => return Err(standard_error(io::FileNotFound))
            };

        let use_ssl = url.scheme.as_slice() == "wss";

        let port = match url.port() {
            Some(p) => p,
            None if use_ssl => 443,
            _ => 80
        };

        Ok(WebSocket {
            stream: None,
            connected: false,
            remote_addr: Some(SocketAddr{ ip: addr, port: port }),
            url: url,
            use_ssl: use_ssl,
        })
    }

    #[allow(unused_variable)]
    fn try_connect(&mut self) -> IoResult<()> {
        self.stream = Some(BufferedStream::new(try!(self.remote_addr.map(|ref a| NetworkStream::connect(format!("{}", a.ip).as_slice(), a.port, self.use_ssl))
                               .unwrap_or_else(|| Err(standard_error(io::InvalidInput))))));
        Ok(())
    }

    fn write_request(&mut self, nonce: &str) -> IoResult<()> {
        let s = match self.stream { Some(ref mut s) => s, None => return Err(standard_error(io::NotConnected)) };

        try!(s.write(format!("GET {} HTTP/1.1\r\n", self.url.serialize_path().unwrap_or("/".to_string())).as_bytes()));
        try!(s.write(format!("Host: {}\r\n", self.url.host().unwrap()).as_bytes()));
        try!(s.write(format!("Origin: {}\r\n", self.url.serialize_no_fragment()).as_bytes()));
        try!(s.write(format!("Sec-WebSocket-Key: {}\r\n", nonce).as_bytes()));

        try!(s.write(b"Upgrade: websocket\r\n"));
        try!(s.write(b"Connection: Upgrade\r\n"));
        try!(s.write(b"Sec-WebSocket-Protocol: char, superchat\r\n"));
        try!(s.write(b"Sec-WebSocket-Version: 13\r\n"));
        try!(s.write(b"\r\n"));

        s.flush()
    }

    fn read_response(&mut self, nonce: &str) -> IoResult<()> {
        let spaces: &[_] = &[' ', '\t', '\r', '\n'];
        let s = match self.stream { Some(ref mut s) => s, None => return Err(standard_error(io::NotConnected)) };
        let status = try!(s.read_line()).as_slice().splitn(2, ' ').nth(1).and_then(|s| from_str::<uint>(s));

        match status {
            Some(101) => (),
            _ => return Err(standard_error(io::InvalidInput))
        }

        let headers = s.lines().map(|r| r.unwrap_or("\r\n".to_string())) .take_while(|l| l.as_slice() != "\r\n")
            .map(|s| s.as_slice().splitn(1, ':').map(|s| s.trim_chars(spaces).to_string()).collect::<Vec<String>>())
            .map(|p| (p[0].to_string(), p[1].to_string()))
            .collect::<TreeMap<String, String>>();

        try!(s.flush());

        let response = headers.find(&"Sec-WebSocket-Accept".to_string());
        match response {
            Some(r) if nonce == r.as_slice() => (),
            _ => return Err(standard_error(io::InvalidInput))
        }

        Ok(())
    }

    pub fn connect(&mut self) -> IoResult<()> {
        let mut nonce = Nonce::new();

        try!(self.try_connect());
        try!(self.write_request(nonce.as_slice()));

        nonce = nonce.encode();
        try!(self.read_response(nonce.as_slice()));

        self.connected = true;

        Ok(())
    }

    fn read_header(&mut self) -> IoResult<WSHeader> {
        // XXX: this is a bug, WSHeader should accept u16
        Ok(WSHeader::from_bits_truncate(try!(self.read_be_u16())))
    }

    fn read_length(&mut self, header: &WSHeader) -> IoResult<uint> {
        let wslen = header & WS_LEN;
        if wslen == WS_LEN16 { self.read_be_u16().map(|v| v as uint) }
        else if wslen == WS_LEN64 { self.read_be_u64().map(|v| v as uint) }
        else { Ok(wslen.bits() as uint) }
    }

    pub fn read_message(&mut self) -> IoResult<WSMessage> {
        let header = try!(self.read_header());
        let len = try!(self.read_length(&header));

        let data = if header.contains(WS_MASK) {
            WebSocket::unmask_data(try!(self.read_exact(len)), try!(self.read_be_u32()))
        } else {
            try!(self.read_exact(len))
        };

        Ok(WSMessage { header: header, data: data })
    }

    fn unmask_data(data: Vec<u8>, mask: u32) -> Vec<u8> {
        data.iter().enumerate().map(|(i, b)| b ^ (mask >> ((i % 4) << 3) & 0xff) as u8).collect::<Vec<u8>>()
    }

    // TODO: send_message(&mut self, &WSMessage) -> IoResult<()>

    pub fn iter(&mut self) -> WSMessages {
        WSMessages { sock: self }
    }
}

impl Reader for WebSocket {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        match self.stream {
            Some(ref mut s) => s.read(buf),
            None => Err(standard_error(io::NotConnected))
        }
    }
}

impl Writer for WebSocket {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        match self.stream {
            Some(ref mut s) => s.write(buf),
            None => Err(standard_error(io::NotConnected))
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match self.stream {
            Some(ref mut s) => s.flush(),
            None => Err(standard_error(io::NotConnected))
        }
    }
}

impl Buffer for WebSocket {
    fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
        match self.stream {
            Some(ref mut s) => s.fill_buf(),
            None => Err(standard_error(io::NotConnected))
        }
    }

    fn consume(&mut self, amt: uint) {
        match self.stream {
            Some(ref mut s) => s.consume(amt),
            None => ()
        }
    }
}

pub struct WSMessages<'a> {
    sock: &'a mut WebSocket
}

pub struct WSDefragMessages<'a> {
    underlying: &'a mut WSMessages<'a>,
    buffer: WSMessage
}

impl<'a> WSMessages<'a> {
    pub fn defrag(&'a mut self) -> WSDefragMessages<'a> {
        WSDefragMessages{ underlying: self, buffer: WSMessage{ header: WSHeader::empty(), data: Vec::new() } }
    }
}

impl<'a> Iterator<WSMessage> for WSMessages<'a> {
    fn next(&mut self) -> Option<WSMessage> {
        self.sock.read_message().ok()
    }
}

impl<'a> WSDefragMessages<'a> {
    fn popbuf(&mut self) -> Option<WSMessage> {
        if self.buffer.data.is_empty() {
            None
        } else {
            let buf = WSMessage{ header: WSHeader::empty(), data: Vec::new() };
            mem::swap(&mut self.buffer, &mut buf);
            Some(buf)
        }
    }

    fn swapbuf<'a>(&mut self, msg: &'a mut WSMessage) -> &'a mut WSMessage {
        mem::swap(&mut self.buffer, msg);
        return msg;
    }
}

impl<'a> Iterator<WSMessage> for WSDefragMessages<'a> {
    fn next(&mut self) -> Option<WSMessage> {
        loop {
            match self.underlying.next() {
                None => return self.popbuf(),
                Some(msg) => if msg.header.contains(WS_FIN) {
                    if msg.header & WS_OPCODE == WS_OPCONT {
                        self.buffer.data.append(msg.data.as_slice());
                        return self.popbuf();
                    } else {
                        return Some(msg);
                    }

                } else {
                    if msg.header & WS_OPCODE == WS_OPCONT {
                        self.buffer.data.append(msg.data.as_slice());
                    } else {
                        self.swapbuf(&mut msg);
                        return Some(msg);
                    }
                }
            }
        }
    }
}

#[bench]
#[allow(dead_code)]
fn test_connect(b: &mut Bencher) {
    let url = Url::parse("wss://stream.pushbullet.com/websocket/").unwrap();
    let mut ws = WebSocket::new(url).unwrap();

    match ws.connect() {
        Err(e) => fail!("error: {}", e),
        _ => ()
    }
    let msg = ws.read_message().unwrap();
    println!("received: {} {} {}", msg, msg.to_string(), msg.to_json());
    for msg in ws.iter() {
        println!("{}", msg.to_string());
    }
}
<commit_msg>remove experimental code<commit_after>use std::io::net::ip::{SocketAddr, Ipv4Addr};
use std::io::net::get_host_addresses;
use std::io::{Buffer, Reader, Writer, IoResult, BufferedStream, standard_error};
use std::io;
use std::collections::TreeMap;
use std::mem;
use url::Url;

#[cfg(test)]
use test::Bencher;
#[cfg(test)]
use serialize::json::ToJson;

use nonce::Nonce;
use message::{WSMessage, WSHeader, WS_FIN, WS_OPCTRL, WS_OPCODE, WS_OPCONT, WS_MASK, WS_LEN, WS_LEN16, WS_LEN64};
use stream::NetworkStream;

pub struct WebSocket<S = NetworkStream> {
    stream: Option<BufferedStream<S>>,
    connected: bool,
    pub remote_addr: Option<SocketAddr>,
    pub url: Url,
    use_ssl: bool,
}

impl WebSocket {
    pub fn new(url: Url) -> IoResult<WebSocket> {
        let addr = match try!(url.domain()
            .map(|h| get_host_addresses(h)
                 .map(|v| v.move_iter().find(|&a| {
                     match a {
                         Ipv4Addr(..) => true,
                         _ => false
                     }
                 })))
            .unwrap_or(Err(standard_error(io::InvalidInput)))) {
                Some(a) => a,
                None => return Err(standard_error(io::FileNotFound))
            };

        let use_ssl = url.scheme.as_slice() == "wss";

        let port = match url.port() {
            Some(p) => p,
            None if use_ssl => 443,
            _ => 80
        };

        Ok(WebSocket {
            stream: None,
            connected: false,
            remote_addr: Some(SocketAddr{ ip: addr, port: port }),
            url: url,
            use_ssl: use_ssl,
        })
    }

    #[allow(unused_variable)]
    fn try_connect(&mut self) -> IoResult<()> {
        self.stream = Some(BufferedStream::new(try!(self.remote_addr.map(|ref a| NetworkStream::connect(format!("{}", a.ip).as_slice(), a.port, self.use_ssl))
                               .unwrap_or_else(|| Err(standard_error(io::InvalidInput))))));
        Ok(())
    }

    fn write_request(&mut self, nonce: &str) -> IoResult<()> {
        let s = match self.stream { Some(ref mut s) => s, None => return Err(standard_error(io::NotConnected)) };

        try!(s.write(format!("GET {} HTTP/1.1\r\n", self.url.serialize_path().unwrap_or("/".to_string())).as_bytes()));
        try!(s.write(format!("Host: {}\r\n", self.url.host().unwrap()).as_bytes()));
        try!(s.write(format!("Origin: {}\r\n", self.url.serialize_no_fragment()).as_bytes()));
        try!(s.write(format!("Sec-WebSocket-Key: {}\r\n", nonce).as_bytes()));

        try!(s.write(b"Upgrade: websocket\r\n"));
        try!(s.write(b"Connection: Upgrade\r\n"));
        try!(s.write(b"Sec-WebSocket-Protocol: char, superchat\r\n"));
        try!(s.write(b"Sec-WebSocket-Version: 13\r\n"));
        try!(s.write(b"\r\n"));

        s.flush()
    }

    fn read_response(&mut self, nonce: &str) -> IoResult<()> {
        let spaces: &[_] = &[' ', '\t', '\r', '\n'];
        let s = match self.stream { Some(ref mut s) => s, None => return Err(standard_error(io::NotConnected)) };
        let status = try!(s.read_line()).as_slice().splitn(2, ' ').nth(1).and_then(|s| from_str::<uint>(s));

        match status {
            Some(101) => (),
            _ => return Err(standard_error(io::InvalidInput))
        }

        let headers = s.lines().map(|r| r.unwrap_or("\r\n".to_string())) .take_while(|l| l.as_slice() != "\r\n")
            .map(|s| s.as_slice().splitn(1, ':').map(|s| s.trim_chars(spaces).to_string()).collect::<Vec<String>>())
            .map(|p| (p[0].to_string(), p[1].to_string()))
            .collect::<TreeMap<String, String>>();

        try!(s.flush());

        let response = headers.find(&"Sec-WebSocket-Accept".to_string());
        match response {
            Some(r) if nonce == r.as_slice() => (),
            _ => return Err(standard_error(io::InvalidInput))
        }

        Ok(())
    }

    pub fn connect(&mut self) -> IoResult<()> {
        let mut nonce = Nonce::new();

        try!(self.try_connect());
        try!(self.write_request(nonce.as_slice()));

        nonce = nonce.encode();
        try!(self.read_response(nonce.as_slice()));

        self.connected = true;

        Ok(())
    }

    fn read_header(&mut self) -> IoResult<WSHeader> {
        // XXX: this is a bug, WSHeader should accept u16
        Ok(WSHeader::from_bits_truncate(try!(self.read_be_u16())))
    }

    fn read_length(&mut self, header: &WSHeader) -> IoResult<uint> {
        let wslen = header & WS_LEN;
        if wslen == WS_LEN16 { self.read_be_u16().map(|v| v as uint) }
        else if wslen == WS_LEN64 { self.read_be_u64().map(|v| v as uint) }
        else { Ok(wslen.bits() as uint) }
    }

    pub fn read_message(&mut self) -> IoResult<WSMessage> {
        let header = try!(self.read_header());
        let len = try!(self.read_length(&header));

        let data = if header.contains(WS_MASK) {
            WebSocket::unmask_data(try!(self.read_exact(len)), try!(self.read_be_u32()))
        } else {
            try!(self.read_exact(len))
        };

        Ok(WSMessage { header: header, data: data })
    }

    fn unmask_data(data: Vec<u8>, mask: u32) -> Vec<u8> {
        data.iter().enumerate().map(|(i, b)| b ^ (mask >> ((i % 4) << 3) & 0xff) as u8).collect::<Vec<u8>>()
    }

    // TODO: send_message(&mut self, &WSMessage) -> IoResult<()>

    pub fn iter(&mut self) -> WSMessages {
        WSMessages { sock: self }
    }
}

impl Reader for WebSocket {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        match self.stream {
            Some(ref mut s) => s.read(buf),
            None => Err(standard_error(io::NotConnected))
        }
    }
}

impl Writer for WebSocket {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        match self.stream {
            Some(ref mut s) => s.write(buf),
            None => Err(standard_error(io::NotConnected))
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match self.stream {
            Some(ref mut s) => s.flush(),
            None => Err(standard_error(io::NotConnected))
        }
    }
}

impl Buffer for WebSocket {
    fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
        match self.stream {
            Some(ref mut s) => s.fill_buf(),
            None => Err(standard_error(io::NotConnected))
        }
    }

    fn consume(&mut self, amt: uint) {
        match self.stream {
            Some(ref mut s) => s.consume(amt),
            None => ()
        }
    }
}

pub struct WSMessages<'a> {
    sock: &'a mut WebSocket
}

impl<'a> Iterator<WSMessage> for WSMessages<'a> {
    fn next(&mut self) -> Option<WSMessage> {
        self.sock.read_message().ok()
    }
}

#[bench]
#[allow(dead_code)]
fn test_connect(b: &mut Bencher) {
    let url = Url::parse("wss://stream.pushbullet.com/websocket/").unwrap();
    let mut ws = WebSocket::new(url).unwrap();

    match ws.connect() {
        Err(e) => fail!("error: {}", e),
        _ => ()
    }
    let msg = ws.read_message().unwrap();
    println!("received: {} {} {}", msg, msg.to_string(), msg.to_json());
    for msg in ws.iter() {
        println!("{}", msg.to_string());
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 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.

#![deny(warnings)]

extern crate build_helper;
extern crate cc;

use build_helper::native_lib_boilerplate;
use std::env;
use std::fs::File;

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    if cfg!(feature = "backtrace") &&
        !target.contains("cloudabi") &&
        !target.contains("emscripten") &&
        !target.contains("fuchsia") &&
        !target.contains("msvc") &&
        !target.contains("wasm32")
    {
        let _ = build_libbacktrace(&target);
    }

    if target.contains("linux") {
        if target.contains("android") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=log");
            println!("cargo:rustc-link-lib=gcc");
        } else if !target.contains("musl") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=rt");
            println!("cargo:rustc-link-lib=pthread");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=execinfo");
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("dragonfly") || target.contains("bitrig") ||
              target.contains("netbsd") || target.contains("openbsd") {
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=socket");
        println!("cargo:rustc-link-lib=posix4");
        println!("cargo:rustc-link-lib=pthread");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-darwin") {
        println!("cargo:rustc-link-lib=System");

        // res_init and friends require -lresolv on macOS/iOS.
        // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-ios") {
        println!("cargo:rustc-link-lib=System");
        println!("cargo:rustc-link-lib=objc");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=Foundation");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("windows") {
        println!("cargo:rustc-link-lib=advapi32");
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=userenv");
        println!("cargo:rustc-link-lib=shell32");
    } else if target.contains("fuchsia") {
        // use system-provided libbacktrace
        if cfg!(feature = "backtrace") {
            println!("cargo:rustc-link-lib=backtrace");
        }
        println!("cargo:rustc-link-lib=zircon");
        println!("cargo:rustc-link-lib=fdio");
    } else if target.contains("cloudabi") {
        if cfg!(feature = "backtrace") {
            println!("cargo:rustc-link-lib=unwind");
        }
        println!("cargo:rustc-link-lib=c");
        println!("cargo:rustc-link-lib=compiler_rt");
    }
}

fn build_libbacktrace(target: &str) -> Result<(), ()> {
    let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", "")?;

    let mut build = cc::Build::new();
    build
        .flag("-fvisibility=hidden")
        .include("../libbacktrace")
        .include(&native.out_dir)
        .out_dir(&native.out_dir)
        .warnings(false)
        .file("../libbacktrace/alloc.c")
        .file("../libbacktrace/backtrace.c")
        .file("../libbacktrace/dwarf.c")
        .file("../libbacktrace/fileline.c")
        .file("../libbacktrace/posix.c")
        .file("../libbacktrace/read.c")
        .file("../libbacktrace/sort.c")
        .file("../libbacktrace/state.c");

    if target.contains("darwin") {
        build.file("../libbacktrace/macho.c");
    } else if target.contains("windows") {
        build.file("../libbacktrace/pecoff.c");
    } else {
        build.file("../libbacktrace/elf.c");

        if target.contains("64") {
            build.define("BACKTRACE_ELF_SIZE", "64");
        } else {
            build.define("BACKTRACE_ELF_SIZE", "32");
        }
    }

    File::create(native.out_dir.join("backtrace-supported.h")).unwrap();
    build.define("BACKTRACE_SUPPORTED", "1");
    build.define("BACKTRACE_USES_MALLOC", "1");
    build.define("BACKTRACE_SUPPORTS_THREADS", "0");
    build.define("BACKTRACE_SUPPORTS_DATA", "0");

    File::create(native.out_dir.join("config.h")).unwrap();
    if !target.contains("apple-ios") &&
       !target.contains("solaris") &&
       !target.contains("redox") &&
       !target.contains("android") {
        build.define("HAVE_DL_ITERATE_PHDR", "1");
    }
    build.define("_GNU_SOURCE", "1");
    build.define("_LARGE_FILES", "1");

    build.compile("backtrace");
    Ok(())
}
<commit_msg>Use in-tree libbacktrace on Fuchsia<commit_after>// Copyright 2015 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.

#![deny(warnings)]

extern crate build_helper;
extern crate cc;

use build_helper::native_lib_boilerplate;
use std::env;
use std::fs::File;

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    if cfg!(feature = "backtrace") &&
        !target.contains("cloudabi") &&
        !target.contains("emscripten") &&
        !target.contains("msvc") &&
        !target.contains("wasm32")
    {
        let _ = build_libbacktrace(&target);
    }

    if target.contains("linux") {
        if target.contains("android") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=log");
            println!("cargo:rustc-link-lib=gcc");
        } else if !target.contains("musl") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=rt");
            println!("cargo:rustc-link-lib=pthread");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=execinfo");
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("dragonfly") || target.contains("bitrig") ||
              target.contains("netbsd") || target.contains("openbsd") {
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=socket");
        println!("cargo:rustc-link-lib=posix4");
        println!("cargo:rustc-link-lib=pthread");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-darwin") {
        println!("cargo:rustc-link-lib=System");

        // res_init and friends require -lresolv on macOS/iOS.
        // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-ios") {
        println!("cargo:rustc-link-lib=System");
        println!("cargo:rustc-link-lib=objc");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=Foundation");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("windows") {
        println!("cargo:rustc-link-lib=advapi32");
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=userenv");
        println!("cargo:rustc-link-lib=shell32");
    } else if target.contains("fuchsia") {
        println!("cargo:rustc-link-lib=zircon");
        println!("cargo:rustc-link-lib=fdio");
    } else if target.contains("cloudabi") {
        if cfg!(feature = "backtrace") {
            println!("cargo:rustc-link-lib=unwind");
        }
        println!("cargo:rustc-link-lib=c");
        println!("cargo:rustc-link-lib=compiler_rt");
    }
}

fn build_libbacktrace(target: &str) -> Result<(), ()> {
    let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", "")?;

    let mut build = cc::Build::new();
    build
        .flag("-fvisibility=hidden")
        .include("../libbacktrace")
        .include(&native.out_dir)
        .out_dir(&native.out_dir)
        .warnings(false)
        .file("../libbacktrace/alloc.c")
        .file("../libbacktrace/backtrace.c")
        .file("../libbacktrace/dwarf.c")
        .file("../libbacktrace/fileline.c")
        .file("../libbacktrace/posix.c")
        .file("../libbacktrace/read.c")
        .file("../libbacktrace/sort.c")
        .file("../libbacktrace/state.c");

    if target.contains("darwin") {
        build.file("../libbacktrace/macho.c");
    } else if target.contains("windows") {
        build.file("../libbacktrace/pecoff.c");
    } else {
        build.file("../libbacktrace/elf.c");

        if target.contains("64") {
            build.define("BACKTRACE_ELF_SIZE", "64");
        } else {
            build.define("BACKTRACE_ELF_SIZE", "32");
        }
    }

    File::create(native.out_dir.join("backtrace-supported.h")).unwrap();
    build.define("BACKTRACE_SUPPORTED", "1");
    build.define("BACKTRACE_USES_MALLOC", "1");
    build.define("BACKTRACE_SUPPORTS_THREADS", "0");
    build.define("BACKTRACE_SUPPORTS_DATA", "0");

    File::create(native.out_dir.join("config.h")).unwrap();
    if !target.contains("apple-ios") &&
       !target.contains("solaris") &&
       !target.contains("redox") &&
       !target.contains("android") {
        build.define("HAVE_DL_ITERATE_PHDR", "1");
    }
    build.define("_GNU_SOURCE", "1");
    build.define("_LARGE_FILES", "1");

    build.compile("backtrace");
    Ok(())
}
<|endoftext|>


<commit_before>extern crate serenity;

use serenity::client::Context;
use serenity::Client;
use serenity::model::Message;
use std::env;

fn main() {
    // Configure the client with your Discord bot token in the environment.
    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::login_bot(&token);

    client.on_message(|_context, message| {
        println!("Received message: {:?}", message);
    });

    client.on_ready(|_context, ready| {
        println!("{} is connected!", ready.user.name);
    });

    // Commands are equivilant to:
    // "~about"
    // "~ping"
    // "~emoji cat"
    // "~emoji dog"
    // "~some complex group"
    client.with_framework(|f| f
        .configure(|c| c
            .on_mention(true)
            .prefix("~"))
        .on("ping", ping_command)
        .set_check("ping", owner_check) // Ensure only the owner can run this
        .on("emoji cat", cat_command)
        .on("emoji dog", dog_command)
        .on("some complex command", some_complex_command)
        // Commands can be in closure-form as well
        .on("about", |context, _message| drop(context.say("A test bot"))));

    let _ = client.start();
}

fn cat_command(context: Context, _message: Message) {
    let _ = context.say(":cat:");
}

fn dog_command(context: Context, _message: Message) {
    let _ = context.say(":dog:");
}

fn ping_command(_context: Context, message: Message) {
    let _ = message.reply("Pong!");
}

fn owner_check(_context: &Context, message: &Message) -> bool {
    // Replace 7 with your ID
    message.author.id.0 == 7u64
}

fn some_complex_command(context: Context, _message: Message) {
    let _ = context.say("This is a command in a complex group");
}
<commit_msg>Fix typo in example 06<commit_after>extern crate serenity;

use serenity::client::Context;
use serenity::Client;
use serenity::model::Message;
use std::env;

fn main() {
    // Configure the client with your Discord bot token in the environment.
    let token = env::var("DISCORD_TOKEN")
        .expect("Expected a token in the environment");
    let mut client = Client::login_bot(&token);

    client.on_message(|_context, message| {
        println!("Received message: {:?}", message);
    });

    client.on_ready(|_context, ready| {
        println!("{} is connected!", ready.user.name);
    });

    // Commands are equivilant to:
    // "~about"
    // "~ping"
    // "~emoji cat"
    // "~emoji dog"
    // "~some complex command"
    client.with_framework(|f| f
        .configure(|c| c
            .on_mention(true)
            .prefix("~"))
        .on("ping", ping_command)
        .set_check("ping", owner_check) // Ensure only the owner can run this
        .on("emoji cat", cat_command)
        .on("emoji dog", dog_command)
        .on("some complex command", some_complex_command)
        // Commands can be in closure-form as well
        .on("about", |context, _message| drop(context.say("A test bot"))));

    let _ = client.start();
}

fn cat_command(context: Context, _message: Message) {
    let _ = context.say(":cat:");
}

fn dog_command(context: Context, _message: Message) {
    let _ = context.say(":dog:");
}

fn ping_command(_context: Context, message: Message) {
    let _ = message.reply("Pong!");
}

fn owner_check(_context: &Context, message: &Message) -> bool {
    // Replace 7 with your ID
    message.author.id.0 == 7u64
}

fn some_complex_command(context: Context, _message: Message) {
    let _ = context.say("This is a command in a complex group");
}
<|endoftext|>