<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.

#[doc(primitive = "bool")]
//
/// The boolean type.
///
mod prim_bool { }

#[doc(primitive = "char")]
//
/// A Unicode scalar value.
///
/// A `char` represents a
/// *[Unicode scalar
/// value](http://www.unicode.org/glossary/#unicode_scalar_value)*, as it can
/// contain any Unicode code point except high-surrogate and low-surrogate code
/// points.
///
/// As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\]
/// (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
/// however the converse is not always true due to the above range limits
/// and, as such, should be performed via the `from_u32` function.
///
/// *[See also the `std::char` module](char/index.html).*
///
mod prim_char { }

#[doc(primitive = "unit")]
//
/// The `()` type, sometimes called "unit" or "nil".
///
/// The `()` type has exactly one value `()`, and is used when there
/// is no other meaningful value that could be returned. `()` is most
/// commonly seen implicitly: functions without a `-> ...` implicitly
/// have return type `()`, that is, these are equivalent:
///
/// ```rust
/// fn long() -> () {}
///
/// fn short() {}
/// ```
///
/// The semicolon `;` can be used to discard the result of an
/// expression at the end of a block, making the expression (and thus
/// the block) evaluate to `()`. For example,
///
/// ```rust
/// fn returns_i64() -> i64 {
///     1i64
/// }
/// fn returns_unit() {
///     1i64;
/// }
///
/// let is_i64 = {
///     returns_i64()
/// };
/// let is_unit = {
///     returns_i64();
/// };
/// ```
///
mod prim_unit { }

#[doc(primitive = "pointer")]
//
/// Raw, unsafe pointers, `*const T`, and `*mut T`.
///
/// Working with raw pointers in Rust is uncommon,
/// typically limited to a few patterns.
///
/// Use the `null` function to create null pointers, and the `is_null` method
/// of the `*const T` type  to check for null. The `*const T` type also defines
/// the `offset` method, for pointer math.
///
/// # Common ways to create raw pointers
///
/// ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`).
///
/// ```
/// let my_num: i32 = 10;
/// let my_num_ptr: *const i32 = &my_num;
/// let mut my_speed: i32 = 88;
/// let my_speed_ptr: *mut i32 = &mut my_speed;
/// ```
///
/// To get a pointer to a boxed value, dereference the box:
///
/// ```
/// let my_num: Box<i32> = Box::new(10);
/// let my_num_ptr: *const i32 = &*my_num;
/// let mut my_speed: Box<i32> = Box::new(88);
/// let my_speed_ptr: *mut i32 = &mut *my_speed;
/// ```
///
/// This does not take ownership of the original allocation
/// and requires no resource management later,
/// but you must not use the pointer after its lifetime.
///
/// ## 2. Consume a box (`Box<T>`).
///
/// The `into_raw` function consumes a box and returns
/// the raw pointer. It doesn't destroy `T` or deallocate any memory.
///
/// ```
/// let my_speed: Box<i32> = Box::new(88);
/// let my_speed: *mut i32 = Box::into_raw(my_speed);
///
/// // By taking ownership of the original `Box<T>` though
/// // we are obligated to put it together later to be destroyed.
/// unsafe {
///     drop(Box::from_raw(my_speed));
/// }
/// ```
///
/// Note that here the call to `drop` is for clarity - it indicates
/// that we are done with the given value and it should be destroyed.
///
/// ## 3. Get it from C.
///
/// ```
/// # #![feature(libc)]
/// extern crate libc;
///
/// use std::mem;
///
/// fn main() {
///     unsafe {
///         let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut i32;
///         if my_num.is_null() {
///             panic!("failed to allocate memory");
///         }
///         libc::free(my_num as *mut libc::c_void);
///     }
/// }
/// ```
///
/// Usually you wouldn't literally use `malloc` and `free` from Rust,
/// but C APIs hand out a lot of pointers generally, so are a common source
/// of raw pointers in Rust.
///
/// *[See also the `std::ptr` module](ptr/index.html).*
///
mod prim_pointer { }

#[doc(primitive = "array")]
//
/// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and
/// the non-negative compile time constant size, `N`.
///
/// Arrays values are created either with an explicit expression that lists
/// each element: `[x, y, z]` or a repeat expression: `[x; N]`. The repeat
/// expression requires that the element type is `Copy`.
///
/// The type `[T; N]` is `Copy` if `T: Copy`.
///
/// Arrays of sizes from 0 to 32 (inclusive) implement the following traits
/// if the element type allows it:
///
/// - `Clone`
/// - `Debug`
/// - `IntoIterator` (implemented for `&[T; N]` and `&mut [T; N]`)
/// - `PartialEq`, `PartialOrd`, `Ord`, `Eq`
/// - `Hash`
/// - `AsRef`, `AsMut`
///
/// Arrays dereference to [slices (`[T]`)][slice], so their methods can be called
/// on arrays.
///
/// [slice]: primitive.slice.html
///
/// Rust does not currently support generics over the size of an array type.
///
/// # Examples
///
/// ```
/// let mut array: [i32; 3] = [0; 3];
///
/// array[1] = 1;
/// array[2] = 2;
///
/// assert_eq!([1, 2], &array[1..]);
///
/// // This loop prints: 0 1 2
/// for x in &array {
///     print!("{} ", x);
/// }
///
/// ```
///
mod prim_array { }

#[doc(primitive = "slice")]
//
/// A dynamically-sized view into a contiguous sequence, `[T]`.
///
/// Slices are a view into a block of memory represented as a pointer and a
/// length.
///
/// ```
/// // slicing a Vec
/// let vec = vec![1, 2, 3];
/// let int_slice = &vec[..];
/// // coercing an array to a slice
/// let str_slice: &[&str] = &["one", "two", "three"];
/// ```
///
/// Slices are either mutable or shared. The shared slice type is `&[T]`,
/// while the mutable slice type is `&mut [T]`, where `T` represents the element
/// type. For example, you can mutate the block of memory that a mutable slice
/// points to:
///
/// ```
/// let x = &mut [1, 2, 3];
/// x[1] = 7;
/// assert_eq!(x, &[1, 7, 3]);
/// ```
///
/// *[See also the `std::slice` module](slice/index.html).*
///
mod prim_slice { }

#[doc(primitive = "str")]
//
/// Unicode string slices.
///
/// Rust's `str` type is one of the core primitive types of the language. `&str`
/// is the borrowed string type. This type of string can only be created from
/// other strings, unless it is a `&'static str` (see below). It is not possible
/// to move out of borrowed strings because they are owned elsewhere.
///
/// # Examples
///
/// Here's some code that uses a `&str`:
///
/// ```
/// let s = "Hello, world.";
/// ```
///
/// This `&str` is a `&'static str`, which is the type of string literals.
/// They're `'static` because literals are available for the entire lifetime of
/// the program.
///
/// You can get a non-`'static` `&str` by taking a slice of a `String`:
///
/// ```
/// let some_string = "Hello, world.".to_string();
/// let s = &some_string;
/// ```
///
/// # Representation
///
/// Rust's string type, `str`, is a sequence of Unicode scalar values encoded as
/// a stream of UTF-8 bytes. All [strings](../../reference.html#literals) are
/// guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are
/// not null-terminated and can thus contain null bytes.
///
/// The actual representation of `str`s have direct mappings to slices: `&str`
/// is the same as `&[u8]`.
///
/// *[See also the `std::str` module](str/index.html).*
///
mod prim_str { }

#[doc(primitive = "tuple")]
//
/// A finite heterogeneous sequence, `(T, U, ..)`.
///
/// To access the _N_-th element of a tuple one can use `N` itself
/// as a field of the tuple.
///
/// Indexing starts from zero, so `0` returns first value, `1`
/// returns second value, and so on. In general, a tuple with _S_
/// elements provides aforementioned fields from `0` to `S-1`.
///
/// If every type inside a tuple implements one of the following
/// traits, then a tuple itself also implements it.
///
/// * `Clone`
/// * `PartialEq`
/// * `Eq`
/// * `PartialOrd`
/// * `Ord`
/// * `Debug`
/// * `Default`
/// * `Hash`
///
/// # Examples
///
/// Accessing elements of a tuple at specified indices:
///
/// ```
/// let x = ("colorless",  "green", "ideas", "sleep", "furiously");
/// assert_eq!(x.3, "sleep");
///
/// let v = (3, 3);
/// let u = (1, -5);
/// assert_eq!(v.0 * u.0 + v.1 * u.1, -12);
/// ```
///
/// Using traits implemented for tuples:
///
/// ```
/// let a = (1, 2);
/// let b = (3, 4);
/// assert!(a != b);
///
/// let c = b.clone();
/// assert!(b == c);
///
/// let d : (u32, f32) = Default::default();
/// assert_eq!(d, (0, 0.0f32));
/// ```
///
mod prim_tuple { }

#[doc(primitive = "f32")]
/// The 32-bit floating point type.
///
/// *[See also the `std::f32` module](f32/index.html).*
///
mod prim_f32 { }

#[doc(primitive = "f64")]
//
/// The 64-bit floating point type.
///
/// *[See also the `std::f64` module](f64/index.html).*
///
mod prim_f64 { }

#[doc(primitive = "i8")]
//
/// The 8-bit signed integer type.
///
/// *[See also the `std::i8` module](i8/index.html).*
///
mod prim_i8 { }

#[doc(primitive = "i16")]
//
/// The 16-bit signed integer type.
///
/// *[See also the `std::i16` module](i16/index.html).*
///
mod prim_i16 { }

#[doc(primitive = "i32")]
//
/// The 32-bit signed integer type.
///
/// *[See also the `std::i32` module](i32/index.html).*
///
mod prim_i32 { }

#[doc(primitive = "i64")]
//
/// The 64-bit signed integer type.
///
/// *[See also the `std::i64` module](i64/index.html).*
///
mod prim_i64 { }

#[doc(primitive = "u8")]
//
/// The 8-bit unsigned integer type.
///
/// *[See also the `std::u8` module](u8/index.html).*
///
mod prim_u8 { }

#[doc(primitive = "u16")]
//
/// The 16-bit unsigned integer type.
///
/// *[See also the `std::u16` module](u16/index.html).*
///
mod prim_u16 { }

#[doc(primitive = "u32")]
//
/// The 32-bit unsigned integer type.
///
/// *[See also the `std::u32` module](u32/index.html).*
///
mod prim_u32 { }

#[doc(primitive = "u64")]
//
/// The 64-bit unsigned integer type.
///
/// *[See also the `std::u64` module](u64/index.html).*
///
mod prim_u64 { }

#[doc(primitive = "isize")]
//
/// The pointer-sized signed integer type.
///
/// *[See also the `std::isize` module](isize/index.html).*
///
mod prim_isize { }

#[doc(primitive = "usize")]
//
/// The pointer-sized unsigned integer type.
///
/// *[See also the `std::usize` module](usize/index.html).*
///
mod prim_usize { }

<commit_msg>Update list of array implementations in src/libstd/primitive_docs.rs<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.

#[doc(primitive = "bool")]
//
/// The boolean type.
///
mod prim_bool { }

#[doc(primitive = "char")]
//
/// A Unicode scalar value.
///
/// A `char` represents a
/// *[Unicode scalar
/// value](http://www.unicode.org/glossary/#unicode_scalar_value)*, as it can
/// contain any Unicode code point except high-surrogate and low-surrogate code
/// points.
///
/// As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\]
/// (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
/// however the converse is not always true due to the above range limits
/// and, as such, should be performed via the `from_u32` function.
///
/// *[See also the `std::char` module](char/index.html).*
///
mod prim_char { }

#[doc(primitive = "unit")]
//
/// The `()` type, sometimes called "unit" or "nil".
///
/// The `()` type has exactly one value `()`, and is used when there
/// is no other meaningful value that could be returned. `()` is most
/// commonly seen implicitly: functions without a `-> ...` implicitly
/// have return type `()`, that is, these are equivalent:
///
/// ```rust
/// fn long() -> () {}
///
/// fn short() {}
/// ```
///
/// The semicolon `;` can be used to discard the result of an
/// expression at the end of a block, making the expression (and thus
/// the block) evaluate to `()`. For example,
///
/// ```rust
/// fn returns_i64() -> i64 {
///     1i64
/// }
/// fn returns_unit() {
///     1i64;
/// }
///
/// let is_i64 = {
///     returns_i64()
/// };
/// let is_unit = {
///     returns_i64();
/// };
/// ```
///
mod prim_unit { }

#[doc(primitive = "pointer")]
//
/// Raw, unsafe pointers, `*const T`, and `*mut T`.
///
/// Working with raw pointers in Rust is uncommon,
/// typically limited to a few patterns.
///
/// Use the `null` function to create null pointers, and the `is_null` method
/// of the `*const T` type  to check for null. The `*const T` type also defines
/// the `offset` method, for pointer math.
///
/// # Common ways to create raw pointers
///
/// ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`).
///
/// ```
/// let my_num: i32 = 10;
/// let my_num_ptr: *const i32 = &my_num;
/// let mut my_speed: i32 = 88;
/// let my_speed_ptr: *mut i32 = &mut my_speed;
/// ```
///
/// To get a pointer to a boxed value, dereference the box:
///
/// ```
/// let my_num: Box<i32> = Box::new(10);
/// let my_num_ptr: *const i32 = &*my_num;
/// let mut my_speed: Box<i32> = Box::new(88);
/// let my_speed_ptr: *mut i32 = &mut *my_speed;
/// ```
///
/// This does not take ownership of the original allocation
/// and requires no resource management later,
/// but you must not use the pointer after its lifetime.
///
/// ## 2. Consume a box (`Box<T>`).
///
/// The `into_raw` function consumes a box and returns
/// the raw pointer. It doesn't destroy `T` or deallocate any memory.
///
/// ```
/// let my_speed: Box<i32> = Box::new(88);
/// let my_speed: *mut i32 = Box::into_raw(my_speed);
///
/// // By taking ownership of the original `Box<T>` though
/// // we are obligated to put it together later to be destroyed.
/// unsafe {
///     drop(Box::from_raw(my_speed));
/// }
/// ```
///
/// Note that here the call to `drop` is for clarity - it indicates
/// that we are done with the given value and it should be destroyed.
///
/// ## 3. Get it from C.
///
/// ```
/// # #![feature(libc)]
/// extern crate libc;
///
/// use std::mem;
///
/// fn main() {
///     unsafe {
///         let my_num: *mut i32 = libc::malloc(mem::size_of::<i32>() as libc::size_t) as *mut i32;
///         if my_num.is_null() {
///             panic!("failed to allocate memory");
///         }
///         libc::free(my_num as *mut libc::c_void);
///     }
/// }
/// ```
///
/// Usually you wouldn't literally use `malloc` and `free` from Rust,
/// but C APIs hand out a lot of pointers generally, so are a common source
/// of raw pointers in Rust.
///
/// *[See also the `std::ptr` module](ptr/index.html).*
///
mod prim_pointer { }

#[doc(primitive = "array")]
//
/// A fixed-size array, denoted `[T; N]`, for the element type, `T`, and
/// the non-negative compile time constant size, `N`.
///
/// Arrays values are created either with an explicit expression that lists
/// each element: `[x, y, z]` or a repeat expression: `[x; N]`. The repeat
/// expression requires that the element type is `Copy`.
///
/// The type `[T; N]` is `Copy` if `T: Copy`.
///
/// Arrays of sizes from 0 to 32 (inclusive) implement the following traits
/// if the element type allows it:
///
/// - `Clone` (only if `T: Copy`)
/// - `Debug`
/// - `IntoIterator` (implemented for `&[T; N]` and `&mut [T; N]`)
/// - `PartialEq`, `PartialOrd`, `Ord`, `Eq`
/// - `Hash`
/// - `AsRef`, `AsMut`
/// - `Borrow`, `BorrowMut`
/// - `Default`
///
/// Arrays dereference to [slices (`[T]`)][slice], so their methods can be called
/// on arrays.
///
/// [slice]: primitive.slice.html
///
/// Rust does not currently support generics over the size of an array type.
///
/// # Examples
///
/// ```
/// let mut array: [i32; 3] = [0; 3];
///
/// array[1] = 1;
/// array[2] = 2;
///
/// assert_eq!([1, 2], &array[1..]);
///
/// // This loop prints: 0 1 2
/// for x in &array {
///     print!("{} ", x);
/// }
///
/// ```
///
mod prim_array { }

#[doc(primitive = "slice")]
//
/// A dynamically-sized view into a contiguous sequence, `[T]`.
///
/// Slices are a view into a block of memory represented as a pointer and a
/// length.
///
/// ```
/// // slicing a Vec
/// let vec = vec![1, 2, 3];
/// let int_slice = &vec[..];
/// // coercing an array to a slice
/// let str_slice: &[&str] = &["one", "two", "three"];
/// ```
///
/// Slices are either mutable or shared. The shared slice type is `&[T]`,
/// while the mutable slice type is `&mut [T]`, where `T` represents the element
/// type. For example, you can mutate the block of memory that a mutable slice
/// points to:
///
/// ```
/// let x = &mut [1, 2, 3];
/// x[1] = 7;
/// assert_eq!(x, &[1, 7, 3]);
/// ```
///
/// *[See also the `std::slice` module](slice/index.html).*
///
mod prim_slice { }

#[doc(primitive = "str")]
//
/// Unicode string slices.
///
/// Rust's `str` type is one of the core primitive types of the language. `&str`
/// is the borrowed string type. This type of string can only be created from
/// other strings, unless it is a `&'static str` (see below). It is not possible
/// to move out of borrowed strings because they are owned elsewhere.
///
/// # Examples
///
/// Here's some code that uses a `&str`:
///
/// ```
/// let s = "Hello, world.";
/// ```
///
/// This `&str` is a `&'static str`, which is the type of string literals.
/// They're `'static` because literals are available for the entire lifetime of
/// the program.
///
/// You can get a non-`'static` `&str` by taking a slice of a `String`:
///
/// ```
/// let some_string = "Hello, world.".to_string();
/// let s = &some_string;
/// ```
///
/// # Representation
///
/// Rust's string type, `str`, is a sequence of Unicode scalar values encoded as
/// a stream of UTF-8 bytes. All [strings](../../reference.html#literals) are
/// guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are
/// not null-terminated and can thus contain null bytes.
///
/// The actual representation of `str`s have direct mappings to slices: `&str`
/// is the same as `&[u8]`.
///
/// *[See also the `std::str` module](str/index.html).*
///
mod prim_str { }

#[doc(primitive = "tuple")]
//
/// A finite heterogeneous sequence, `(T, U, ..)`.
///
/// To access the _N_-th element of a tuple one can use `N` itself
/// as a field of the tuple.
///
/// Indexing starts from zero, so `0` returns first value, `1`
/// returns second value, and so on. In general, a tuple with _S_
/// elements provides aforementioned fields from `0` to `S-1`.
///
/// If every type inside a tuple implements one of the following
/// traits, then a tuple itself also implements it.
///
/// * `Clone`
/// * `PartialEq`
/// * `Eq`
/// * `PartialOrd`
/// * `Ord`
/// * `Debug`
/// * `Default`
/// * `Hash`
///
/// # Examples
///
/// Accessing elements of a tuple at specified indices:
///
/// ```
/// let x = ("colorless",  "green", "ideas", "sleep", "furiously");
/// assert_eq!(x.3, "sleep");
///
/// let v = (3, 3);
/// let u = (1, -5);
/// assert_eq!(v.0 * u.0 + v.1 * u.1, -12);
/// ```
///
/// Using traits implemented for tuples:
///
/// ```
/// let a = (1, 2);
/// let b = (3, 4);
/// assert!(a != b);
///
/// let c = b.clone();
/// assert!(b == c);
///
/// let d : (u32, f32) = Default::default();
/// assert_eq!(d, (0, 0.0f32));
/// ```
///
mod prim_tuple { }

#[doc(primitive = "f32")]
/// The 32-bit floating point type.
///
/// *[See also the `std::f32` module](f32/index.html).*
///
mod prim_f32 { }

#[doc(primitive = "f64")]
//
/// The 64-bit floating point type.
///
/// *[See also the `std::f64` module](f64/index.html).*
///
mod prim_f64 { }

#[doc(primitive = "i8")]
//
/// The 8-bit signed integer type.
///
/// *[See also the `std::i8` module](i8/index.html).*
///
mod prim_i8 { }

#[doc(primitive = "i16")]
//
/// The 16-bit signed integer type.
///
/// *[See also the `std::i16` module](i16/index.html).*
///
mod prim_i16 { }

#[doc(primitive = "i32")]
//
/// The 32-bit signed integer type.
///
/// *[See also the `std::i32` module](i32/index.html).*
///
mod prim_i32 { }

#[doc(primitive = "i64")]
//
/// The 64-bit signed integer type.
///
/// *[See also the `std::i64` module](i64/index.html).*
///
mod prim_i64 { }

#[doc(primitive = "u8")]
//
/// The 8-bit unsigned integer type.
///
/// *[See also the `std::u8` module](u8/index.html).*
///
mod prim_u8 { }

#[doc(primitive = "u16")]
//
/// The 16-bit unsigned integer type.
///
/// *[See also the `std::u16` module](u16/index.html).*
///
mod prim_u16 { }

#[doc(primitive = "u32")]
//
/// The 32-bit unsigned integer type.
///
/// *[See also the `std::u32` module](u32/index.html).*
///
mod prim_u32 { }

#[doc(primitive = "u64")]
//
/// The 64-bit unsigned integer type.
///
/// *[See also the `std::u64` module](u64/index.html).*
///
mod prim_u64 { }

#[doc(primitive = "isize")]
//
/// The pointer-sized signed integer type.
///
/// *[See also the `std::isize` module](isize/index.html).*
///
mod prim_isize { }

#[doc(primitive = "usize")]
//
/// The pointer-sized unsigned integer type.
///
/// *[See also the `std::usize` module](usize/index.html).*
///
mod prim_usize { }

<|endoftext|>


<commit_before>#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub use self::x86::*;

mod x86 {
    pub use core::intrinsics::atomic_xchg;

    pub unsafe fn atomic_set_bit<T>(nr: usize, addr: *mut T) {
        asm!("lock bts $1, $0"
             :: "=*m" (addr as *mut u32), "Ir" (nr)
             : "memory"
             : "volatile");
    }

    pub unsafe fn atomic_clear_bit<T>(nr: usize, addr: *mut T) {
        asm!("lock btr $1, $0"
             :: "=*m" (addr as *mut u32), "Ir" (nr)
             : "memory"
             : "volatile");
    }

    pub fn first_bit(data: usize) -> usize {
        unsafe {
            let ret;

            asm!("bsf $0, $1\n\t\
                 jnz 1f\n\t
                 mov $$0, $0\n\t
                 1:\n\t"
                 : "=r" (ret)
                 : "r" (data)
                 :: "volatile");

            ret
        }
    }

    pub fn wmb() {
        unsafe {
            asm!("sfence" ::: "memory" : "volatile");
        }
    }

    #[test]
    pub fn test_set_and_clear() {
        let mut array = [0u32; 4];

        unsafe  {
            atomic_set_bit(1, &mut array[0] as *mut u32);
            atomic_set_bit(2, &mut array[0] as *mut u32);
            atomic_set_bit(3, &mut array[0] as *mut u32);
            atomic_set_bit(32, &mut array[0] as *mut u32);
            atomic_set_bit(33, &mut array[0] as *mut u32);
            atomic_set_bit(34, &mut array[0] as *mut u32);
            atomic_set_bit(127, &mut array[0] as *mut u32);

            assert_eq!(array[0], 0xE);
            assert_eq!(array[1], 0x7);
            assert_eq!(array[2], 0x0);
            assert_eq!(array[3], 0x80000000);

            atomic_clear_bit(1, &mut array[0] as *mut u32);
            atomic_clear_bit(2, &mut array[0] as *mut u32);
            atomic_clear_bit(3, &mut array[0] as *mut u32);
            atomic_clear_bit(32, &mut array[0] as *mut u32);
            atomic_clear_bit(33, &mut array[0] as *mut u32);
            atomic_clear_bit(34, &mut array[0] as *mut u32);
            atomic_clear_bit(127, &mut array[0] as *mut u32);

            assert_eq!(array[0], 0x0);
            assert_eq!(array[1], 0x0);
            assert_eq!(array[2], 0x0);
            assert_eq!(array[3], 0x0);
        }
    }

    #[test]
    pub fn test_first_bit() {
        assert_eq!(first_bit(0x0), 0);
        assert_eq!(first_bit(0x1), 0);
        assert_eq!(first_bit(0x2), 1);
        assert_eq!(first_bit(0x3), 0);
        assert_eq!(first_bit(0x8000), 15);
        assert_eq!(first_bit(0xFF80), 7);
        assert_eq!(first_bit(0x80000000), 31);
    }
}
<commit_msg>libxen: Correct first_bit x86 version<commit_after>#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub use self::x86::*;

mod x86 {
    pub use core::intrinsics::atomic_xchg;

    pub unsafe fn atomic_set_bit<T>(nr: usize, addr: *mut T) {
        asm!("lock bts $1, $0"
             :: "=*m" (addr as *mut u32), "Ir" (nr)
             : "memory"
             : "volatile");
    }

    pub unsafe fn atomic_clear_bit<T>(nr: usize, addr: *mut T) {
        asm!("lock btr $1, $0"
             :: "=*m" (addr as *mut u32), "Ir" (nr)
             : "memory"
             : "volatile");
    }

    pub fn first_bit(data: usize) -> usize {
        unsafe {
            let ret;

            asm!("bsf $1, $0\n\t\
                 jnz 1f\n\t
                 mov $$0, $0\n\t
                 1:\n\t"
                 : "=r" (ret)
                 : "r" (data)
                 :: "volatile");

            ret
        }
    }

    pub fn wmb() {
        unsafe {
            asm!("sfence" ::: "memory" : "volatile");
        }
    }

    #[test]
    pub fn test_set_and_clear() {
        let mut array = [0u32; 4];

        unsafe  {
            atomic_set_bit(1, &mut array[0] as *mut u32);
            atomic_set_bit(2, &mut array[0] as *mut u32);
            atomic_set_bit(3, &mut array[0] as *mut u32);
            atomic_set_bit(32, &mut array[0] as *mut u32);
            atomic_set_bit(33, &mut array[0] as *mut u32);
            atomic_set_bit(34, &mut array[0] as *mut u32);
            atomic_set_bit(127, &mut array[0] as *mut u32);

            assert_eq!(array[0], 0xE);
            assert_eq!(array[1], 0x7);
            assert_eq!(array[2], 0x0);
            assert_eq!(array[3], 0x80000000);

            atomic_clear_bit(1, &mut array[0] as *mut u32);
            atomic_clear_bit(2, &mut array[0] as *mut u32);
            atomic_clear_bit(3, &mut array[0] as *mut u32);
            atomic_clear_bit(32, &mut array[0] as *mut u32);
            atomic_clear_bit(33, &mut array[0] as *mut u32);
            atomic_clear_bit(34, &mut array[0] as *mut u32);
            atomic_clear_bit(127, &mut array[0] as *mut u32);

            assert_eq!(array[0], 0x0);
            assert_eq!(array[1], 0x0);
            assert_eq!(array[2], 0x0);
            assert_eq!(array[3], 0x0);
        }
    }

    #[test]
    pub fn test_first_bit() {
        assert_eq!(first_bit(0x0), 0);
        assert_eq!(first_bit(0x1), 0);
        assert_eq!(first_bit(0x2), 1);
        assert_eq!(first_bit(0x3), 0);
        assert_eq!(first_bit(0x8000), 15);
        assert_eq!(first_bit(0xFF80), 7);
        assert_eq!(first_bit(0x80000000), 31);
    }
}
<|endoftext|>


<commit_before>use std::thread::sleep_ms;
use std::io::{Read, Write, Result, BufRead, BufReader, BufWriter};
use std::fs::File;

use std::net::{TcpListener, TcpStream};
use std::mem::size_of;

use std::sync::mpsc::{Sender, Receiver, channel};

use std::thread;
use std::sync::Arc;
use std::mem;

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use communication::communicator::{Binary, Process};
use drain::DrainExt;

// TODO : Much of this only relates to BinaryWriter/BinaryReader based communication, not networking.
// TODO : Could be moved somewhere less networking-specific.

#[derive(Copy, Clone)]
pub struct MessageHeader {
    pub graph:      u64,   // graph identifier
    pub channel:    u64,   // index of channel
    pub source:     u64,   // index of worker sending message
    pub target:     u64,   // index of worker receiving message
    pub length:     u64,   // number of bytes in message
}

impl MessageHeader {
    // returns a header when there is enough supporting data
    fn try_read(bytes: &mut &[u8]) -> Option<MessageHeader> {
        if bytes.len() > size_of::<MessageHeader>() {
            // capture original in case we need to rewind
            let original = *bytes;

            // unclear what order struct initializers run in, so ...
            let graph = bytes.read_u64::<LittleEndian>().unwrap();
            let channel = bytes.read_u64::<LittleEndian>().unwrap();
            let source = bytes.read_u64::<LittleEndian>().unwrap();
            let target = bytes.read_u64::<LittleEndian>().unwrap();
            let length = bytes.read_u64::<LittleEndian>().unwrap();

            if bytes.len() >= length as usize {
                Some(MessageHeader {
                    graph: graph,
                    channel: channel,
                    source: source,
                    target: target,
                    length: length,
                })
            }
            else {
                // rewind the reader
                *bytes = original;
                None
            }
        }
        else { None }
    }

    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(self.graph));
        try!(writer.write_u64::<LittleEndian>(self.channel));
        try!(writer.write_u64::<LittleEndian>(self.source));
        try!(writer.write_u64::<LittleEndian>(self.target));
        try!(writer.write_u64::<LittleEndian>(self.length));
        Ok(())
    }
}

// structure in charge of receiving data from a Reader, for example the network
struct BinaryReceiver<R: Read> {
    reader:     R,          // the generic reader
    buffer:     Vec<u8>,    // current working buffer
    double:     Vec<u8>,    // second working buffer
    staging:    Vec<u8>,    // 1 << 20 of buffer to read into
    targets:    Switchboard<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
}

impl<R: Read> BinaryReceiver<R> {
    fn new(reader: R, channels: Receiver<((u64, u64, u64), (Sender<Vec<u8>>, Receiver<Vec<u8>>))>) -> BinaryReceiver<R> {
        BinaryReceiver {
            reader:     reader,
            buffer:     Vec::new(),
            double:     Vec::new(),
            staging:    vec![0u8; 1 << 20],
            targets:    Switchboard::new(channels),
        }
    }

    fn recv_loop(&mut self) {
        loop {

            // attempt to read some more bytes into our buffer
            // TODO : We read in to self.staging because extending a Vec<u8> is hard without
            // TODO : using set_len, which is unsafe.
            // TODO : Could consider optimizing for the self.buffer.len() == 0 case, swapping
            // TODO : self.staging with self.buffer, rather than using write_all.
            let read = self.reader.read(&mut self.staging[..]).unwrap_or(0);
            self.buffer.write_all(&self.staging[..read]).unwrap(); // <-- shouldn't fail

            {
                // get a view of available bytes
                let mut slice = &self.buffer[..];

                while let Some(header) = MessageHeader::try_read(&mut slice) {

                    let h_len = header.length as usize;  // length in bytes
                    let target = self.targets.ensure(header.target, header.graph, header.channel);
                    let mut buffer = target.1.try_recv().unwrap_or(Vec::new());

                    buffer.clear();
                    buffer.write_all(&slice[..h_len]).unwrap();
                    slice = &slice[h_len..];

                    target.0.send(buffer).unwrap();
                }

                // TODO: way inefficient... =/ Fix! :D
                // if slice.len() < self.buffer.len() {
                    self.double.clear();
                    self.double.write_all(slice).unwrap();
                // }
            }

            // if self.double.len() > 0 {
                mem::swap(&mut self.buffer, &mut self.double);
                // self.double.clear();
            // }
        }
    }
}

// structure in charge of receiving data from a Reader, for example the network
struct BinaryReceiver2<R: Read> {
    reader:     R,          // the generic reader
    buffer:     Vec<u8>,    // current working buffer
    length:     usize,
    targets:    Switchboard<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
}

impl<R: Read> BinaryReceiver2<R> {
    fn new(reader: R, channels: Receiver<((u64, u64, u64), (Sender<Vec<u8>>, Receiver<Vec<u8>>))>) -> BinaryReceiver2<R> {
        BinaryReceiver2 {
            reader:     reader,
            buffer:     vec![0u8; 1 << 20],
            length:     0,
            targets:    Switchboard::new(channels),
        }
    }

    fn recv_loop(&mut self) {
        loop {

            // if we've mostly filled our buffer and still can't read a whole message from it,
            // we'll need more space / to read more at once. let's double the buffer!
            if self.length >= self.buffer.len() / 2 {
                self.buffer.extend(::std::iter::repeat(0u8).take(self.length));
            }

            // attempt to read some more bytes into our buffer
            let read = self.reader.read(&mut self.buffer[self.length..]).unwrap_or(0);
            self.length += read;

            let remaining = {
                let mut slice = &self.buffer[..self.length];
                while let Some(header) = MessageHeader::try_read(&mut slice) {
                    let h_len = header.length as usize;  // length in bytes
                    let target = &mut self.targets.ensure(header.target, header.graph, header.channel).0;
                    target.send(slice[..h_len].to_vec()).unwrap();
                    slice = &slice[h_len..];
                }

                slice.len()
            };

            // we consumed bytes, must shift to beginning.
            // this should optimize to copy_overlapping;
            // would just do that if it weren't unsafe =/
            if remaining < self.length {
                for index in 0..remaining {
                    self.buffer[index] = self.buffer[index + self.length - remaining];
                }
                self.length = remaining;
            }
        }
    }
}

// structure in charge of sending data to a Writer, for example the network
struct BinarySender<W: Write> {
    id:         u64,    // destination process
    writer:     W,
    sources:    Receiver<(MessageHeader, Vec<u8>)>,
    returns:    Switchboard<Sender<Vec<u8>>>,
}

impl<W: Write> BinarySender<W> {
    fn new(id: u64,
           writer: W,
           sources: Receiver<(MessageHeader, Vec<u8>)>,
           channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>)>) -> BinarySender<W> {
        BinarySender {
            id:         id,
            writer:     writer,
            sources:    sources,
            returns: Switchboard::new(channels),
        }
    }

    fn send_loop(&mut self) {
        let mut stash = Vec::new();

        // block until data to recv
        while let Ok((header, buffer)) = self.sources.recv() {

            stash.push((header, buffer));

            // collect any additional outstanding data to send
            while let Ok((header, buffer)) = self.sources.try_recv() {
                stash.push((header, buffer));
            }

            // println!("send loop to process {}:\tstarting", self.id);
            for (mut header, mut buffer) in stash.drain_temp() {
                header.length = buffer.len() as u64;    // <-- is this really our job? O.o
                header.write_to(&mut self.writer).unwrap();
                self.writer.write_all(&buffer[..]).unwrap();
                buffer.clear();

                // self.returns.ensure(header.source, header.graph, header.channel).send(buffer).unwrap();
            }

            self.writer.flush().unwrap();    // <-- because writer is buffered
        }
    }
}

struct Switchboard<T:Send> {
    source: Receiver<((u64, u64, u64), T)>,
    buffer: Vec<Vec<Vec<Option<T>>>>,
}

impl<T:Send> Switchboard<T> {
    pub fn new(source: Receiver<((u64, u64, u64), T)>) -> Switchboard<T> {
        Switchboard {
            source: source,
            buffer: Vec::new(),
        }
    }

    pub fn ensure(&mut self, a: u64, b: u64, c: u64) -> &mut T {
        let a = a as usize;
        let b = b as usize;
        let c = c as usize;

        while self.buffer.len() <= a { self.buffer.push(Vec::new()); }
        while self.buffer[a].len() <= b { self.buffer[a].push(Vec::new()); }
        while self.buffer[a][b].len() <= c { self.buffer[a][b].push(None); }

        while let None = self.buffer[a][b][c] {
            let ((x, y, z), s) = self.source.recv().unwrap();

            let x = x as usize;
            let y = y as usize;
            let z = z as usize;

            while self.buffer.len() <= x { self.buffer.push(Vec::new()); }
            while self.buffer[x].len() <= y { self.buffer[x].push(Vec::new()); }
            while self.buffer[x][y].len() <= z { self.buffer[x][y].push(None); }
            self.buffer[x][y][z] = Some(s);
        }

        // we've just ensured that this is not None
        self.buffer[a][b][c].as_mut().unwrap()
    }
}

pub fn initialize_networking_from_file(filename: &str, my_index: u64, workers: u64) -> Result<Vec<Binary>> {

    let reader = BufReader::new(try!(File::open(filename)));
    let mut addresses = Vec::new();

    for line in reader.lines() {
        addresses.push(try!(line));
    }

    initialize_networking(addresses, my_index, workers)
}

pub fn initialize_networking(addresses: Vec<String>, my_index: u64, workers: u64) -> Result<Vec<Binary>> {

    let processes = addresses.len() as u64;
    let hosts1 = Arc::new(addresses);
    let hosts2 = hosts1.clone();

    let start_task = thread::spawn(move || start_connections(hosts1, my_index));
    let await_task = thread::spawn(move || await_connections(hosts2, my_index));

    let mut results = try!(start_task.join().unwrap());

    results.push(None);
    let mut to_extend = try!(await_task.join().unwrap());
    results.extend(to_extend.drain_temp());

    println!("worker {}:\tinitialization complete", my_index);

    let mut writers = Vec::new();   // handles to the BinarySenders (to present new channels)
    let mut readers = Vec::new();   // handles to the BinaryReceivers (to present new channels)
    let mut senders = Vec::new();   // destinations for serialized data (to send serialized data)

    // for each process, if a stream exists (i.e. not local) ...
    for index in (0..results.len()) {
        if let Some(stream) = results[index].take() {

            let (writer_channels_s, writer_channels_r) = channel();
            let (reader_channels_s, reader_channels_r) = channel();
            let (sender_channels_s, sender_channels_r) = channel();

            writers.push(writer_channels_s);    //
            readers.push(reader_channels_s);    //
            senders.push(sender_channels_s);    //

            let mut sender = BinarySender::new(index as u64,
                                               BufWriter::with_capacity(1 << 20, stream.try_clone().unwrap()),
                                               sender_channels_r,
                                               writer_channels_r);
            let mut recver = BinaryReceiver::new(stream.try_clone().unwrap(), reader_channels_r);

            // start senders and receivers associated with this stream
            thread::Builder::new().name(format!("send thread {}", index))
                                  .spawn(move || sender.send_loop())
                                  .unwrap();
            thread::Builder::new().name(format!("recv thread {}", index))
                                  .spawn(move || recver.recv_loop())
                                  .unwrap();

        }
    }

    let proc_comms = Process::new_vector(workers);

    let mut results = Vec::new();
    for (index, proc_comm) in proc_comms.into_iter().enumerate() {
        results.push(Binary {
            inner:          proc_comm,
            index:          my_index * workers + index as u64,
            peers:          workers * processes,
            graph:          0,          // TODO : Fix this
            allocated:      0,
            writers:        writers.clone(),
            readers:        readers.clone(),
            senders:        senders.clone(),
        });
    }

    return Ok(results);
}

// result contains connections [0, my_index - 1].
fn start_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..my_index).map(|_| None).collect();
    for index in (0..my_index) {
        let mut connected = false;
        while !connected {
            match TcpStream::connect(&addresses[index as usize][..]) {
                Ok(mut stream) => {
                    try!(stream.write_u64::<LittleEndian>(my_index));
                    results[index as usize] = Some(stream);
                    println!("worker {}:\tconnection to worker {}", my_index, index);
                    connected = true;
                },
                Err(error) => {
                    println!("worker {}:\terror connecting to worker {}: {}; retrying", my_index, index, error);
                    sleep_ms(1000);
                },
            }
        }
    }

    return Ok(results);
}

// result contains connections [my_index + 1, addresses.len() - 1].
fn await_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..(addresses.len() - my_index as usize - 1)).map(|_| None).collect();
    let listener = try!(TcpListener::bind(&addresses[my_index as usize][..]));

    for _ in (my_index as usize + 1 .. addresses.len()) {
        let mut stream = try!(listener.accept()).0;
        let identifier = try!(stream.read_u64::<LittleEndian>()) as usize;
        results[identifier - my_index as usize - 1] = Some(stream);
        println!("worker {}:\tconnection from worker {}", my_index, identifier);
    }

    return Ok(results);
}
<commit_msg>simpler, less copying receive loop<commit_after>use std::thread::sleep_ms;
use std::io::{Read, Write, Result, BufRead, BufReader, BufWriter};
use std::fs::File;

use std::net::{TcpListener, TcpStream};
use std::mem::size_of;

use std::sync::mpsc::{Sender, Receiver, channel};

use std::thread;
use std::sync::Arc;
use std::mem;

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use communication::communicator::{Binary, Process};
use drain::DrainExt;

// TODO : Much of this only relates to BinaryWriter/BinaryReader based communication, not networking.
// TODO : Could be moved somewhere less networking-specific.

#[derive(Copy, Clone)]
pub struct MessageHeader {
    pub graph:      u64,   // graph identifier
    pub channel:    u64,   // index of channel
    pub source:     u64,   // index of worker sending message
    pub target:     u64,   // index of worker receiving message
    pub length:     u64,   // number of bytes in message
}

impl MessageHeader {
    // returns a header when there is enough supporting data
    fn try_read(bytes: &mut &[u8]) -> Option<MessageHeader> {
        if bytes.len() > size_of::<MessageHeader>() {
            // capture original in case we need to rewind
            let original = *bytes;

            // unclear what order struct initializers run in, so ...
            let graph = bytes.read_u64::<LittleEndian>().unwrap();
            let channel = bytes.read_u64::<LittleEndian>().unwrap();
            let source = bytes.read_u64::<LittleEndian>().unwrap();
            let target = bytes.read_u64::<LittleEndian>().unwrap();
            let length = bytes.read_u64::<LittleEndian>().unwrap();

            if bytes.len() >= length as usize {
                Some(MessageHeader {
                    graph: graph,
                    channel: channel,
                    source: source,
                    target: target,
                    length: length,
                })
            }
            else {
                // rewind the reader
                *bytes = original;
                None
            }
        }
        else { None }
    }

    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(self.graph));
        try!(writer.write_u64::<LittleEndian>(self.channel));
        try!(writer.write_u64::<LittleEndian>(self.source));
        try!(writer.write_u64::<LittleEndian>(self.target));
        try!(writer.write_u64::<LittleEndian>(self.length));
        Ok(())
    }
}

// // structure in charge of receiving data from a Reader, for example the network
// struct BinaryReceiver<R: Read> {
//     reader:     R,          // the generic reader
//     buffer:     Vec<u8>,    // current working buffer
//     double:     Vec<u8>,    // second working buffer
//     staging:    Vec<u8>,    // 1 << 20 of buffer to read into
//     targets:    Switchboard<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
// }
//
// impl<R: Read> BinaryReceiver<R> {
//     fn new(reader: R, channels: Receiver<((u64, u64, u64), (Sender<Vec<u8>>, Receiver<Vec<u8>>))>) -> BinaryReceiver<R> {
//         BinaryReceiver {
//             reader:     reader,
//             buffer:     Vec::new(),
//             double:     Vec::new(),
//             staging:    vec![0u8; 1 << 20],
//             targets:    Switchboard::new(channels),
//         }
//     }
//
//     fn recv_loop(&mut self) {
//         loop {
//
//             // attempt to read some more bytes into our buffer
//             // TODO : We read in to self.staging because extending a Vec<u8> is hard without
//             // TODO : using set_len, which is unsafe.
//             // TODO : Could consider optimizing for the self.buffer.len() == 0 case, swapping
//             // TODO : self.staging with self.buffer, rather than using write_all.
//             let read = self.reader.read(&mut self.staging[..]).unwrap_or(0);
//             self.buffer.write_all(&self.staging[..read]).unwrap(); // <-- shouldn't fail
//
//             {
//                 // get a view of available bytes
//                 let mut slice = &self.buffer[..];
//
//                 while let Some(header) = MessageHeader::try_read(&mut slice) {
//
//                     let h_len = header.length as usize;  // length in bytes
//                     let target = self.targets.ensure(header.target, header.graph, header.channel);
//                     let mut buffer = target.1.try_recv().unwrap_or(Vec::new());
//
//                     buffer.clear();
//                     buffer.write_all(&slice[..h_len]).unwrap();
//                     slice = &slice[h_len..];
//
//                     target.0.send(buffer).unwrap();
//                 }
//
//                 // TODO: way inefficient... =/ Fix! :D
//                 // if slice.len() < self.buffer.len() {
//                     self.double.clear();
//                     self.double.write_all(slice).unwrap();
//                 // }
//             }
//
//             // if self.double.len() > 0 {
//                 mem::swap(&mut self.buffer, &mut self.double);
//                 // self.double.clear();
//             // }
//         }
//     }
// }

// structure in charge of receiving data from a Reader, for example the network
struct BinaryReceiver<R: Read> {
    reader:     R,          // the generic reader
    buffer:     Vec<u8>,    // current working buffer
    length:     usize,
    targets:    Switchboard<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
}

impl<R: Read> BinaryReceiver<R> {
    fn new(reader: R, channels: Receiver<((u64, u64, u64), (Sender<Vec<u8>>, Receiver<Vec<u8>>))>) -> BinaryReceiver<R> {
        BinaryReceiver {
            reader:     reader,
            buffer:     vec![0u8; 1 << 20],
            length:     0,
            targets:    Switchboard::new(channels),
        }
    }

    fn recv_loop(&mut self) {
        loop {

            // if we've mostly filled our buffer and still can't read a whole message from it,
            // we'll need more space / to read more at once. let's double the buffer!
            if self.length >= self.buffer.len() / 2 {
                self.buffer.extend(::std::iter::repeat(0u8).take(self.length));
            }

            // attempt to read some more bytes into our buffer
            let read = self.reader.read(&mut self.buffer[self.length..]).unwrap_or(0);
            self.length += read;

            let remaining = {
                let mut slice = &self.buffer[..self.length];
                while let Some(header) = MessageHeader::try_read(&mut slice) {
                    let h_len = header.length as usize;  // length in bytes
                    let target = &mut self.targets.ensure(header.target, header.graph, header.channel).0;
                    target.send(slice[..h_len].to_vec()).unwrap();
                    slice = &slice[h_len..];
                }

                slice.len()
            };

            // we consumed bytes, must shift to beginning.
            // this should optimize to copy_overlapping;
            // would just do that if it weren't unsafe =/
            if remaining < self.length {
                for index in 0..remaining {
                    self.buffer[index] = self.buffer[index + self.length - remaining];
                }
                self.length = remaining;
            }
        }
    }
}

// structure in charge of sending data to a Writer, for example the network
struct BinarySender<W: Write> {
    id:         u64,    // destination process
    writer:     W,
    sources:    Receiver<(MessageHeader, Vec<u8>)>,
    returns:    Switchboard<Sender<Vec<u8>>>,
}

impl<W: Write> BinarySender<W> {
    fn new(id: u64,
           writer: W,
           sources: Receiver<(MessageHeader, Vec<u8>)>,
           channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>)>) -> BinarySender<W> {
        BinarySender {
            id:         id,
            writer:     writer,
            sources:    sources,
            returns: Switchboard::new(channels),
        }
    }

    fn send_loop(&mut self) {
        let mut stash = Vec::new();

        // block until data to recv
        while let Ok((header, buffer)) = self.sources.recv() {

            stash.push((header, buffer));

            // collect any additional outstanding data to send
            while let Ok((header, buffer)) = self.sources.try_recv() {
                stash.push((header, buffer));
            }

            // println!("send loop to process {}:\tstarting", self.id);
            for (mut header, mut buffer) in stash.drain_temp() {
                header.length = buffer.len() as u64;    // <-- is this really our job? O.o
                header.write_to(&mut self.writer).unwrap();
                self.writer.write_all(&buffer[..]).unwrap();
                buffer.clear();

                // self.returns.ensure(header.source, header.graph, header.channel).send(buffer).unwrap();
            }

            self.writer.flush().unwrap();    // <-- because writer is buffered
        }
    }
}

struct Switchboard<T:Send> {
    source: Receiver<((u64, u64, u64), T)>,
    buffer: Vec<Vec<Vec<Option<T>>>>,
}

impl<T:Send> Switchboard<T> {
    pub fn new(source: Receiver<((u64, u64, u64), T)>) -> Switchboard<T> {
        Switchboard {
            source: source,
            buffer: Vec::new(),
        }
    }

    pub fn ensure(&mut self, a: u64, b: u64, c: u64) -> &mut T {
        let a = a as usize;
        let b = b as usize;
        let c = c as usize;

        while self.buffer.len() <= a { self.buffer.push(Vec::new()); }
        while self.buffer[a].len() <= b { self.buffer[a].push(Vec::new()); }
        while self.buffer[a][b].len() <= c { self.buffer[a][b].push(None); }

        while let None = self.buffer[a][b][c] {
            let ((x, y, z), s) = self.source.recv().unwrap();

            let x = x as usize;
            let y = y as usize;
            let z = z as usize;

            while self.buffer.len() <= x { self.buffer.push(Vec::new()); }
            while self.buffer[x].len() <= y { self.buffer[x].push(Vec::new()); }
            while self.buffer[x][y].len() <= z { self.buffer[x][y].push(None); }
            self.buffer[x][y][z] = Some(s);
        }

        // we've just ensured that this is not None
        self.buffer[a][b][c].as_mut().unwrap()
    }
}

pub fn initialize_networking_from_file(filename: &str, my_index: u64, workers: u64) -> Result<Vec<Binary>> {

    let reader = BufReader::new(try!(File::open(filename)));
    let mut addresses = Vec::new();

    for line in reader.lines() {
        addresses.push(try!(line));
    }

    initialize_networking(addresses, my_index, workers)
}

pub fn initialize_networking(addresses: Vec<String>, my_index: u64, workers: u64) -> Result<Vec<Binary>> {

    let processes = addresses.len() as u64;
    let hosts1 = Arc::new(addresses);
    let hosts2 = hosts1.clone();

    let start_task = thread::spawn(move || start_connections(hosts1, my_index));
    let await_task = thread::spawn(move || await_connections(hosts2, my_index));

    let mut results = try!(start_task.join().unwrap());

    results.push(None);
    let mut to_extend = try!(await_task.join().unwrap());
    results.extend(to_extend.drain_temp());

    println!("worker {}:\tinitialization complete", my_index);

    let mut writers = Vec::new();   // handles to the BinarySenders (to present new channels)
    let mut readers = Vec::new();   // handles to the BinaryReceivers (to present new channels)
    let mut senders = Vec::new();   // destinations for serialized data (to send serialized data)

    // for each process, if a stream exists (i.e. not local) ...
    for index in (0..results.len()) {
        if let Some(stream) = results[index].take() {

            let (writer_channels_s, writer_channels_r) = channel();
            let (reader_channels_s, reader_channels_r) = channel();
            let (sender_channels_s, sender_channels_r) = channel();

            writers.push(writer_channels_s);    //
            readers.push(reader_channels_s);    //
            senders.push(sender_channels_s);    //

            let mut sender = BinarySender::new(index as u64,
                                               BufWriter::with_capacity(1 << 20, stream.try_clone().unwrap()),
                                               sender_channels_r,
                                               writer_channels_r);
            let mut recver = BinaryReceiver::new(stream.try_clone().unwrap(), reader_channels_r);

            // start senders and receivers associated with this stream
            thread::Builder::new().name(format!("send thread {}", index))
                                  .spawn(move || sender.send_loop())
                                  .unwrap();
            thread::Builder::new().name(format!("recv thread {}", index))
                                  .spawn(move || recver.recv_loop())
                                  .unwrap();

        }
    }

    let proc_comms = Process::new_vector(workers);

    let mut results = Vec::new();
    for (index, proc_comm) in proc_comms.into_iter().enumerate() {
        results.push(Binary {
            inner:          proc_comm,
            index:          my_index * workers + index as u64,
            peers:          workers * processes,
            graph:          0,          // TODO : Fix this
            allocated:      0,
            writers:        writers.clone(),
            readers:        readers.clone(),
            senders:        senders.clone(),
        });
    }

    return Ok(results);
}

// result contains connections [0, my_index - 1].
fn start_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..my_index).map(|_| None).collect();
    for index in (0..my_index) {
        let mut connected = false;
        while !connected {
            match TcpStream::connect(&addresses[index as usize][..]) {
                Ok(mut stream) => {
                    try!(stream.write_u64::<LittleEndian>(my_index));
                    results[index as usize] = Some(stream);
                    println!("worker {}:\tconnection to worker {}", my_index, index);
                    connected = true;
                },
                Err(error) => {
                    println!("worker {}:\terror connecting to worker {}: {}; retrying", my_index, index, error);
                    sleep_ms(1000);
                },
            }
        }
    }

    return Ok(results);
}

// result contains connections [my_index + 1, addresses.len() - 1].
fn await_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..(addresses.len() - my_index as usize - 1)).map(|_| None).collect();
    let listener = try!(TcpListener::bind(&addresses[my_index as usize][..]));

    for _ in (my_index as usize + 1 .. addresses.len()) {
        let mut stream = try!(listener.accept()).0;
        let identifier = try!(stream.read_u64::<LittleEndian>()) as usize;
        results[identifier - my_index as usize - 1] = Some(stream);
        println!("worker {}:\tconnection from worker {}", my_index, identifier);
    }

    return Ok(results);
}
<|endoftext|>


<commit_before>use seed::prelude::*;
use crate::Msg;

pub mod perfects_utils {
	use num_bigint::{BigUint,ToBigUint};
	use num_traits::{ToPrimitive};
    use seed::prelude::*;
    use crate::Msg;

	#[derive(Clone)]
	pub struct Perfect {
		pub n: u64,
		pub p: u64,
		pub digits: u64,
		pub discovery: String,
	}

	#[derive(Clone)]
	pub struct PerfectDownload {
		pub n: u64,
		pub p: u64,
	}

	pub fn perfects() -> Vec<Perfect> {
        vec![
			Perfect {n: 51, p: 82589934, digits: 49724095, discovery: String::from("2018 Laroche, Woltman, Kurowski, Blosser, et al.")},
			Perfect {n: 50, p: 77232917, digits: 46498850, discovery: String::from("2017 Jonathan Pace, George Woltman, Scott Kurowski, Aaron Blosser, et al..") },
			Perfect {n: 49, p: 74207281, digits: 44677235, discovery: String::from("2016 Cooper, Woltman, Kurowski, Blosser et al.") },
			Perfect {n: 48, p: 57885161, digits: 34850340, discovery: String::from("2013 Cooper, Woltman, Kurowski, et al.") },
			Perfect {n: 47, p: 43112609, digits: 25956377, discovery: String::from("2008 Smith, Woltman, Kurowski, et al.") },
			Perfect {n: 46, p: 42643801, digits: 42643801, discovery: String::from("2009 Strindmo, Woltman, Kurowski, et al.") },
			Perfect {n: 45, p: 37156667, digits: 22370543, discovery: String::from("2008 Elvenich, Woltman, Kurowski, et al.") },
			Perfect {n: 44, p: 32582657, digits: 19616714, discovery: String::from("2006 Cooper, Boone, Woltman, Kurowski, et al.") },
			Perfect {n: 43, p: 30402457, digits: 18304103, discovery: String::from("2005 Cooper, Boone, Woltman, Kurowski, et al.") },
			Perfect {n: 42, p: 25964951, digits: 15632458, discovery: String::from("2005 Nowak, Woltman, Kurowski, et. al.") },
			Perfect {n: 41, p: 24036583, digits: 14471465, discovery: String::from("2004 Findley, Woltman, Kurowski, et. al.") },
			Perfect {n: 40, p: 20996011, digits: 12640858, discovery: String::from("2003 Shafer, Woltman, Kurowski, et. al.") },
			Perfect {n: 39, p: 13466917, digits: 8107892, discovery: String::from("2001 Cameron, Woltman, Kurowski, et. al.") },
			Perfect {n: 38, p: 6972593, digits: 4197919, discovery: String::from("1999 Hajratwala, Woltman, Kurowski, et. al.") },
			Perfect {n: 37, p: 3021377, digits: 1819050, discovery: String::from("1998 Clarkson, Woltman, Kurowski, et. al.") },
			Perfect {n: 36, p: 2976221, digits: 1791864, discovery: String::from("1997 Spence, Woltman, et. al.") },
			Perfect {n: 35, p: 1398269, digits: 841842, discovery: String::from("1996 Armengaud, Woltman, et. al.") },
			Perfect {n: 34, p: 1257787, digits: 757263, discovery: String::from("1996 Slowinski&Gage") },
			Perfect {n: 33, p: 859433, digits: 517430, discovery: String::from("1994 Slowinski&Gage") },
			Perfect {n: 32, p: 756839, digits: 455663, discovery: String::from("1992 Slowinski&Gage") },
			Perfect {n: 31, p: 216091, digits: 130100, discovery: String::from("1985 Slowinski") },
			Perfect {n: 30, p: 132049, digits: 79502, discovery: String::from("1983 Slowinski") },
			Perfect {n: 29, p: 110503, digits: 66530, discovery: String::from("1988 Colquitt&Welsh") },
			Perfect {n: 28, p: 86243, digits: 51924, discovery: String::from("1982 Slowinski") },
			Perfect {n: 27, p: 44497, digits: 26790, discovery: String::from("1979 Nelson&Slowinski") },
			Perfect {n: 26, p: 23209, digits: 13973, discovery: String::from("1979 Noll") },
			Perfect {n: 25, p: 21701, digits: 13066, discovery: String::from("1978 Noll&Nickel") },
			Perfect {n: 24, p: 19937, digits: 12003, discovery: String::from("1971 Tuckerman") },
			Perfect {n: 23, p: 11213, digits: 6751, discovery: String::from("1963 Gillies") },
			Perfect {n: 22, p: 9941, digits: 5985, discovery: String::from("1963 Gillies") },
			Perfect {n: 21, p: 9689, digits: 5834, discovery: String::from("1963 Gillies") },
			Perfect {n: 20, p: 4423, digits: 2663, discovery: String::from("1961 Hurwitz") },
			Perfect {n: 19, p: 4253, digits: 2561, discovery: String::from("1961 Hurwitz") },
			Perfect {n: 18, p: 3217, digits: 1937, discovery: String::from("1957 Riesel") },
			Perfect {n: 17, p: 2281, digits: 1373, discovery: String::from("1952 Robinson") },
			Perfect {n: 16, p: 2203, digits: 1327, discovery: String::from("1952 Robinson") },
			Perfect {n: 15, p: 1279, digits: 770, discovery: String::from("1952 Robinson") },
			Perfect {n: 14, p: 607, digits: 366, discovery: String::from("1952 Robinson") },
			Perfect {n: 13, p: 521, digits: 314, discovery: String::from("1952 Robinson") },
			Perfect {n: 12, p: 127, digits: 77, discovery: String::from("1876 Lucas") },
			Perfect {n: 11, p: 107, digits: 65, discovery: String::from("1914 Powers") },
			Perfect {n: 10, p: 89, digits: 54, discovery: String::from("1911 Powers") },
			Perfect {n: 9, p: 61, digits: 37, discovery: String::from("1883 Pervushin") },
			Perfect {n: 8, p: 31, digits: 19, discovery: String::from("1772 Euler") },
			Perfect {n: 7, p: 19, digits: 12, discovery: String::from("1588 Cataldi") },
			Perfect {n: 6, p: 17, digits: 10, discovery: String::from("1588 Cataldi") },
			Perfect {n: 5, p: 13, digits: 8, discovery: String::from("1456 ?") },
			Perfect {n: 4, p: 7, digits: 4, discovery: String::from("?") },
			Perfect {n: 3, p: 5, digits: 3, discovery: String::from("?") },
			Perfect {n: 2, p: 3, digits: 2, discovery: String::from("?") },
			Perfect {n: 1, p: 2, digits: 1, discovery: String::from("?") },
		]
	}

	pub fn save_as_file(filename:String, filecontent:String) -> seed::dom_types::Node<Msg> {
        let href:String = vec!["data:text/plain,",&filecontent].into_iter().collect();
        a![attrs!{At::Download => &filename, At::Href => &href}, "TXT"]
    }

	pub fn generate_file(n:u64, p:u64) -> seed::dom_types::Node<Msg> {
		let download_filename:String = format!("P{}.txt",&n.to_string());
		let two:BigUint = 2.to_biguint().unwrap();
		let power:BigUint = two.clone() << (p.to_usize().unwrap()-1-1);
        let perfect_value:BigUint = power.clone() * ((power.clone()*two.clone()) -1.to_biguint().unwrap());
        save_as_file(download_filename, perfect_value.to_string())
    }
}

pub fn render(model: &crate::Model) -> seed::dom_types::Node<Msg> {
    let mut html = vec![];
    let perfects = perfects_utils::perfects().to_owned();

    for perfect in perfects.iter() {
		let perfectp:u64 = perfect.p;
		let perfect_download = perfects_utils::PerfectDownload {n: perfect.n, p: perfect.p};
		let equation:String = format!("2{} × (2{}-1)",&(perfectp-1).to_string(),&(perfectp).to_string());

        html.push(
            tr![
                td![perfect.n.to_string()],//rank
				td![El::from_html(&equation)],//perfect number as a formula

                td![perfect.digits.to_string()],//digits in length
                td![perfect.discovery],//discovery
				if model.download.n == perfect.n {
					td![perfects_utils::generate_file(model.download.n,model.download.p)]
				} else {
					td![button!["Generate",mouse_ev("mouseup", move |event| Msg::GenerateDownload(event, perfect_download))]]
				},
            ]
        );
    }

    div![
        h1!["The Perfect Numbers"],
        br![],
        br![],
        br![],
        table![
            attrs!{At::Class => "perfecttable text"},
            tbody![
                tr![
                    td![
                        b!["No."]
                    ],
                    td![
                        b!["Prime"]
                    ],
                    td![
                        b!["Digits"]
                    ],
                    td![
                        b!["Discovered"]
                    ],
                    td![
                        b!["Download"]
                    ]
                ],
                html
            ]
        ]
    ]
}

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

    #[test]
    fn perfect_test<'a>() {
        let mut perfects:Vec<perfects_utils::Perfect> = perfects_utils::perfects();
		perfects.reverse();
        assert_eq!(perfects[49].digits, 46498850);
        assert_eq!(perfects[39].digits, 12640858);
    }
}<commit_msg>Added assertion for 51st perfect<commit_after>use seed::prelude::*;
use crate::Msg;

pub mod perfects_utils {
	use num_bigint::{BigUint,ToBigUint};
	use num_traits::{ToPrimitive};
    use seed::prelude::*;
    use crate::Msg;

	#[derive(Clone)]
	pub struct Perfect {
		pub n: u64,
		pub p: u64,
		pub digits: u64,
		pub discovery: String,
	}

	#[derive(Clone)]
	pub struct PerfectDownload {
		pub n: u64,
		pub p: u64,
	}

	pub fn perfects() -> Vec<Perfect> {
        vec![
			Perfect {n: 51, p: 82589934, digits: 49724095, discovery: String::from("2018 Laroche, Woltman, Kurowski, Blosser, et al.")},
			Perfect {n: 50, p: 77232917, digits: 46498850, discovery: String::from("2017 Jonathan Pace, George Woltman, Scott Kurowski, Aaron Blosser, et al..") },
			Perfect {n: 49, p: 74207281, digits: 44677235, discovery: String::from("2016 Cooper, Woltman, Kurowski, Blosser et al.") },
			Perfect {n: 48, p: 57885161, digits: 34850340, discovery: String::from("2013 Cooper, Woltman, Kurowski, et al.") },
			Perfect {n: 47, p: 43112609, digits: 25956377, discovery: String::from("2008 Smith, Woltman, Kurowski, et al.") },
			Perfect {n: 46, p: 42643801, digits: 42643801, discovery: String::from("2009 Strindmo, Woltman, Kurowski, et al.") },
			Perfect {n: 45, p: 37156667, digits: 22370543, discovery: String::from("2008 Elvenich, Woltman, Kurowski, et al.") },
			Perfect {n: 44, p: 32582657, digits: 19616714, discovery: String::from("2006 Cooper, Boone, Woltman, Kurowski, et al.") },
			Perfect {n: 43, p: 30402457, digits: 18304103, discovery: String::from("2005 Cooper, Boone, Woltman, Kurowski, et al.") },
			Perfect {n: 42, p: 25964951, digits: 15632458, discovery: String::from("2005 Nowak, Woltman, Kurowski, et. al.") },
			Perfect {n: 41, p: 24036583, digits: 14471465, discovery: String::from("2004 Findley, Woltman, Kurowski, et. al.") },
			Perfect {n: 40, p: 20996011, digits: 12640858, discovery: String::from("2003 Shafer, Woltman, Kurowski, et. al.") },
			Perfect {n: 39, p: 13466917, digits: 8107892, discovery: String::from("2001 Cameron, Woltman, Kurowski, et. al.") },
			Perfect {n: 38, p: 6972593, digits: 4197919, discovery: String::from("1999 Hajratwala, Woltman, Kurowski, et. al.") },
			Perfect {n: 37, p: 3021377, digits: 1819050, discovery: String::from("1998 Clarkson, Woltman, Kurowski, et. al.") },
			Perfect {n: 36, p: 2976221, digits: 1791864, discovery: String::from("1997 Spence, Woltman, et. al.") },
			Perfect {n: 35, p: 1398269, digits: 841842, discovery: String::from("1996 Armengaud, Woltman, et. al.") },
			Perfect {n: 34, p: 1257787, digits: 757263, discovery: String::from("1996 Slowinski&Gage") },
			Perfect {n: 33, p: 859433, digits: 517430, discovery: String::from("1994 Slowinski&Gage") },
			Perfect {n: 32, p: 756839, digits: 455663, discovery: String::from("1992 Slowinski&Gage") },
			Perfect {n: 31, p: 216091, digits: 130100, discovery: String::from("1985 Slowinski") },
			Perfect {n: 30, p: 132049, digits: 79502, discovery: String::from("1983 Slowinski") },
			Perfect {n: 29, p: 110503, digits: 66530, discovery: String::from("1988 Colquitt&Welsh") },
			Perfect {n: 28, p: 86243, digits: 51924, discovery: String::from("1982 Slowinski") },
			Perfect {n: 27, p: 44497, digits: 26790, discovery: String::from("1979 Nelson&Slowinski") },
			Perfect {n: 26, p: 23209, digits: 13973, discovery: String::from("1979 Noll") },
			Perfect {n: 25, p: 21701, digits: 13066, discovery: String::from("1978 Noll&Nickel") },
			Perfect {n: 24, p: 19937, digits: 12003, discovery: String::from("1971 Tuckerman") },
			Perfect {n: 23, p: 11213, digits: 6751, discovery: String::from("1963 Gillies") },
			Perfect {n: 22, p: 9941, digits: 5985, discovery: String::from("1963 Gillies") },
			Perfect {n: 21, p: 9689, digits: 5834, discovery: String::from("1963 Gillies") },
			Perfect {n: 20, p: 4423, digits: 2663, discovery: String::from("1961 Hurwitz") },
			Perfect {n: 19, p: 4253, digits: 2561, discovery: String::from("1961 Hurwitz") },
			Perfect {n: 18, p: 3217, digits: 1937, discovery: String::from("1957 Riesel") },
			Perfect {n: 17, p: 2281, digits: 1373, discovery: String::from("1952 Robinson") },
			Perfect {n: 16, p: 2203, digits: 1327, discovery: String::from("1952 Robinson") },
			Perfect {n: 15, p: 1279, digits: 770, discovery: String::from("1952 Robinson") },
			Perfect {n: 14, p: 607, digits: 366, discovery: String::from("1952 Robinson") },
			Perfect {n: 13, p: 521, digits: 314, discovery: String::from("1952 Robinson") },
			Perfect {n: 12, p: 127, digits: 77, discovery: String::from("1876 Lucas") },
			Perfect {n: 11, p: 107, digits: 65, discovery: String::from("1914 Powers") },
			Perfect {n: 10, p: 89, digits: 54, discovery: String::from("1911 Powers") },
			Perfect {n: 9, p: 61, digits: 37, discovery: String::from("1883 Pervushin") },
			Perfect {n: 8, p: 31, digits: 19, discovery: String::from("1772 Euler") },
			Perfect {n: 7, p: 19, digits: 12, discovery: String::from("1588 Cataldi") },
			Perfect {n: 6, p: 17, digits: 10, discovery: String::from("1588 Cataldi") },
			Perfect {n: 5, p: 13, digits: 8, discovery: String::from("1456 ?") },
			Perfect {n: 4, p: 7, digits: 4, discovery: String::from("?") },
			Perfect {n: 3, p: 5, digits: 3, discovery: String::from("?") },
			Perfect {n: 2, p: 3, digits: 2, discovery: String::from("?") },
			Perfect {n: 1, p: 2, digits: 1, discovery: String::from("?") },
		]
	}

	pub fn save_as_file(filename:String, filecontent:String) -> seed::dom_types::Node<Msg> {
        let href:String = vec!["data:text/plain,",&filecontent].into_iter().collect();
        a![attrs!{At::Download => &filename, At::Href => &href}, "TXT"]
    }

	pub fn generate_file(n:u64, p:u64) -> seed::dom_types::Node<Msg> {
		let download_filename:String = format!("P{}.txt",&n.to_string());
		let two:BigUint = 2.to_biguint().unwrap();
		let power:BigUint = two.clone() << (p.to_usize().unwrap()-1-1);
        let perfect_value:BigUint = power.clone() * ((power.clone()*two.clone()) -1.to_biguint().unwrap());
        save_as_file(download_filename, perfect_value.to_string())
    }
}

pub fn render(model: &crate::Model) -> seed::dom_types::Node<Msg> {
    let mut html = vec![];
    let perfects = perfects_utils::perfects().to_owned();

    for perfect in perfects.iter() {
		let perfectp:u64 = perfect.p;
		let perfect_download = perfects_utils::PerfectDownload {n: perfect.n, p: perfect.p};
		let equation:String = format!("2{} × (2{}-1)",&(perfectp-1).to_string(),&(perfectp).to_string());

        html.push(
            tr![
                td![perfect.n.to_string()],//rank
				td![El::from_html(&equation)],//perfect number as a formula

                td![perfect.digits.to_string()],//digits in length
                td![perfect.discovery],//discovery
				if model.download.n == perfect.n {
					td![perfects_utils::generate_file(model.download.n,model.download.p)]
				} else {
					td![button!["Generate",mouse_ev("mouseup", move |event| Msg::GenerateDownload(event, perfect_download))]]
				},
            ]
        );
    }

    div![
        h1!["The Perfect Numbers"],
        br![],
        br![],
        br![],
        table![
            attrs!{At::Class => "perfecttable text"},
            tbody![
                tr![
                    td![
                        b!["No."]
                    ],
                    td![
                        b!["Prime"]
                    ],
                    td![
                        b!["Digits"]
                    ],
                    td![
                        b!["Discovered"]
                    ],
                    td![
                        b!["Download"]
                    ]
                ],
                html
            ]
        ]
    ]
}

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

    #[test]
    fn perfect_test<'a>() {
        let mut perfects:Vec<perfects_utils::Perfect> = perfects_utils::perfects();
		perfects.reverse();
		assert_eq!(perfects[50].digits, 49724095);
        assert_eq!(perfects[49].digits, 46498850);
        assert_eq!(perfects[39].digits, 12640858);
    }
}<|endoftext|>


<commit_before>use std::io;
use std::io::Write;
use std::str::from_utf8;

use dbutil::normalize_position;
use error::OperationError;
use rdbutil::constants::*;
use rdbutil::{EncodeError, encode_i64, encode_slice_u8};

#[derive(PartialEq, Debug, Clone)]
pub enum ValueString {
    Integer(i64),
    Data(Vec<u8>),
}

impl ValueString {
    pub fn new(newvalue: Vec<u8>) -> Self {
        if newvalue.len() < 32 { // ought to be enough!
            if let Ok(utf8) = from_utf8(&*newvalue) {
                if let Ok(i) = utf8.parse::<i64>() {
                    return ValueString::Integer(i);
                }
            }
        }
        return ValueString::Data(newvalue);
    }

    pub fn to_vec(&self) -> Vec<u8> {
        match *self {
            ValueString::Data(ref data) => data.clone(),
            ValueString::Integer(ref int) => format!("{}", int).into_bytes(),
        }
    }

    pub fn strlen(&self) -> usize {
        match *self {
            ValueString::Data(ref data) => data.len(),
            ValueString::Integer(ref int) => format!("{}", int).len(),
        }
    }

    pub fn append(&mut self, newvalue: Vec<u8>) {
        match *self {
            ValueString::Data(ref mut data) => data.extend(newvalue),
            ValueString::Integer(i) => {
                let oldstr = format!("{}", i);
                *self = ValueString::new([oldstr.into_bytes(), newvalue].concat());
            },
        };
    }

    pub fn incr(&mut self, incr: i64) -> Result<i64, OperationError> {
        let val = match *self {
            ValueString::Integer(i) => i,
            ValueString::Data(ref data) => {
                if data.len() > 32 {
                    return Err(OperationError::OverflowError);
                }
                let res = try!(from_utf8(&data));
                try!(res.parse::<i64>())
            },
        };
        let newval = try!(val.checked_add(incr).ok_or(OperationError::OverflowError));
        *self = ValueString::Integer(newval.clone());
        Ok(newval)
    }

    pub fn incrbyfloat(&mut self, incr: f64) -> Result<f64, OperationError> {
        let val = match *self {
            ValueString::Integer(i) => i as f64,
            ValueString::Data(ref data) => {
                if data.len() > 32 {
                    return Err(OperationError::OverflowError);
                }
                let res = try!(from_utf8(&data));
                try!(res.parse::<f64>())
            },
        };
        let newval = val + incr;
        *self = ValueString::Data(format!("{}", newval).into_bytes());
        Ok(newval)
    }

    pub fn getrange(&self, _start: i64, _stop: i64) -> Vec<u8> {
        let s = match *self {
            ValueString::Integer(ref i) => format!("{}", i).into_bytes(),
            ValueString::Data(ref s) => s.clone(),
        };

        let len = s.len();
        let start = match normalize_position(_start, len) {
            Ok(i) => i,
            Err(g) => if !g { 0 } else { return Vec::new(); }
        } as usize;
        let stop = match normalize_position(_stop, len) {
            Ok(i) => i,
            Err(g) => if !g { return Vec::new(); } else { len }
        } as usize;
        let mut v = Vec::with_capacity(stop - start + 1);
        v.extend(s[start..stop + 1].iter());
        v
    }

    pub fn setbit(&mut self, bitoffset: usize, on: bool) -> bool {
        match *self {
            ValueString::Integer(i) => *self = ValueString::Data(format!("{}", i).into_bytes()),
            ValueString::Data(_) => (),
        };
        let mut d = match *self {
            ValueString::Data(ref mut d) => d,
            _ => panic!("Value should be data"),
        };

        let byte = bitoffset >> 3;

        while byte + 1 > d.len() {
            d.push(0);
        }

        let mut byteval = d[byte];
        let bit = 7 - (bitoffset & 0x7);
        let bitval = byteval & (1 << bit);

        byteval &= !(1 << bit);
        byteval |= (if on { 1 } else { 0 } & 0x1) << bit;
        d[byte] = byteval;

        bitval != 0
    }

    pub fn getbit(&self, bitoffset: usize) -> bool {
        let tmp;
        let d = match *self {
            ValueString::Integer(i) => { tmp = format!("{}", i).into_bytes(); &tmp },
            ValueString::Data(ref d) => d,
        };

        let byte = bitoffset >> 3;
        if byte >= d.len() {
            return false;
        }

        let bit = 7 - (bitoffset & 0x7);;
        let bitval = d[byte] & (1 << bit);

        bitval != 0
    }

    pub fn setrange(&mut self, _index: usize, data: Vec<u8>) -> usize {
        if data.len() == 0 {
            return self.strlen();
        }

        match *self {
            ValueString::Integer(i) => *self = ValueString::Data(format!("{}", i).into_bytes()),
            ValueString::Data(_) => (),
        }

        let mut d = match self {
            &mut ValueString::Data(ref mut s) => s,
            _ => panic!("String must be data"),
        };

        let mut index = _index;
        for _ in d.len()..index {
            d.push(0);
        }
        for c in data {
            d.push(c);
            if index < d.len() - 1 {
                d.swap_remove(index);
            }
            index += 1;
        }
        d.len()
    }

    pub fn dump<T: Write>(&self, writer: &mut T) -> io::Result<usize> {
        let mut v = vec![];
        match *self {
            ValueString::Integer(ref i) => match encode_i64(i.clone(), &mut v) {
                Ok(s) => s,
                Err(e) => match e {
                    EncodeError::IOError(e) => return Err(e),
                    EncodeError::OverflowError => try!(encode_slice_u8(&*self.to_vec(), &mut v, false))
                }
            },
            ValueString::Data(ref d) => try!(encode_slice_u8(&*d, &mut v, true)),
        };
        let data = [
            vec![TYPE_STRING],
            v,
            vec![(VERSION & 0xff) as u8],
            vec![((VERSION >> 8) & 0xff) as u8],
        ].concat();
        writer.write(&*data)
    }

    pub fn debug_object(&self) -> String {
        let mut serialized_data = vec![];
        let serialized = self.dump(&mut serialized_data).unwrap();
        let encoding = match *self {
            ValueString::Integer(_) => "int",
            ValueString::Data(_) => "raw",
        };
        format!("Value at:0x0000000000 refcount:1 encoding:{} serializedlength:{} lru:0 lru_seconds_idle:0", encoding, serialized).to_owned()
    }
}

#[cfg(test)]
mod test_rdb {
    use std::i64;

    use super::ValueString;

    #[test]
    fn dump_integer() {
        let mut v = vec![];
        ValueString::Integer(1).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\xc0\x01\x07\x00");
    }

    #[test]
    fn dump_integer_overflow() {
        let mut v = vec![];
        ValueString::Integer(i64::MAX).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\x139223372036854775807\x07\x00");
    }

    #[test]
    fn dump_string() {
        let mut v = vec![];
        ValueString::Data(b"hello world".to_vec()).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\x0bhello world\x07\x00");
    }
}
<commit_msg>Boundary check in getrange<commit_after>use std::io;
use std::io::Write;
use std::str::from_utf8;

use dbutil::normalize_position;
use error::OperationError;
use rdbutil::constants::*;
use rdbutil::{EncodeError, encode_i64, encode_slice_u8};

#[derive(PartialEq, Debug, Clone)]
pub enum ValueString {
    Integer(i64),
    Data(Vec<u8>),
}

impl ValueString {
    pub fn new(newvalue: Vec<u8>) -> Self {
        if newvalue.len() < 32 { // ought to be enough!
            if let Ok(utf8) = from_utf8(&*newvalue) {
                if let Ok(i) = utf8.parse::<i64>() {
                    return ValueString::Integer(i);
                }
            }
        }
        return ValueString::Data(newvalue);
    }

    pub fn to_vec(&self) -> Vec<u8> {
        match *self {
            ValueString::Data(ref data) => data.clone(),
            ValueString::Integer(ref int) => format!("{}", int).into_bytes(),
        }
    }

    pub fn strlen(&self) -> usize {
        match *self {
            ValueString::Data(ref data) => data.len(),
            ValueString::Integer(ref int) => format!("{}", int).len(),
        }
    }

    pub fn append(&mut self, newvalue: Vec<u8>) {
        match *self {
            ValueString::Data(ref mut data) => data.extend(newvalue),
            ValueString::Integer(i) => {
                let oldstr = format!("{}", i);
                *self = ValueString::new([oldstr.into_bytes(), newvalue].concat());
            },
        };
    }

    pub fn incr(&mut self, incr: i64) -> Result<i64, OperationError> {
        let val = match *self {
            ValueString::Integer(i) => i,
            ValueString::Data(ref data) => {
                if data.len() > 32 {
                    return Err(OperationError::OverflowError);
                }
                let res = try!(from_utf8(&data));
                try!(res.parse::<i64>())
            },
        };
        let newval = try!(val.checked_add(incr).ok_or(OperationError::OverflowError));
        *self = ValueString::Integer(newval.clone());
        Ok(newval)
    }

    pub fn incrbyfloat(&mut self, incr: f64) -> Result<f64, OperationError> {
        let val = match *self {
            ValueString::Integer(i) => i as f64,
            ValueString::Data(ref data) => {
                if data.len() > 32 {
                    return Err(OperationError::OverflowError);
                }
                let res = try!(from_utf8(&data));
                try!(res.parse::<f64>())
            },
        };
        let newval = val + incr;
        *self = ValueString::Data(format!("{}", newval).into_bytes());
        Ok(newval)
    }

    pub fn getrange(&self, _start: i64, _stop: i64) -> Vec<u8> {
        let s = match *self {
            ValueString::Integer(ref i) => format!("{}", i).into_bytes(),
            ValueString::Data(ref s) => s.clone(),
        };

        let len = s.len();
        let start = match normalize_position(_start, len) {
            Ok(i) => i,
            Err(g) => if !g { 0 } else { return Vec::new(); }
        } as usize;
        let stop = match normalize_position(_stop, len) {
            Ok(i) => i,
            Err(g) => if !g { return Vec::new(); } else { len - 1 }
        } as usize;

        if stop < start {
            return Vec::new();
        }

        let mut v = Vec::with_capacity(stop - start + 1);
        v.extend(s[start..stop + 1].iter());
        v
    }

    pub fn setbit(&mut self, bitoffset: usize, on: bool) -> bool {
        match *self {
            ValueString::Integer(i) => *self = ValueString::Data(format!("{}", i).into_bytes()),
            ValueString::Data(_) => (),
        };
        let mut d = match *self {
            ValueString::Data(ref mut d) => d,
            _ => panic!("Value should be data"),
        };

        let byte = bitoffset >> 3;

        while byte + 1 > d.len() {
            d.push(0);
        }

        let mut byteval = d[byte];
        let bit = 7 - (bitoffset & 0x7);
        let bitval = byteval & (1 << bit);

        byteval &= !(1 << bit);
        byteval |= (if on { 1 } else { 0 } & 0x1) << bit;
        d[byte] = byteval;

        bitval != 0
    }

    pub fn getbit(&self, bitoffset: usize) -> bool {
        let tmp;
        let d = match *self {
            ValueString::Integer(i) => { tmp = format!("{}", i).into_bytes(); &tmp },
            ValueString::Data(ref d) => d,
        };

        let byte = bitoffset >> 3;
        if byte >= d.len() {
            return false;
        }

        let bit = 7 - (bitoffset & 0x7);;
        let bitval = d[byte] & (1 << bit);

        bitval != 0
    }

    pub fn setrange(&mut self, _index: usize, data: Vec<u8>) -> usize {
        if data.len() == 0 {
            return self.strlen();
        }

        match *self {
            ValueString::Integer(i) => *self = ValueString::Data(format!("{}", i).into_bytes()),
            ValueString::Data(_) => (),
        }

        let mut d = match self {
            &mut ValueString::Data(ref mut s) => s,
            _ => panic!("String must be data"),
        };

        let mut index = _index;
        for _ in d.len()..index {
            d.push(0);
        }
        for c in data {
            d.push(c);
            if index < d.len() - 1 {
                d.swap_remove(index);
            }
            index += 1;
        }
        d.len()
    }

    pub fn dump<T: Write>(&self, writer: &mut T) -> io::Result<usize> {
        let mut v = vec![];
        match *self {
            ValueString::Integer(ref i) => match encode_i64(i.clone(), &mut v) {
                Ok(s) => s,
                Err(e) => match e {
                    EncodeError::IOError(e) => return Err(e),
                    EncodeError::OverflowError => try!(encode_slice_u8(&*self.to_vec(), &mut v, false))
                }
            },
            ValueString::Data(ref d) => try!(encode_slice_u8(&*d, &mut v, true)),
        };
        let data = [
            vec![TYPE_STRING],
            v,
            vec![(VERSION & 0xff) as u8],
            vec![((VERSION >> 8) & 0xff) as u8],
        ].concat();
        writer.write(&*data)
    }

    pub fn debug_object(&self) -> String {
        let mut serialized_data = vec![];
        let serialized = self.dump(&mut serialized_data).unwrap();
        let encoding = match *self {
            ValueString::Integer(_) => "int",
            ValueString::Data(_) => "raw",
        };
        format!("Value at:0x0000000000 refcount:1 encoding:{} serializedlength:{} lru:0 lru_seconds_idle:0", encoding, serialized).to_owned()
    }
}

#[cfg(test)]
mod test_rdb {
    use std::i64;

    use super::ValueString;

    #[test]
    fn dump_integer() {
        let mut v = vec![];
        ValueString::Integer(1).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\xc0\x01\x07\x00");
    }

    #[test]
    fn dump_integer_overflow() {
        let mut v = vec![];
        ValueString::Integer(i64::MAX).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\x139223372036854775807\x07\x00");
    }

    #[test]
    fn dump_string() {
        let mut v = vec![];
        ValueString::Data(b"hello world".to_vec()).dump(&mut v).unwrap();
        assert_eq!(&*v, b"\x00\x0bhello world\x07\x00");
    }
}
<|endoftext|>


<commit_before>extern crate cbindgen;

use cbindgen::*;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    style: Option<Style>,
) {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");
        }
    }

    if let Some(style) = style {
        command.arg("--style");
        command.arg(match style {
            Style::Both => "both",
            Style::Tag => "tag",
            Style::Type => "type",
        });
    }

    command.arg("-o").arg(output);

    if env::var("CBINDGEN_TEST_VERIFY").is_ok() {
        command.arg("--verify");
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
}

fn compile(cbindgen_output: &Path, language: Language) {
    let cc = env::var("CC").unwrap_or_else(|_| match language {
        Language::Cxx => "g++".to_owned(),
        Language::C => "gcc".to_owned(),
    });

    let mut object = cbindgen_output.to_path_buf();
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-c").arg(cbindgen_output);
    command.arg("-o").arg(&object);
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        command.arg("-std=c++11");
    }

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    language: Language,
    style: Option<Style>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let mut output = Path::new(&crate_dir).join("tests").join("expectations");
    if let Some(style) = style {
        match style {
            Style::Both => {
                output.push("both");
            }
            Style::Tag => {
                output.push("tag");
            }
            Style::Type => {}
        }
    }
    match language {
        Language::Cxx => {
            output.push(format!("{}.cpp", name));
        }
        Language::C => {
            output.push(format!("{}.c", name));
        }
    }

    run_cbindgen(cbindgen_path, path, &output, language, style);
    compile(&output, language);
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    for style in &[Style::Type, Style::Tag, Style::Both] {
        run_compile_test(cbindgen_path, name, &test, Language::C, Some(*style));
    }
    run_compile_test(cbindgen_path, name, &test, Language::Cxx, None);
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<commit_msg>Add support for selection of a custom C++ compiler<commit_after>extern crate cbindgen;

use cbindgen::*;
use std::path::Path;
use std::process::Command;
use std::{env, fs, str};

fn run_cbindgen(
    cbindgen_path: &'static str,
    path: &Path,
    output: &Path,
    language: Language,
    style: Option<Style>,
) {
    let program = Path::new(cbindgen_path);
    let mut command = Command::new(&program);
    match language {
        Language::Cxx => {}
        Language::C => {
            command.arg("--lang").arg("c");
        }
    }

    if let Some(style) = style {
        command.arg("--style");
        command.arg(match style {
            Style::Both => "both",
            Style::Tag => "tag",
            Style::Type => "type",
        });
    }

    command.arg("-o").arg(output);

    if env::var("CBINDGEN_TEST_VERIFY").is_ok() {
        command.arg("--verify");
    }

    let mut config = path.clone().to_path_buf();
    config.set_extension("toml");
    if config.exists() {
        command.arg("--config").arg(config);
    }

    command.arg(path);

    println!("Running: {:?}", command);
    let cbindgen_output = command.output().expect("failed to execute process");
    assert!(
        cbindgen_output.status.success(),
        "cbindgen failed: {:?} with error: {}",
        output,
        str::from_utf8(&cbindgen_output.stderr).unwrap_or_default()
    );
}

fn compile(cbindgen_output: &Path, language: Language) {
    let cc = match language {
        Language::Cxx => env::var("CXX").unwrap_or_else(|_| "g++".to_owned()),
        Language::C => env::var("CC").unwrap_or_else(|_| "gcc".to_owned()),
    };

    let mut object = cbindgen_output.to_path_buf();
    object.set_extension("o");

    let mut command = Command::new(cc);
    command.arg("-D").arg("DEFINED");
    command.arg("-c").arg(cbindgen_output);
    command.arg("-o").arg(&object);
    if let Language::Cxx = language {
        // enum class is a c++11 extension which makes g++ on macos 10.14 error out
        command.arg("-std=c++11");
    }

    println!("Running: {:?}", command);
    let out = command.output().expect("failed to compile");
    assert!(out.status.success(), "Output failed to compile: {:?}", out);

    if object.exists() {
        fs::remove_file(object).unwrap();
    }
}

fn run_compile_test(
    cbindgen_path: &'static str,
    name: &'static str,
    path: &Path,
    language: Language,
    style: Option<Style>,
) {
    let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
    let mut output = Path::new(&crate_dir).join("tests").join("expectations");
    if let Some(style) = style {
        match style {
            Style::Both => {
                output.push("both");
            }
            Style::Tag => {
                output.push("tag");
            }
            Style::Type => {}
        }
    }
    match language {
        Language::Cxx => {
            output.push(format!("{}.cpp", name));
        }
        Language::C => {
            output.push(format!("{}.c", name));
        }
    }

    run_cbindgen(cbindgen_path, path, &output, language, style);
    compile(&output, language);
}

fn test_file(cbindgen_path: &'static str, name: &'static str, filename: &'static str) {
    let test = Path::new(filename);
    for style in &[Style::Type, Style::Tag, Style::Both] {
        run_compile_test(cbindgen_path, name, &test, Language::C, Some(*style));
    }
    run_compile_test(cbindgen_path, name, &test, Language::Cxx, None);
}

macro_rules! test_file {
    ($cbindgen_path:expr, $test_function_name:ident, $name:expr, $file:tt) => {
        #[test]
        fn $test_function_name() {
            test_file($cbindgen_path, $name, $file);
        }
    };
}

// This file is generated by build.rs
include!(concat!(env!("OUT_DIR"), "/tests.rs"));
<|endoftext|>