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

use core::iter;
use core::str;
use core::vec;

pub trait ToBase64 {
    fn to_base64(&self) -> ~str;
}

static CHARS: [char, ..64] = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
];

impl<'self> ToBase64 for &'self [u8] {
    fn to_base64(&self) -> ~str {
        let mut s = ~"";
        unsafe {
            let len = self.len();
            str::reserve(&mut s, ((len + 3u) / 4u) * 3u);

            let mut i = 0u;

            while i < len - (len % 3u) {
                let n = (self[i] as uint) << 16u |
                        (self[i + 1u] as uint) << 8u |
                        (self[i + 2u] as uint);

                // This 24-bit number gets separated into four 6-bit numbers.
                str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
                str::push_char(&mut s, CHARS[n & 63u]);

                i += 3u;
            }

            // Heh, would be cool if we knew this was exhaustive
            // (the dream of bounded integer types)
            match len % 3 {
              0 => (),
              1 => {
                let n = (self[i] as uint) << 16u;
                str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
                str::push_char(&mut s, '=');
                str::push_char(&mut s, '=');
              }
              2 => {
                let n = (self[i] as uint) << 16u |
                    (self[i + 1u] as uint) << 8u;
                str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
                str::push_char(&mut s, '=');
              }
              _ => fail!(~"Algebra is broken, please alert the math police")
            }
        }
        s
    }
}

impl<'self> ToBase64 for &'self str {
    fn to_base64(&self) -> ~str {
        str::to_bytes(*self).to_base64()
    }
}

pub trait FromBase64 {
    fn from_base64(&self) -> ~[u8];
}

impl FromBase64 for ~[u8] {
    fn from_base64(&self) -> ~[u8] {
        if self.len() % 4u != 0u { fail!(~"invalid base64 length"); }

        let len = self.len();
        let mut padding = 0u;

        if len != 0u {
            if self[len - 1u] == '=' as u8 { padding += 1u; }
            if self[len - 2u] == '=' as u8 { padding += 1u; }
        }

        let mut r = vec::with_capacity((len / 4u) * 3u - padding);

        unsafe {
            let mut i = 0u;
            while i < len {
                let mut n = 0u;

                for iter::repeat(4u) {
                    let ch = self[i] as char;
                    n <<= 6u;

                    if ch >= 'A' && ch <= 'Z' {
                        n |= (ch as uint) - 0x41u;
                    } else if ch >= 'a' && ch <= 'z' {
                        n |= (ch as uint) - 0x47u;
                    } else if ch >= '0' && ch <= '9' {
                        n |= (ch as uint) + 0x04u;
                    } else if ch == '+' {
                        n |= 0x3Eu;
                    } else if ch == '/' {
                        n |= 0x3Fu;
                    } else if ch == '=' {
                        match len - i {
                          1u => {
                            r.push(((n >> 16u) & 0xFFu) as u8);
                            r.push(((n >> 8u ) & 0xFFu) as u8);
                            return copy r;
                          }
                          2u => {
                            r.push(((n >> 10u) & 0xFFu) as u8);
                            return copy r;
                          }
                          _ => fail!(~"invalid base64 padding")
                        }
                    } else {
                        fail!(~"invalid base64 character");
                    }

                    i += 1u;
                };

                r.push(((n >> 16u) & 0xFFu) as u8);
                r.push(((n >> 8u ) & 0xFFu) as u8);
                r.push(((n       ) & 0xFFu) as u8);
            }
        }
        r
    }
}

impl FromBase64 for ~str {
    fn from_base64(&self) -> ~[u8] {
        str::to_bytes(*self).from_base64()
    }
}

#[cfg(test)]
mod tests {
    use core::str;

    #[test]
    pub fn test_to_base64() {
        fail_unless!((~"").to_base64()       == ~"");
        fail_unless!((~"f").to_base64()      == ~"Zg==");
        fail_unless!((~"fo").to_base64()     == ~"Zm8=");
        fail_unless!((~"foo").to_base64()    == ~"Zm9v");
        fail_unless!((~"foob").to_base64()   == ~"Zm9vYg==");
        fail_unless!((~"fooba").to_base64()  == ~"Zm9vYmE=");
        fail_unless!((~"foobar").to_base64() == ~"Zm9vYmFy");
    }

    #[test]
    pub fn test_from_base64() {
        fail_unless!((~"").from_base64() == str::to_bytes(~""));
        fail_unless!((~"Zg==").from_base64() == str::to_bytes(~"f"));
        fail_unless!((~"Zm8=").from_base64() == str::to_bytes(~"fo"));
        fail_unless!((~"Zm9v").from_base64() == str::to_bytes(~"foo"));
        fail_unless!((~"Zm9vYg==").from_base64() == str::to_bytes(~"foob"));
        fail_unless!((~"Zm9vYmE=").from_base64() == str::to_bytes(~"fooba"));
        fail_unless!((~"Zm9vYmFy").from_base64() == str::to_bytes(~"foobar"));
    }
}
<commit_msg>base64: add docstring<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Base64 binary-to-text encoding

use core::iter;
use core::str;
use core::vec;

pub trait ToBase64 {
    fn to_base64(&self) -> ~str;
}

static CHARS: [char, ..64] = [
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
    'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
    'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
    'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
];

impl<'self> ToBase64 for &'self [u8] {
    fn to_base64(&self) -> ~str {
        let mut s = ~"";
        unsafe {
            let len = self.len();
            str::reserve(&mut s, ((len + 3u) / 4u) * 3u);

            let mut i = 0u;

            while i < len - (len % 3u) {
                let n = (self[i] as uint) << 16u |
                        (self[i + 1u] as uint) << 8u |
                        (self[i + 2u] as uint);

                // This 24-bit number gets separated into four 6-bit numbers.
                str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
                str::push_char(&mut s, CHARS[n & 63u]);

                i += 3u;
            }

            // Heh, would be cool if we knew this was exhaustive
            // (the dream of bounded integer types)
            match len % 3 {
              0 => (),
              1 => {
                let n = (self[i] as uint) << 16u;
                str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
                str::push_char(&mut s, '=');
                str::push_char(&mut s, '=');
              }
              2 => {
                let n = (self[i] as uint) << 16u |
                    (self[i + 1u] as uint) << 8u;
                str::push_char(&mut s, CHARS[(n >> 18u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 12u) & 63u]);
                str::push_char(&mut s, CHARS[(n >> 6u) & 63u]);
                str::push_char(&mut s, '=');
              }
              _ => fail!(~"Algebra is broken, please alert the math police")
            }
        }
        s
    }
}

impl<'self> ToBase64 for &'self str {
    fn to_base64(&self) -> ~str {
        str::to_bytes(*self).to_base64()
    }
}

pub trait FromBase64 {
    fn from_base64(&self) -> ~[u8];
}

impl FromBase64 for ~[u8] {
    fn from_base64(&self) -> ~[u8] {
        if self.len() % 4u != 0u { fail!(~"invalid base64 length"); }

        let len = self.len();
        let mut padding = 0u;

        if len != 0u {
            if self[len - 1u] == '=' as u8 { padding += 1u; }
            if self[len - 2u] == '=' as u8 { padding += 1u; }
        }

        let mut r = vec::with_capacity((len / 4u) * 3u - padding);

        unsafe {
            let mut i = 0u;
            while i < len {
                let mut n = 0u;

                for iter::repeat(4u) {
                    let ch = self[i] as char;
                    n <<= 6u;

                    if ch >= 'A' && ch <= 'Z' {
                        n |= (ch as uint) - 0x41u;
                    } else if ch >= 'a' && ch <= 'z' {
                        n |= (ch as uint) - 0x47u;
                    } else if ch >= '0' && ch <= '9' {
                        n |= (ch as uint) + 0x04u;
                    } else if ch == '+' {
                        n |= 0x3Eu;
                    } else if ch == '/' {
                        n |= 0x3Fu;
                    } else if ch == '=' {
                        match len - i {
                          1u => {
                            r.push(((n >> 16u) & 0xFFu) as u8);
                            r.push(((n >> 8u ) & 0xFFu) as u8);
                            return copy r;
                          }
                          2u => {
                            r.push(((n >> 10u) & 0xFFu) as u8);
                            return copy r;
                          }
                          _ => fail!(~"invalid base64 padding")
                        }
                    } else {
                        fail!(~"invalid base64 character");
                    }

                    i += 1u;
                };

                r.push(((n >> 16u) & 0xFFu) as u8);
                r.push(((n >> 8u ) & 0xFFu) as u8);
                r.push(((n       ) & 0xFFu) as u8);
            }
        }
        r
    }
}

impl FromBase64 for ~str {
    fn from_base64(&self) -> ~[u8] {
        str::to_bytes(*self).from_base64()
    }
}

#[cfg(test)]
mod tests {
    use core::str;

    #[test]
    pub fn test_to_base64() {
        fail_unless!((~"").to_base64()       == ~"");
        fail_unless!((~"f").to_base64()      == ~"Zg==");
        fail_unless!((~"fo").to_base64()     == ~"Zm8=");
        fail_unless!((~"foo").to_base64()    == ~"Zm9v");
        fail_unless!((~"foob").to_base64()   == ~"Zm9vYg==");
        fail_unless!((~"fooba").to_base64()  == ~"Zm9vYmE=");
        fail_unless!((~"foobar").to_base64() == ~"Zm9vYmFy");
    }

    #[test]
    pub fn test_from_base64() {
        fail_unless!((~"").from_base64() == str::to_bytes(~""));
        fail_unless!((~"Zg==").from_base64() == str::to_bytes(~"f"));
        fail_unless!((~"Zm8=").from_base64() == str::to_bytes(~"fo"));
        fail_unless!((~"Zm9v").from_base64() == str::to_bytes(~"foo"));
        fail_unless!((~"Zm9vYg==").from_base64() == str::to_bytes(~"foob"));
        fail_unless!((~"Zm9vYmE=").from_base64() == str::to_bytes(~"fooba"));
        fail_unless!((~"Zm9vYmFy").from_base64() == str::to_bytes(~"foobar"));
    }
}
<|endoftext|>


<commit_before><commit_msg>Specify which Read trait to use in from_reader<commit_after><|endoftext|>


<commit_before><commit_msg>Added tests for writing to static mut's in statics.<commit_after><|endoftext|>


<commit_before>use std::mem;
use std::prelude::v1::*;

use {Async, Poll};
use stream::{Stream, Fuse};

/// An adaptor that buffers elements in a vector before passing them on as one item.
///
/// This adaptor will buffer up a list of items in a stream and pass on the
/// vector used for buffering when a specified capacity has been reached. This is
/// created by the `Stream::buffer` method.
#[must_use = "streams do nothing unless polled"]
pub struct Buffer<S>
    where S: Stream
{
    capacity: usize, // TODO: Do we need this? Doesn't Vec::capacity() suffice?
    items: Vec<<S as Stream>::Item>,
    stream: Fuse<S>
}

pub fn new<S>(s: S, capacity: usize) -> Buffer<S>
    where S: Stream
{
    Buffer {
        capacity: capacity,
        items: Vec::with_capacity(capacity),
        stream: super::fuse::new(s),
    }
}

impl<S> Stream for Buffer<S>
    where S: Stream
{
    type Item = Vec<<S as Stream>::Item>;
    type Error = <S as Stream>::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        let maybe_next = try_ready!(self.stream.poll());

        if let Some(item) = maybe_next {
            // Push the item into the buffer and check whether it is
            // full. If so, replace our buffer with a new and empty one
            // and return the full one.
            self.items.push(item);
            if self.items.len() < self.capacity {
                Ok(Async::NotReady)
            } else {
                let full_buf = mem::replace(&mut self.items, Vec::with_capacity(self.capacity));
                Ok(Async::Ready(Some(full_buf)))
            }
        } else {
            // Since the underlying stream ran out of values, return
            // what we have buffered, if we have anything.
            if self.items.len() > 0 {
                let full_buf = mem::replace(&mut self.items, Vec::new());
                Ok(Async::Ready(Some(full_buf)))
            } else {
                Ok(Async::Ready(None))
            }
        }
    }
}
<commit_msg>Repeatedly call poll until Async::NotReady<commit_after>use std::mem;
use std::prelude::v1::*;

use {Async, Poll};
use stream::{Stream, Fuse};

/// An adaptor that buffers elements in a vector before passing them on as one item.
///
/// This adaptor will buffer up a list of items in a stream and pass on the
/// vector used for buffering when a specified capacity has been reached. This is
/// created by the `Stream::buffer` method.
#[must_use = "streams do nothing unless polled"]
pub struct Buffer<S>
    where S: Stream
{
    capacity: usize, // TODO: Do we need this? Doesn't Vec::capacity() suffice?
    items: Vec<<S as Stream>::Item>,
    stream: Fuse<S>
}

pub fn new<S>(s: S, capacity: usize) -> Buffer<S>
    where S: Stream
{
    Buffer {
        capacity: capacity,
        items: Vec::with_capacity(capacity),
        stream: super::fuse::new(s),
    }
}

impl<S> Stream for Buffer<S>
    where S: Stream
{
    type Item = Vec<<S as Stream>::Item>;
    type Error = <S as Stream>::Error;

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        loop {
            if let Some(item) = try_ready!(self.stream.poll()) {
                // Push the item into the buffer and check whether it is
                // full. If so, replace our buffer with a new and empty one
                // and return the full one.
                self.items.push(item);
                if self.items.len() >= self.capacity {
                    let full_buf = mem::replace(&mut self.items, Vec::with_capacity(self.capacity));
                    return Ok(Async::Ready(Some(full_buf)))
                }
            } else {
                // Since the underlying stream ran out of values, return
                // what we have buffered, if we have anything.
                return if self.items.len() > 0 {
                    let full_buf = mem::replace(&mut self.items, Vec::new());
                    Ok(Async::Ready(Some(full_buf)))
                } else {
                    Ok(Async::Ready(None))
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>feat(Process): Reveal less info about the process<commit_after><|endoftext|>


<commit_before><commit_msg>Add the proxy example from #100<commit_after>//! A proxy that forwards data to another server and forwards that server's
//! responses back to clients.

extern crate futures;
extern crate tokio_core;
extern crate tokio_io;

use std::sync::Arc;
use std::env;
use std::net::{Shutdown, SocketAddr};
use std::io::{self, Read, Write};

use futures::stream::Stream;
use futures::{Future, Poll};
use tokio_core::net::{TcpListener, TcpStream};
use tokio_core::reactor::Core;
use tokio_io::{AsyncRead, AsyncWrite};
use tokio_io::io::{copy, shutdown};

fn main() {
    let listen_addr = env::args().nth(1).unwrap_or("127.0.0.1:8081".to_string());
    let listen_addr = listen_addr.parse::<SocketAddr>().unwrap();

    let server_addr = env::args().nth(2).unwrap_or("127.0.0.1:8080".to_string());
    let server_addr = server_addr.parse::<SocketAddr>().unwrap();

    // Create the event loop that will drive this server.
    let mut l = Core::new().unwrap();
    let handle = l.handle();

    // Create a TCP listener which will listen for incoming connections.
    let socket = TcpListener::bind(&listen_addr, &l.handle()).unwrap();
    println!("Listening on: {}", listen_addr);
    println!("Proxying to: {}", server_addr);

    let done = socket.incoming().for_each(move |(client, client_addr)| {
        let server = TcpStream::connect(&server_addr, &handle);
        let amounts = server.and_then(move |server| {
            // Create separate read/write handles for the TCP clients that we're
            // proxying data between. Note that typically you'd use
            // `AsyncRead::split` for this operation, but we want our writer
            // handles to have a custom implementation of `shutdown` which
            // actually calls `TcpStream::shutdown` to ensure that EOF is
            // transmitted properly across the proxied connection.
            //
            // As a result, we wrap up our client/server manually in arcs and
            // use the impls below on our custom `MyTcpStream` type.
            let client_reader = MyTcpStream(Arc::new(client));
            let client_writer = client_reader.clone();
            let server_reader = MyTcpStream(Arc::new(server));
            let server_writer = server_reader.clone();

            // Copy the data (in parallel) between the client and the server.
            // After the copy is done we indicate to the remote side that we've
            // finished by shutting down the connection.
            let client_to_server = copy(client_reader, server_writer)
                .and_then(|(n, _, server_writer)| {
                    shutdown(server_writer).map(move |_| n)
                });

            let server_to_client = copy(server_reader, client_writer)
                .and_then(|(n, _, client_writer)| {
                    shutdown(client_writer).map(move |_| n)
                });

            client_to_server.join(server_to_client)
        });

        let msg = amounts.map(move |(from_client, from_server)| {
            println!("client at {} wrote {} bytes and received {} bytes",
                     client_addr, from_client, from_server);
        }).map_err(|e| {
            // Don't panic. Maybe the client just disconnected too soon.
            println!("error: {}", e);
        });
        handle.spawn(msg);

        Ok(())
    });
    l.run(done).unwrap();
}

// This is a custom type used to have a custom implementation of the
// `AsyncWrite::shutdown` method which actually calls `TcpStream::shutdown` to
// notify the remote end that we're done writing.
#[derive(Clone)]
struct MyTcpStream(Arc<TcpStream>);

impl Read for MyTcpStream {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (&*self.0).read(buf)
    }
}

impl Write for MyTcpStream {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        (&*self.0).write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl AsyncRead for MyTcpStream {}

impl AsyncWrite for MyTcpStream {
    fn shutdown(&mut self) -> Poll<(), io::Error> {
        try!(self.0.shutdown(Shutdown::Write));
        Ok(().into())
    }
}
<|endoftext|>


<commit_before><commit_msg>Some Drow notes<commit_after><|endoftext|>


<commit_before><commit_msg>Skeleton for problem 2358<commit_after>// https://leetcode.com/problems/maximum-number-of-groups-entering-a-competition/
pub fn maximum_groups(grades: Vec<i32>) -> i32 {
    todo!()
}

fn main() {
    println!("{}", maximum_groups(vec![10, 6, 12, 7, 3, 5])); // 3
    println!("{}", maximum_groups(vec![8, 8])); // 1
}
<|endoftext|>


<commit_before><commit_msg>Add check for object safety<commit_after>fn assert_is_object_safe<T>() {}

#[test]
fn future() {
    // `FutureExt`, `TryFutureExt` and `UnsafeFutureObj` are not object safe.
    use futures::future::{FusedFuture, Future, TryFuture};

    assert_is_object_safe::<&dyn Future<Output = ()>>();
    assert_is_object_safe::<&dyn TryFuture<Ok = (), Error = ()>>();
    assert_is_object_safe::<&dyn FusedFuture>();
}

#[test]
fn stream() {
    // `StreamExt` and `StreamExt` are not object safe.
    use futures::stream::{FusedStream, Stream, TryStream};

    assert_is_object_safe::<&dyn Stream<Item = ()>>();
    assert_is_object_safe::<&dyn TryStream<Ok = (), Error = ()>>();
    assert_is_object_safe::<&dyn FusedStream>();
}

#[test]
fn sink() {
    // `SinkExt` is not object safe.
    use futures::sink::Sink;

    assert_is_object_safe::<&dyn Sink<(), Error = ()>>();
}

#[test]
fn io() {
    // `AsyncReadExt`, `AsyncWriteExt`, `AsyncSeekExt` and `AsyncBufReadExt` are not object safe.
    use futures::io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite};

    assert_is_object_safe::<&dyn AsyncRead>();
    assert_is_object_safe::<&dyn AsyncWrite>();
    assert_is_object_safe::<&dyn AsyncSeek>();
    assert_is_object_safe::<&dyn AsyncBufRead>();
}

#[test]
fn task() {
    // `ArcWake`, `SpawnExt` and `LocalSpawnExt` are not object safe.
    use futures::task::{LocalSpawn, Spawn};

    assert_is_object_safe::<&dyn Spawn>();
    assert_is_object_safe::<&dyn LocalSpawn>();
}
<|endoftext|>


<commit_before><commit_msg>test(easy): Port toml-rs macro test (#193)<commit_after>#![cfg(feature = "easy")]
#![recursion_limit = "256"]

use std::f64;

macro_rules! table {
    ($($key:expr => $value:expr,)*) => {{
        // https://github.com/rust-lang/rust/issues/60643
        #[allow(unused_mut)]
        let mut table = toml_edit::easy::value::Table::new();
        $(
            table.insert($key.to_string(), $value.into());
        )*
        toml_edit::easy::Value::Table(table)
    }};
}

macro_rules! array {
    ($($element:expr,)*) => {{
        #![allow(clippy::vec_init_then_push)]

        // https://github.com/rust-lang/rust/issues/60643
        #[allow(unused_mut)]
        let mut array = toml_edit::easy::value::Array::new();
        $(
            array.push($element.into());
        )*
        toml_edit::easy::Value::Array(array)
    }};
}

macro_rules! datetime {
    ($s:tt) => {
        $s.parse::<toml_edit::easy::value::Datetime>().unwrap()
    };
}

#[test]
fn test_cargo_toml() {
    // Simple sanity check of:
    //
    //   - Ordinary tables
    //   - Inline tables
    //   - Inline arrays
    //   - String values
    //   - Table keys containing hyphen
    //   - Table headers containing hyphen
    let actual = toml_edit::easy::toml! {
        [package]
        name = "toml"
        version = "0.4.5"
        authors = ["Alex Crichton <alex@alexcrichton.com>"]

        [badges]
        travis-ci = { repository = "alexcrichton/toml-rs" }

        [dependencies]
        serde = "1.0"

        [dev-dependencies]
        serde_derive = "1.0"
        serde_json = "1.0"
    };

    let expected = table! {
        "package" => table! {
            "name" => "toml".to_owned(),
            "version" => "0.4.5".to_owned(),
            "authors" => array! {
                "Alex Crichton <alex@alexcrichton.com>".to_owned(),
            },
        },
        "badges" => table! {
            "travis-ci" => table! {
                "repository" => "alexcrichton/toml-rs".to_owned(),
            },
        },
        "dependencies" => table! {
            "serde" => "1.0".to_owned(),
        },
        "dev-dependencies" => table! {
            "serde_derive" => "1.0".to_owned(),
            "serde_json" => "1.0".to_owned(),
        },
    };

    assert_eq!(actual, expected);
}

#[test]
fn test_array() {
    // Copied from the TOML spec.
    let actual = toml_edit::easy::toml! {
        [[fruit]]
        name = "apple"

        [fruit.physical]
        color = "red"
        shape = "round"

        [[fruit.variety]]
        name = "red delicious"

        [[fruit.variety]]
        name = "granny smith"

        [[fruit]]
        name = "banana"

        [[fruit.variety]]
        name = "plantain"
    };

    let expected = table! {
        "fruit" => array! {
            table! {
                "name" => "apple",
                "physical" => table! {
                    "color" => "red",
                    "shape" => "round",
                },
                "variety" => array! {
                    table! {
                        "name" => "red delicious",
                    },
                    table! {
                        "name" => "granny smith",
                    },
                },
            },
            table! {
                "name" => "banana",
                "variety" => array! {
                    table! {
                        "name" => "plantain",
                    },
                },
            },
        },
    };

    assert_eq!(actual, expected);
}

#[test]
fn test_number() {
    #![allow(clippy::unusual_byte_groupings)]
    #![allow(clippy::approx_constant)]

    let actual = toml_edit::easy::toml! {
        positive = 1
        negative = -1
        table = { positive = 1, negative = -1 }
        array = [ 1, -1 ]
        neg_zero = -0
        pos_zero = +0
        float = 3.14

        sf1 = inf
        sf2 = +inf
        sf3 = -inf
        sf7 = +0.0
        sf8 = -0.0

        hex = 0xa_b_c
        oct = 0o755
        bin = 0b11010110
    };

    let expected = table! {
        "positive" => 1,
        "negative" => -1,
        "table" => table! {
            "positive" => 1,
            "negative" => -1,
        },
        "array" => array! {
            1,
            -1,
        },
        "neg_zero" => -0,
        "pos_zero" => 0,
        "float" => 3.14,
        "sf1" => f64::INFINITY,
        "sf2" => f64::INFINITY,
        "sf3" => f64::NEG_INFINITY,
        "sf7" => 0.0,
        "sf8" => -0.0,
        "hex" => 2748,
        "oct" => 493,
        "bin" => 214,
    };

    assert_eq!(actual, expected);
}

#[test]
fn test_nan() {
    let actual = toml_edit::easy::toml! {
        sf4 = nan
        sf5 = +nan
        sf6 = -nan
    };
    assert!(actual["sf4"].as_float().unwrap().is_nan());
    assert!(actual["sf5"].as_float().unwrap().is_nan());
    assert!(actual["sf6"].as_float().unwrap().is_nan());
}

#[test]
fn test_datetime() {
    let actual = toml_edit::easy::toml! {
        // Copied from the TOML spec.
        odt1 = 1979-05-27T07:32:00Z
        odt2 = 1979-05-27T00:32:00-07:00
        odt3 = 1979-05-27T00:32:00.999999-07:00
        odt4 = 1979-05-27 07:32:00Z
        ldt1 = 1979-05-27T07:32:00
        ldt2 = 1979-05-27T00:32:00.999999
        ld1 = 1979-05-27
        lt1 = 07:32:00
        lt2 = 00:32:00.999999

        table = {
            odt1 = 1979-05-27T07:32:00Z,
            odt2 = 1979-05-27T00:32:00-07:00,
            odt3 = 1979-05-27T00:32:00.999999-07:00,
            odt4 = 1979-05-27 07:32:00Z,
            ldt1 = 1979-05-27T07:32:00,
            ldt2 = 1979-05-27T00:32:00.999999,
            ld1 = 1979-05-27,
            lt1 = 07:32:00,
            lt2 = 00:32:00.999999,
        }

        array = [
            1979-05-27T07:32:00Z,
            1979-05-27T00:32:00-07:00,
            1979-05-27T00:32:00.999999-07:00,
            1979-05-27 07:32:00Z,
            1979-05-27T07:32:00,
            1979-05-27T00:32:00.999999,
            1979-05-27,
            07:32:00,
            00:32:00.999999,
        ]
    };

    let expected = table! {
        "odt1" => datetime!("1979-05-27T07:32:00Z"),
        "odt2" => datetime!("1979-05-27T00:32:00-07:00"),
        "odt3" => datetime!("1979-05-27T00:32:00.999999-07:00"),
        "odt4" => datetime!("1979-05-27 07:32:00Z"),
        "ldt1" => datetime!("1979-05-27T07:32:00"),
        "ldt2" => datetime!("1979-05-27T00:32:00.999999"),
        "ld1" => datetime!("1979-05-27"),
        "lt1" => datetime!("07:32:00"),
        "lt2" => datetime!("00:32:00.999999"),

        "table" => table! {
            "odt1" => datetime!("1979-05-27T07:32:00Z"),
            "odt2" => datetime!("1979-05-27T00:32:00-07:00"),
            "odt3" => datetime!("1979-05-27T00:32:00.999999-07:00"),
            "odt4" => datetime!("1979-05-27 07:32:00Z"),
            "ldt1" => datetime!("1979-05-27T07:32:00"),
            "ldt2" => datetime!("1979-05-27T00:32:00.999999"),
            "ld1" => datetime!("1979-05-27"),
            "lt1" => datetime!("07:32:00"),
            "lt2" => datetime!("00:32:00.999999"),
        },

        "array" => array! {
            datetime!("1979-05-27T07:32:00Z"),
            datetime!("1979-05-27T00:32:00-07:00"),
            datetime!("1979-05-27T00:32:00.999999-07:00"),
            datetime!("1979-05-27 07:32:00Z"),
            datetime!("1979-05-27T07:32:00"),
            datetime!("1979-05-27T00:32:00.999999"),
            datetime!("1979-05-27"),
            datetime!("07:32:00"),
            datetime!("00:32:00.999999"),
        },
    };

    assert_eq!(actual, expected);
}

// This test requires rustc >= 1.20.
#[test]
fn test_quoted_key() {
    let actual = toml_edit::easy::toml! {
        "quoted" = true
        table = { "quoted" = true }

        [target."cfg(windows)".dependencies]
        winapi = "0.2.8"
    };

    let expected = table! {
        "quoted" => true,
        "table" => table! {
            "quoted" => true,
        },
        "target" => table! {
            "cfg(windows)" => table! {
                "dependencies" => table! {
                    "winapi" => "0.2.8",
                },
            },
        },
    };

    assert_eq!(actual, expected);
}

#[test]
fn test_empty() {
    let actual = toml_edit::easy::toml! {
        empty_inline_table = {}
        empty_inline_array = []

        [empty_table]

        [[empty_array]]
    };

    let expected = table! {
        "empty_inline_table" => table! {},
        "empty_inline_array" => array! {},
        "empty_table" => table! {},
        "empty_array" => array! {
            table! {},
        },
    };

    assert_eq!(actual, expected);
}

#[test]
fn test_dotted_keys() {
    let actual = toml_edit::easy::toml! {
        a.b = 123
        a.c = 1979-05-27T07:32:00Z
        [table]
        a.b.c = 1
        a  .  b  .  d = 2
        in = { type.name = "cat", type.color = "blue" }
    };

    let expected = table! {
        "a" => table! {
            "b" => 123,
            "c" => datetime!("1979-05-27T07:32:00Z"),
        },
        "table" => table! {
            "a" => table! {
                "b" => table! {
                    "c" => 1,
                    "d" => 2,
                },
            },
            "in" => table! {
                "type" => table! {
                    "name" => "cat",
                    "color" => "blue",
                },
            },
        },
    };

    assert_eq!(actual, expected);
}
<|endoftext|>


<commit_before><commit_msg>Added a Rust game for Four in a row, cool :smile:<commit_after><|endoftext|>


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

use std::borrow::Cow;
use std::fmt::Display;
use std::path::Path;
use std::vec::Vec;
use std::rc::Rc;
use std::cell::RefCell;

use dbus;
use dbus::Connection;
use dbus::BusType;
use dbus::Message;
use dbus::MessageItem;
use dbus::NameFlag;
use dbus::arg::Array;
use dbus::arg::IterAppend;
use dbus::tree::Access;
use dbus::tree::EmitsChangedSignal;
use dbus::tree::Factory;
use dbus::tree::MethodErr;
use dbus::tree::MTFn;
use dbus::tree::MethodResult;
use dbus::tree::MethodInfo;
use dbus::tree::PropInfo;
use dbus::tree::Tree;
use dbus::ConnectionItem;

use engine::{Engine, Redundancy};
use stratis::VERSION;

use super::pool::create_dbus_pool;
use super::types::{DeferredAction, DbusContext, DbusErrorEnum, TData};
use super::util::STRATIS_BASE_PATH;
use super::util::STRATIS_BASE_SERVICE;
use super::util::code_to_message_items;
use super::util::default_object_path;
use super::util::engine_to_dbus_err;
use super::util::get_next_arg;
use super::util::ok_message_items;
use super::util::tuple_to_option;

fn create_pool(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message: &Message = m.msg;
    let mut iter = message.iter_init();

    let name: &str = try!(get_next_arg(&mut iter, 0));
    let redundancy: (bool, u16) = try!(get_next_arg(&mut iter, 1));
    let force: bool = try!(get_next_arg(&mut iter, 2));
    let devs: Array<&str, _> = try!(get_next_arg(&mut iter, 3));

    let blockdevs = devs.map(|x| Path::new(x)).collect::<Vec<&Path>>();

    let object_path = m.path.get_name();
    let dbus_context = m.tree.get_data();
    let result = dbus_context
        .engine
        .borrow_mut()
        .create_pool(name, &blockdevs, tuple_to_option(redundancy), force);

    let return_message = message.method_return();

    let msg = match result {
        Ok((uuid, devnodes)) => {
            let pool_object_path: dbus::Path =
                create_dbus_pool(dbus_context, object_path.clone(), uuid);
            let paths = devnodes
                .iter()
                .map(|d| {
                         d.to_str()
                             .expect("'d' originated in the 'devs' D-Bus argument.")
                             .into()
                     });
            let paths = paths.map(MessageItem::Str).collect();
            let return_path = MessageItem::ObjectPath(pool_object_path);
            let return_list = MessageItem::Array(paths, "s".into());
            let return_value = MessageItem::Struct(vec![return_path, return_list]);
            let (rc, rs) = ok_message_items();
            return_message.append3(return_value, rc, rs)
        }
        Err(x) => {
            let return_path = MessageItem::ObjectPath(default_object_path());
            let return_list = MessageItem::Array(vec![], "s".into());
            let return_value = MessageItem::Struct(vec![return_path, return_list]);
            let (rc, rs) = engine_to_dbus_err(&x);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(return_value, rc, rs)
        }
    };
    Ok(vec![msg])
}

fn destroy_pool(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {

    let message: &Message = m.msg;
    let mut iter = message.iter_init();

    let object_path: dbus::Path<'static> = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();

    let default_return = MessageItem::Bool(false);
    let return_message = message.method_return();

    let pool_uuid = match m.tree.get(&object_path) {
        Some(pool_path) => get_data!(pool_path; default_return; return_message).uuid,
        None => {
            let (rc, rs) = ok_message_items();
            return Ok(vec![return_message.append3(default_return, rc, rs)]);
        }
    };

    let msg = match dbus_context
              .engine
              .borrow_mut()
              .destroy_pool(&pool_uuid) {
        Ok(action) => {
            dbus_context
                .actions
                .borrow_mut()
                .push_remove(object_path);
            let (rc, rs) = ok_message_items();
            return_message.append3(MessageItem::Bool(action), rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(default_return, rc, rs)
        }
    };
    Ok(vec![msg])
}

fn get_list_items<T, I>(i: &mut IterAppend, iter: I) -> Result<(), MethodErr>
    where T: Display + Into<u16>,
          I: Iterator<Item = T>
{
    let msg_vec = iter.map(|item| {
                               MessageItem::Struct(vec![MessageItem::Str(format!("{}", item)),
                                                        MessageItem::UInt16(item.into())])
                           })
        .collect::<Vec<MessageItem>>();
    i.append(MessageItem::Array(msg_vec, Cow::Borrowed("(sq)")));
    Ok(())
}

fn get_error_values(i: &mut IterAppend,
                    _p: &PropInfo<MTFn<TData>, TData>)
                    -> Result<(), MethodErr> {
    get_list_items(i, DbusErrorEnum::iter_variants())
}

fn get_redundancy_values(i: &mut IterAppend,
                         _p: &PropInfo<MTFn<TData>, TData>)
                         -> Result<(), MethodErr> {
    get_list_items(i, Redundancy::iter_variants())
}

fn get_version(i: &mut IterAppend, _p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    i.append(VERSION);
    Ok(())
}

fn configure_simulator(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message = m.msg;
    let mut iter = message.iter_init();

    let denominator: u32 = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();
    let result = dbus_context
        .engine
        .borrow_mut()
        .configure_simulator(denominator);

    let return_message = message.method_return();

    let msg = match result {
        Ok(_) => {
            let (rc, rs) = ok_message_items();
            return_message.append2(rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append2(rc, rs)
        }
    };
    Ok(vec![msg])
}

fn get_base_tree<'a>(dbus_context: DbusContext) -> Tree<MTFn<TData>, TData> {

    let f = Factory::new_fn();

    let base_tree = f.tree(dbus_context);

    let create_pool_method = f.method("CreatePool", (), create_pool)
        .in_arg(("name", "s"))
        .in_arg(("redundancy", "(bq)"))
        .in_arg(("force", "b"))
        .in_arg(("devices", "as"))
        .out_arg(("result", "(oas)"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let destroy_pool_method = f.method("DestroyPool", (), destroy_pool)
        .in_arg(("pool", "o"))
        .out_arg(("action", "b"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let configure_simulator_method = f.method("ConfigureSimulator", (), configure_simulator)
        .in_arg(("denominator", "u"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let redundancy_values_property =
        f.property::<Array<(&str, u16), &Iterator<Item = (&str, u16)>>, _>("RedundancyValues", ())
            .access(Access::Read)
            .emits_changed(EmitsChangedSignal::Const)
            .on_get(get_redundancy_values);

    let error_values_property =
        f.property::<Array<(&str, u16), &Iterator<Item = (&str, u16)>>, _>("ErrorValues", ())
            .access(Access::Read)
            .emits_changed(EmitsChangedSignal::Const)
            .on_get(get_error_values);

    let version_property = f.property::<&str, _>("Version", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_version);

    let interface_name = format!("{}.{}", STRATIS_BASE_SERVICE, "Manager");

    let obj_path = f.object_path(STRATIS_BASE_PATH, None)
        .introspectable()
        .object_manager()
        .add(f.interface(interface_name, ())
                 .add_m(create_pool_method)
                 .add_m(destroy_pool_method)
                 .add_m(configure_simulator_method)
                 .add_p(error_values_property)
                 .add_p(redundancy_values_property)
                 .add_p(version_property));

    base_tree.add(obj_path)
}

#[allow(type_complexity)]
pub fn connect(engine: Rc<RefCell<Engine>>)
               -> Result<(Connection, Tree<MTFn<TData>, TData>, DbusContext), dbus::Error> {
    let c = try!(Connection::get_private(BusType::System));

    let tree = get_base_tree(DbusContext::new(engine));
    let dbus_context = tree.get_data().clone();
    try!(tree.set_registered(&c, true));

    try!(c.register_name(STRATIS_BASE_SERVICE, NameFlag::ReplaceExisting as u32));

    Ok((c, tree, dbus_context))
}

pub fn handle(c: &Connection,
              item: ConnectionItem,
              tree: &mut Tree<MTFn<TData>, TData>,
              dbus_context: &DbusContext)
              -> Result<(), dbus::Error> {
    if let ConnectionItem::MethodCall(ref msg) = item {
        if let Some(v) = tree.handle(&msg) {
            // Probably the wisest is to ignore any send errors here -
            // maybe the remote has disconnected during our processing.
            for m in v {
                let _ = c.send(m);
            }
        }

        let mut b_actions = dbus_context.actions.borrow_mut();
        for action in b_actions.drain() {
            match action {
                DeferredAction::Add(path) => {
                    try!(c.register_object_path(path.get_name()));
                    tree.insert(path);
                }
                DeferredAction::Remove(path) => {
                    c.unregister_object_path(&path);
                    tree.remove(&path);
                }
            }
        }
    }

    Ok(())
}
<commit_msg>Omit an unneeded lifetime parameter<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::borrow::Cow;
use std::fmt::Display;
use std::path::Path;
use std::vec::Vec;
use std::rc::Rc;
use std::cell::RefCell;

use dbus;
use dbus::Connection;
use dbus::BusType;
use dbus::Message;
use dbus::MessageItem;
use dbus::NameFlag;
use dbus::arg::Array;
use dbus::arg::IterAppend;
use dbus::tree::Access;
use dbus::tree::EmitsChangedSignal;
use dbus::tree::Factory;
use dbus::tree::MethodErr;
use dbus::tree::MTFn;
use dbus::tree::MethodResult;
use dbus::tree::MethodInfo;
use dbus::tree::PropInfo;
use dbus::tree::Tree;
use dbus::ConnectionItem;

use engine::{Engine, Redundancy};
use stratis::VERSION;

use super::pool::create_dbus_pool;
use super::types::{DeferredAction, DbusContext, DbusErrorEnum, TData};
use super::util::STRATIS_BASE_PATH;
use super::util::STRATIS_BASE_SERVICE;
use super::util::code_to_message_items;
use super::util::default_object_path;
use super::util::engine_to_dbus_err;
use super::util::get_next_arg;
use super::util::ok_message_items;
use super::util::tuple_to_option;

fn create_pool(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message: &Message = m.msg;
    let mut iter = message.iter_init();

    let name: &str = try!(get_next_arg(&mut iter, 0));
    let redundancy: (bool, u16) = try!(get_next_arg(&mut iter, 1));
    let force: bool = try!(get_next_arg(&mut iter, 2));
    let devs: Array<&str, _> = try!(get_next_arg(&mut iter, 3));

    let blockdevs = devs.map(|x| Path::new(x)).collect::<Vec<&Path>>();

    let object_path = m.path.get_name();
    let dbus_context = m.tree.get_data();
    let result = dbus_context
        .engine
        .borrow_mut()
        .create_pool(name, &blockdevs, tuple_to_option(redundancy), force);

    let return_message = message.method_return();

    let msg = match result {
        Ok((uuid, devnodes)) => {
            let pool_object_path: dbus::Path =
                create_dbus_pool(dbus_context, object_path.clone(), uuid);
            let paths = devnodes
                .iter()
                .map(|d| {
                         d.to_str()
                             .expect("'d' originated in the 'devs' D-Bus argument.")
                             .into()
                     });
            let paths = paths.map(MessageItem::Str).collect();
            let return_path = MessageItem::ObjectPath(pool_object_path);
            let return_list = MessageItem::Array(paths, "s".into());
            let return_value = MessageItem::Struct(vec![return_path, return_list]);
            let (rc, rs) = ok_message_items();
            return_message.append3(return_value, rc, rs)
        }
        Err(x) => {
            let return_path = MessageItem::ObjectPath(default_object_path());
            let return_list = MessageItem::Array(vec![], "s".into());
            let return_value = MessageItem::Struct(vec![return_path, return_list]);
            let (rc, rs) = engine_to_dbus_err(&x);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(return_value, rc, rs)
        }
    };
    Ok(vec![msg])
}

fn destroy_pool(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {

    let message: &Message = m.msg;
    let mut iter = message.iter_init();

    let object_path: dbus::Path<'static> = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();

    let default_return = MessageItem::Bool(false);
    let return_message = message.method_return();

    let pool_uuid = match m.tree.get(&object_path) {
        Some(pool_path) => get_data!(pool_path; default_return; return_message).uuid,
        None => {
            let (rc, rs) = ok_message_items();
            return Ok(vec![return_message.append3(default_return, rc, rs)]);
        }
    };

    let msg = match dbus_context
              .engine
              .borrow_mut()
              .destroy_pool(&pool_uuid) {
        Ok(action) => {
            dbus_context
                .actions
                .borrow_mut()
                .push_remove(object_path);
            let (rc, rs) = ok_message_items();
            return_message.append3(MessageItem::Bool(action), rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append3(default_return, rc, rs)
        }
    };
    Ok(vec![msg])
}

fn get_list_items<T, I>(i: &mut IterAppend, iter: I) -> Result<(), MethodErr>
    where T: Display + Into<u16>,
          I: Iterator<Item = T>
{
    let msg_vec = iter.map(|item| {
                               MessageItem::Struct(vec![MessageItem::Str(format!("{}", item)),
                                                        MessageItem::UInt16(item.into())])
                           })
        .collect::<Vec<MessageItem>>();
    i.append(MessageItem::Array(msg_vec, Cow::Borrowed("(sq)")));
    Ok(())
}

fn get_error_values(i: &mut IterAppend,
                    _p: &PropInfo<MTFn<TData>, TData>)
                    -> Result<(), MethodErr> {
    get_list_items(i, DbusErrorEnum::iter_variants())
}

fn get_redundancy_values(i: &mut IterAppend,
                         _p: &PropInfo<MTFn<TData>, TData>)
                         -> Result<(), MethodErr> {
    get_list_items(i, Redundancy::iter_variants())
}

fn get_version(i: &mut IterAppend, _p: &PropInfo<MTFn<TData>, TData>) -> Result<(), MethodErr> {
    i.append(VERSION);
    Ok(())
}

fn configure_simulator(m: &MethodInfo<MTFn<TData>, TData>) -> MethodResult {
    let message = m.msg;
    let mut iter = message.iter_init();

    let denominator: u32 = try!(get_next_arg(&mut iter, 0));

    let dbus_context = m.tree.get_data();
    let result = dbus_context
        .engine
        .borrow_mut()
        .configure_simulator(denominator);

    let return_message = message.method_return();

    let msg = match result {
        Ok(_) => {
            let (rc, rs) = ok_message_items();
            return_message.append2(rc, rs)
        }
        Err(err) => {
            let (rc, rs) = engine_to_dbus_err(&err);
            let (rc, rs) = code_to_message_items(rc, rs);
            return_message.append2(rc, rs)
        }
    };
    Ok(vec![msg])
}

fn get_base_tree(dbus_context: DbusContext) -> Tree<MTFn<TData>, TData> {

    let f = Factory::new_fn();

    let base_tree = f.tree(dbus_context);

    let create_pool_method = f.method("CreatePool", (), create_pool)
        .in_arg(("name", "s"))
        .in_arg(("redundancy", "(bq)"))
        .in_arg(("force", "b"))
        .in_arg(("devices", "as"))
        .out_arg(("result", "(oas)"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let destroy_pool_method = f.method("DestroyPool", (), destroy_pool)
        .in_arg(("pool", "o"))
        .out_arg(("action", "b"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let configure_simulator_method = f.method("ConfigureSimulator", (), configure_simulator)
        .in_arg(("denominator", "u"))
        .out_arg(("return_code", "q"))
        .out_arg(("return_string", "s"));

    let redundancy_values_property =
        f.property::<Array<(&str, u16), &Iterator<Item = (&str, u16)>>, _>("RedundancyValues", ())
            .access(Access::Read)
            .emits_changed(EmitsChangedSignal::Const)
            .on_get(get_redundancy_values);

    let error_values_property =
        f.property::<Array<(&str, u16), &Iterator<Item = (&str, u16)>>, _>("ErrorValues", ())
            .access(Access::Read)
            .emits_changed(EmitsChangedSignal::Const)
            .on_get(get_error_values);

    let version_property = f.property::<&str, _>("Version", ())
        .access(Access::Read)
        .emits_changed(EmitsChangedSignal::Const)
        .on_get(get_version);

    let interface_name = format!("{}.{}", STRATIS_BASE_SERVICE, "Manager");

    let obj_path = f.object_path(STRATIS_BASE_PATH, None)
        .introspectable()
        .object_manager()
        .add(f.interface(interface_name, ())
                 .add_m(create_pool_method)
                 .add_m(destroy_pool_method)
                 .add_m(configure_simulator_method)
                 .add_p(error_values_property)
                 .add_p(redundancy_values_property)
                 .add_p(version_property));

    base_tree.add(obj_path)
}

#[allow(type_complexity)]
pub fn connect(engine: Rc<RefCell<Engine>>)
               -> Result<(Connection, Tree<MTFn<TData>, TData>, DbusContext), dbus::Error> {
    let c = try!(Connection::get_private(BusType::System));

    let tree = get_base_tree(DbusContext::new(engine));
    let dbus_context = tree.get_data().clone();
    try!(tree.set_registered(&c, true));

    try!(c.register_name(STRATIS_BASE_SERVICE, NameFlag::ReplaceExisting as u32));

    Ok((c, tree, dbus_context))
}

pub fn handle(c: &Connection,
              item: ConnectionItem,
              tree: &mut Tree<MTFn<TData>, TData>,
              dbus_context: &DbusContext)
              -> Result<(), dbus::Error> {
    if let ConnectionItem::MethodCall(ref msg) = item {
        if let Some(v) = tree.handle(&msg) {
            // Probably the wisest is to ignore any send errors here -
            // maybe the remote has disconnected during our processing.
            for m in v {
                let _ = c.send(m);
            }
        }

        let mut b_actions = dbus_context.actions.borrow_mut();
        for action in b_actions.drain() {
            match action {
                DeferredAction::Add(path) => {
                    try!(c.register_object_path(path.get_name()));
                    tree.insert(path);
                }
                DeferredAction::Remove(path) => {
                    c.unregister_object_path(&path);
                    tree.remove(&path);
                }
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>Multithreaded for some reason<commit_after>// Cooperative optimization solver
use std::collections::BinaryHeap;
use std::io::Write;
extern crate rand;

#[macro_use(max)]
extern crate gelpia_utils;
extern crate ga;
extern crate gr;

use ga::{ea, Individual};

use gelpia_utils::{Quple, INF, NINF, Flt, Parameters, eps_tol};

use gr::{GI, width_box, split_box, midpoint_box};

use std::sync::{Barrier, RwLock, Arc, RwLockWriteGuard};

use std::sync::atomic::{AtomicBool, Ordering, AtomicUsize};

use std::thread;

use std::time::Duration;

extern crate function;
use function::FuncObj;

extern crate args;
use args::{process_args};

extern crate threadpool;
use threadpool::ThreadPool;
use std::sync::mpsc::channel;
extern crate time;

/// Returns the guaranteed upperbound for the algorithm
/// from the queue.
fn get_upper_bound(q: &RwLockWriteGuard<Vec<Quple>>,
                   f_best_high: f64) -> f64{
    let mut max = f_best_high;
    for qi in q.iter() {
        max = max!{max, qi.fdata.upper()};
    }
    max
}

fn log_max(q: &RwLockWriteGuard<Vec<Quple>>,
           f_best_low: f64,
           f_best_high: f64) {
    let max = get_upper_bound(q, f_best_high);
    let _ = writeln!(&mut std::io::stderr(),
                     "lb: {}, possible ub: {}, guaranteed ub: {}",
                     f_best_low,
                     f_best_high,
                     max);
}

fn print_q(q: &RwLockWriteGuard<BinaryHeap<Quple>>) {
    let mut lq: BinaryHeap<Quple> = (*q).clone();
    while lq.len() != 0 {
        let qi = lq.pop().unwrap();
        let (gen, v, fx) = (qi.pf, qi.p, qi.fdata);
        print!("[{}, {}, {}], ", v, gen, qi.fdata.to_string());
    }
    println!("\n");
}

/// Returns a tuple (function_estimate, eval_interval)
/// # Arguments
/// * `f` - The function to evaluate with
/// * `input` - The input domain
fn est_func(f: &FuncObj, input: &Vec<GI>) -> (Flt, GI) {
    let mid = midpoint_box(input);
    let est_m = f.call(&mid);
    let fsx = f.call(&input);
    let fsx_u = f.call(&input.iter()
                       .map(|&si| GI::new_p(si.upper()))
                       .collect::<Vec<_>>());
    let fsx_l = f.call(&input.iter()
                       .map(|&si| GI::new_p(si.lower()))
                       .collect::<Vec<_>>());
    let est_max = est_m.lower().max(fsx_u.lower()).max(fsx_l.lower());
    (est_max, fsx)
}

// Returns the upper bound, the domain where this bound occurs and a status
// flag indicating whether the answer is complete for the problem.
fn ibba(x_0: Vec<GI>, e_x: Flt, e_f: Flt, e_f_r: Flt,
        f_bestag: Arc<RwLock<Flt>>,
        f_best_shared: Arc<RwLock<Flt>>,
        x_bestbb: Arc<RwLock<Vec<GI>>>,
        b1: Arc<Barrier>, b2: Arc<Barrier>,
        q: Arc<RwLock<Vec<Quple>>>,
        sync: Arc<AtomicBool>, stop: Arc<AtomicBool>,
        f: FuncObj,
        logging: bool, max_iters: u32)
        -> (Flt, Flt, Vec<GI>) {
    let mut best_x = x_0.clone();

    let iters = Arc::new(AtomicUsize::new(0));
    let (est_max, first_val) = est_func(&f, &x_0);
    {
        q.write().unwrap().push(Quple{p: est_max, pf: 0, data: x_0.clone(),
                                      fdata: first_val});
    }
    let mut f_best_low = est_max;
    let mut f_best_high = est_max;

    let n_workers = 11;
    let n_jobs = n_workers;
    let pool = ThreadPool::new(n_workers);

    while q.read().unwrap().len() != 0 && !stop.load(Ordering::Acquire) {
        if max_iters != 0 && iters.load(Ordering::Acquire) as u32 >= max_iters {
            break;
        }
        if sync.load(Ordering::Acquire) {
            // Ugly: Update the update thread's view of the best branch bound.
            *f_best_shared.write().unwrap() = f_best_low;
            b1.wait();
            b2.wait();
        }
        {
            // Take q as writable during an iteration
            let q = q.write().unwrap();

            let fbl_orig = f_best_low;
            f_best_low = max!(f_best_low, *f_bestag.read().unwrap());

            if iters.load(Ordering::Acquire) % 2048 == 0 {
                let guaranteed_bound =
                    get_upper_bound(&q, f_best_high);
                if (guaranteed_bound - f_best_high).abs() < e_f {
                    f_best_high = guaranteed_bound;
                    break;
                }
            }

            if logging && fbl_orig != f_best_low {
                log_max(&q, f_best_low, f_best_high);
            }
        }

        let p_q_len = {
            let mut q = q.write().unwrap();
            q.sort();
            q.len()/n_workers + 1
        };

/*        let mut p_q = vec![];
        {
            let mut total_len = 0;
            let q = q.write().unwrap();
            let q_len = q.len();
            for i in 0..n_workers {
                let mut elems = vec![];
                for j in 0..p_q_len {
                    if i + j*n_workers >= q_len {
                        break;
                    }
                    elems.push(q[i+j*n_workers].clone());
                }
                total_len += elems.len();
                p_q.push(elems);
            }
        } */

        let outer_barr = Arc::new(Barrier::new(n_workers + 1));

        let (qtx, qrx) = channel();
        let (htx, hrx) = channel();
        let (ltx, lrx) = channel();

        for i in 0..n_workers {
            let inner_barr = outer_barr.clone();
//            let elems = p_q[i].clone();
            let _f = f.clone();
            let qtx = qtx.clone();
            let htx = htx.clone();
            let ltx = ltx.clone();
            let f_bestag = f_bestag.clone();
            let iters = iters.clone();
            let lqi = q.clone();
            pool.execute(move || {
                let mut l_f_best_high = f_best_high;
                let mut l_best_x = vec![];

                let mut l_f_best_low = f_best_low;
                let mut l_best_low_x = vec![];

                let mut lqo = vec![];
                let mut used = false;
                let lqi = lqi.read().unwrap();
//                let elems_len = elems.len();

                for j in 0..p_q_len {
                    if i + j*n_workers >= lqi.len() { break };
                    used = true;
                    let ref elem = lqi[i + j*n_workers];
                    let ref x = elem.data;
                    let ref iter_est = elem.p;
                    let ref fx = elem.fdata;
                    let ref gen = elem.pf;
                    //let (ref x, iter_est, fx, gen) = ;

                    if fx.upper() < l_f_best_low ||
                        width_box(&x, e_x) ||
                        eps_tol(*fx, *iter_est, e_f, e_f_r) {
                            if l_f_best_high < fx.upper() {
                                l_f_best_high = fx.upper();
                                l_best_x = x.clone();
                                // htx.send((fx.upper(), x.clone())).unwrap();
                            }
                        }
                    else {
                        let (x_s, is_split) = split_box(&x);
                        for sx in x_s {
                            let (est_max, fsx) = est_func(&_f, &sx);
                            if l_f_best_low < est_max {
                                l_f_best_low = est_max;
                                l_best_low_x = sx.clone();
                                // ltx.send((est_max, sx.clone())).unwrap();
                            }
                            iters.fetch_add(1, Ordering::Release);
                            if is_split && fsx.upper() > f_best_low &&
                                fsx.upper() > *f_bestag.read().unwrap() {
                                    lqo.push(Quple{p: est_max,
                                                   pf: gen+1,
                                                   data: sx,
                                                   fdata: fsx});
                                }
                        }
                    }
                }
                ltx.send((l_f_best_low, l_best_low_x, used)).unwrap();
                htx.send((l_f_best_high, l_best_x, used)).unwrap();
                lqo.sort();
                qtx.send(lqo).unwrap();
                inner_barr.wait();
            });
        }
        outer_barr.wait();
        drop(qtx);
        drop(htx);
        drop(ltx);

        for li in lrx.iter() {
            let (lb, lx, non_empty) = li;
            if non_empty && f_best_low < lb {
                f_best_low = lb;
                *x_bestbb.write().unwrap() = lx.clone();
            }
        }

        for hi in hrx.iter() {
            let (ub, ux, non_empty) = hi;
            if non_empty && f_best_high < ub {
                f_best_high = ub;
                best_x = ux.clone();
            }
        }
        {
            let mut lq = q.write().unwrap();
            *lq = vec![];
            for qis in qrx.iter() {
                for qi in &qis {
                    if qi.fdata.upper() > f_best_low {
                        lq.push(qi.clone());
                    }
                }
            }
        }
    }
    println!("{}", iters.load(Ordering::Acquire));
    stop.store(true, Ordering::Release);
    (f_best_low, f_best_high, best_x)
}

fn update(stop: Arc<AtomicBool>, _sync: Arc<AtomicBool>,
          _b1: Arc<Barrier>, _b2: Arc<Barrier>,
          _f: FuncObj,
          timeout: u32) {
    let start = time::get_time();
    let one_sec = Duration::new(1, 0);
    'out: while !stop.load(Ordering::Acquire) {
        // Timer code...
        thread::sleep(one_sec);
        if timeout > 0 &&
            (time::get_time() - start).num_seconds() >= timeout as i64 {
                let _ = writeln!(&mut std::io::stderr(), "Stopping early...");
                stop.store(true, Ordering::Release);
                break 'out;
            }
    }
}

fn main() {
    let args = process_args();

    let ref x_0 = args.domain;
    let ref fo = args.function;
    let x_err = args.x_error;
    let y_err = args.y_error;
    let y_rel = args.y_error_rel;
    let seed = args.seed;

    // Early out if there are no input variables...
    if x_0.len() == 0 {
        let result = fo.call(&x_0);
        println!("[[{},{}], {{}}]", result.lower(), result.upper());
        return
    }

    let q_inner: Vec<Quple> = Vec::new();
    let q = Arc::new(RwLock::new(q_inner));

    let population_inner: Vec<Individual> = Vec::new();
    let population = Arc::new(RwLock::new(population_inner));

    let b1 = Arc::new(Barrier::new(3));
    let b2 = Arc::new(Barrier::new(3));

    let sync = Arc::new(AtomicBool::new(false));
    let stop = Arc::new(AtomicBool::new(false));

    let f_bestag: Arc<RwLock<Flt>> = Arc::new(RwLock::new(NINF));
    let f_best_shared: Arc<RwLock<Flt>> = Arc::new(RwLock::new(NINF));

    let x_e = x_0.clone();
    let x_i = x_0.clone();

    let x_bestbb = Arc::new(RwLock::new(x_0.clone()));

    let ibba_thread =
    {
        let q = q.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let f_bestag = f_bestag.clone();
        let f_best_shared = f_best_shared.clone();
        let x_bestbb = x_bestbb.clone();
        let sync = sync.clone();
        let stop = stop.clone();
        let fo_c = fo.clone();
        let logging = args.logging;
        let iters= args.iters;
        thread::Builder::new().name("IBBA".to_string()).spawn(move || {
            ibba(x_i, x_err, y_err, y_rel,
                 f_bestag, f_best_shared,
                 x_bestbb,
                 b1, b2, q, sync, stop, fo_c, logging, iters)
        })};

    let ea_thread =
    {
        let population = population.clone();
        let f_bestag = f_bestag.clone();
        let x_bestbb = x_bestbb.clone();
        let sync = sync.clone();
        let stop = stop.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let fo_c = fo.clone();
        let factor = x_e.len();
        thread::Builder::new().name("EA".to_string()).spawn(move || {
            ea(x_e, Parameters{population: 50*factor, //1000,
                               selection: 8, //4,
                               elitism: 5, //2,
                               mutation: 0.4_f64,//0.3_f64,
                               crossover: 0.0_f64, // 0.5_f64
                               seed:  seed,
            },
               population,
               f_bestag,
               x_bestbb,
               b1, b2,
               stop, sync, fo_c)
        })};

    // pending finding out how to kill threads
    //let update_thread =
    {
        let sync = sync.clone();
        let stop = stop.clone();
        let b1 = b1.clone();
        let b2 = b2.clone();
        let fo_c = fo.clone();
        let to = args.timeout.clone();
        let _ = thread::Builder::new().name("Update".to_string()).spawn(move || {
            update(stop, sync, b1, b2, fo_c, to)
        });};

    let result = ibba_thread.unwrap().join();
    let ea_result = ea_thread.unwrap().join();

    // Join EA and Update here pending stop signaling.
    if result.is_ok() {
        let (min, mut max, mut interval) = result.unwrap();
        // Go through all remaining intervals from IBBA to find the true
        // max
        let mut lq = q.write().unwrap();
        while lq.len() != 0 {
            let ref top = lq.pop().unwrap();
            let (ub, dom) = (top.fdata.upper(), &top.data);
            if ub > max {
            max = ub;
            interval = dom.clone();
        }
    }
    println!("[[{},{}], {{", min, max);
    for i in 0..args.names.len() {
        println!("'{}' : {},", args.names[i], interval[i].to_string());
    }
    println!("}}]");

}
else {println!("error")}
}
<|endoftext|>


<commit_before><commit_msg>Mutable Fibonacci<commit_after>// compute the nth Fibonacci number
fn main() {
    let mut first = 1u;
    let mut second = 1u;
    let mut sum = 0u;
    let mut count = 0u;

    println!("Computing the 10th Fibonacci number");
    loop {
        count += 1;
        if count == 9 {
            println!("We are done here");
            break;
        }

        sum = first + second;
        first = second;
        second = sum;

    }

    println!("Computed the 10th Fibonacci {}", sum);
}
<|endoftext|>


<commit_before><commit_msg>remove obsolete cstack lint directive<commit_after><|endoftext|>


<commit_before><commit_msg>take out `rc` from behind the `libc` config flag<commit_after><|endoftext|>


<commit_before>s! {
    pub struct shmid_ds {
        pub shm_perm: ::ipc_perm,
        pub shm_segsz: ::size_t,
        pub shm_amp: *mut ::c_void,
        pub shm_lkcnt: ::c_ushort,
        pub shm_lpid: ::pid_t,
        pub shm_cpid: ::pid_t,
        pub shm_nattch: ::shmatt_t,
        pub shm_cnattch: ::c_ulong,
        pub shm_atime: ::time_t,
        pub shm_dtime: ::time_t,
        pub shm_ctime: ::time_t,
        pub shm_pad4: [i64; 4],
    }
}

pub const AF_LOCAL: ::c_int = 1; // AF_UNIX
pub const AF_FILE: ::c_int = 1; // AF_UNIX

pub const EFD_SEMAPHORE: ::c_int = 0x1;
pub const EFD_NONBLOCK: ::c_int = 0x800;
pub const EFD_CLOEXEC: ::c_int = 0x80000;

pub const TCP_KEEPIDLE: ::c_int = 34;
pub const TCP_KEEPCNT: ::c_int = 35;
pub const TCP_KEEPINTVL: ::c_int = 36;
pub const TCP_CONGESTION: ::c_int = 37;

pub const F_OFD_GETLK: ::c_int = 50;
pub const F_OFD_SETLKL: ::c_int = 51;
pub const F_OFD_SETLKW: ::c_int = 52;
pub const F_FLOCK: ::c_int = 55;
pub const F_FLOCKW: ::c_int = 56;

pub const MR_HDR_AOUT: ::c_uint = 0x3;

extern "C" {
    pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int;

    pub fn mincore(addr: ::caddr_t, len: ::size_t, vec: *mut ::c_char) -> ::c_int;

    pub fn pset_bind_lwp(
        pset: ::psetid_t,
        id: ::id_t,
        pid: ::pid_t,
        opset: *mut ::psetid_t,
    ) -> ::c_int;
    pub fn pset_getloadavg(pset: ::psetid_t, load: *mut ::c_double, num: ::c_int) -> ::c_int;

    pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t;
    pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t)
        -> ::ssize_t;
    pub fn getpagesizes2(pagesize: *mut ::size_t, nelem: ::c_int) -> ::c_int;
}
<commit_msg>illumos SOL_FILTER socket option.<commit_after>s! {
    pub struct shmid_ds {
        pub shm_perm: ::ipc_perm,
        pub shm_segsz: ::size_t,
        pub shm_amp: *mut ::c_void,
        pub shm_lkcnt: ::c_ushort,
        pub shm_lpid: ::pid_t,
        pub shm_cpid: ::pid_t,
        pub shm_nattch: ::shmatt_t,
        pub shm_cnattch: ::c_ulong,
        pub shm_atime: ::time_t,
        pub shm_dtime: ::time_t,
        pub shm_ctime: ::time_t,
        pub shm_pad4: [i64; 4],
    }

    pub struct fil_info {
        pub fi_flags: ::c_int,
        pub fi_pos: ::c_int,
        pub fi_name: [::c_char; ::FILNAME_MAX as usize],
    }
}

pub const AF_LOCAL: ::c_int = 1; // AF_UNIX
pub const AF_FILE: ::c_int = 1; // AF_UNIX

pub const EFD_SEMAPHORE: ::c_int = 0x1;
pub const EFD_NONBLOCK: ::c_int = 0x800;
pub const EFD_CLOEXEC: ::c_int = 0x80000;

pub const TCP_KEEPIDLE: ::c_int = 34;
pub const TCP_KEEPCNT: ::c_int = 35;
pub const TCP_KEEPINTVL: ::c_int = 36;
pub const TCP_CONGESTION: ::c_int = 37;

pub const F_OFD_GETLK: ::c_int = 50;
pub const F_OFD_SETLKL: ::c_int = 51;
pub const F_OFD_SETLKW: ::c_int = 52;
pub const F_FLOCK: ::c_int = 55;
pub const F_FLOCKW: ::c_int = 56;

pub const FIL_ATTACH: ::c_int = 0x1;
pub const FIL_DETACH: ::c_int = 0x2;
pub const FIL_LIST: ::c_int = 0x3;
pub const FILNAME_MAX: ::c_int = 32;
pub const FILF_PROG: ::c_int = 0x1;
pub const FILF_AUTO: ::c_int = 0x2;
pub const FILF_BYPASS: ::c_int = 0x4;
pub const SOL_FILTER: ::c_int = 0xfffc;

pub const MR_HDR_AOUT: ::c_uint = 0x3;

extern "C" {
    pub fn eventfd(init: ::c_uint, flags: ::c_int) -> ::c_int;

    pub fn mincore(addr: ::caddr_t, len: ::size_t, vec: *mut ::c_char) -> ::c_int;

    pub fn pset_bind_lwp(
        pset: ::psetid_t,
        id: ::id_t,
        pid: ::pid_t,
        opset: *mut ::psetid_t,
    ) -> ::c_int;
    pub fn pset_getloadavg(pset: ::psetid_t, load: *mut ::c_double, num: ::c_int) -> ::c_int;

    pub fn preadv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t) -> ::ssize_t;
    pub fn pwritev(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int, offset: ::off_t)
        -> ::ssize_t;
    pub fn getpagesizes2(pagesize: *mut ::size_t, nelem: ::c_int) -> ::c_int;
}
<|endoftext|>


<commit_before>#[doc = "Random number generation"];

export rng, seed, seeded_rng, weighted, extensions;

enum rctx {}

#[abi = "cdecl"]
native mod rustrt {
    fn rand_seed() -> [u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: [u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;
}

#[doc = "A value with a particular weight compared to other values"]
type weighted<T> = { weight: uint, item: T };

#[doc = "Extension methods for random number generators"]
impl extensions for rng {

    #[doc = "Return a random int"]
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    #[doc = "Return an int randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_int_from(start: int, end: int) -> int {
        assert start <= end;
        start + int::abs(self.gen_int() % (end - start + 1))
    }

    #[doc = "Return a random i8"]
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    #[doc = "Return a random i16"]
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    #[doc = "Return a random i32"]
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    #[doc = "Return a random i64"]
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    #[doc = "Return a random uint"]
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    #[doc = "Return a uint randomly chosen from the range [start, end], \
             failing if start > end"]
    fn gen_uint_from(start: uint, end: uint) -> uint {
        assert start <= end;
        start + (self.gen_uint() % (end - start + 1u))
    }

    #[doc = "Return a random u8"]
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    #[doc = "Return a random u16"]
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    #[doc = "Return a random u32"]
    fn gen_u32() -> u32 {
        self.next()
    }

    #[doc = "Return a random u64"]
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    #[doc = "Return a random float"]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    #[doc = "Return a random f32"]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    #[doc = "Return a random f64"]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        let scale = u32::max_value as f64;
        ret ((u1 / scale + u2) / scale + u3) / scale;
    }

    #[doc = "Return a random char"]
    fn gen_char() -> char {
        self.next() as char
    }

    #[doc = "Return a char randomly chosen from chars, failing if chars is \
             empty"]
    fn gen_char_from(chars: str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    #[doc = "Return a random bool"]
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    #[doc = "Return a bool with a 1 in n chance of true"]
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_from(1u, n) == 1u
        }
    }

    #[doc = "Return a random string of the specified length composed of A-Z, \
             a-z, 0-9"]
    fn gen_str(len: uint) -> str {
        let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                      "abcdefghijklmnopqrstuvwxyz" +
                      "0123456789";
        let mut s = "";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        s
    }

    #[doc = "Return a random byte string of the specified length"]
    fn gen_bytes(len: uint) -> [u8] {
        vec::from_fn(len) {|_i|
            self.gen_u8()
        }
    }

    #[doc = "Choose an item randomly, failing if values is empty"]
    fn choose<T:copy>(values: [T]) -> T {
        self.choose_option(values).get()
    }

    #[doc = "Choose some(item) randomly, returning none if values is empty"]
    fn choose_option<T:copy>(values: [T]) -> option<T> {
        if values.is_empty() {
            none
        } else {
            some(values[self.gen_uint_from(0u, values.len() - 1u)])
        }
    }

    #[doc = "Choose an item respecting the relative weights, failing if \
             the sum of the weights is 0"]
    fn choose_weighted<T: copy>(v : [weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    #[doc = "Choose some(item) respecting the relative weights, returning \
             none if the sum of the weights is 0"]
    fn choose_weighted_option<T:copy>(v: [weighted<T>]) -> option<T> {
        let mut total = 0u;
        for v.each {|item|
            total += item.weight;
        }
        if total == 0u {
            ret none;
        }
        let chosen = self.gen_uint_from(0u, total - 1u);
        let mut so_far = 0u;
        for v.each {|item|
            so_far += item.weight;
            if so_far > chosen {
                ret some(item.item);
            }
        }
        unreachable();
    }

    #[doc = "Return a vec containing copies of the items, in order, where \
             the weight of the item determines how many copies there are"]
    fn weighted_vec<T:copy>(v: [weighted<T>]) -> [T] {
        let mut r = [];
        for v.each {|item|
            uint::range(0u, item.weight) {|_i|
                r += [item.item];
            }
        }
        r
    }

    #[doc = "Shuffle a vec"]
    fn shuffle<T:copy>(values: [T]) -> [T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        ret vec::from_mut(m);
    }

    #[doc = "Shuffle a mutable vec in place"]
    fn shuffle_mut<T>(&values: [mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_from(0u, i));
        }
    }

}

resource rand_res(c: *rctx) { rustrt::rand_free(c); }

impl of rng for @rand_res {
    fn next() -> u32 { ret rustrt::rand_next(**self); }
}

#[doc = "Create a new random seed for seeded_rng"]
fn seed() -> [u8] {
    rustrt::rand_seed()
}

#[doc = "Create a random number generator with a system specified seed"]
fn rng() -> rng {
    @rand_res(rustrt::rand_new()) as rng
}

#[doc = "Create a random number generator using the specified seed. A \
         generator constructed with a given seed will generate the same \
         sequence of values as all other generators constructed with the \
         same seed. The seed may be any length."]
fn seeded_rng(seed: [u8]) -> rng {
    @rand_res(rustrt::rand_new_seeded(seed)) as rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn gen_int_from() {
        let r = rand::rng();
        let a = r.gen_int_from(-3, 42);
        assert a >= -3 && a <= 42;
        assert r.gen_int_from(0, 0) == 0;
        assert r.gen_int_from(-12, -12) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(target_os = "win3"))]
    fn gen_int_from_fail() {
        rand::rng().gen_int_from(5, -2);
    }

    #[test]
    fn gen_uint_from() {
        let r = rand::rng();
        let a = r.gen_uint_from(3u, 42u);
        assert a >= 3u && a <= 42u;
        assert r.gen_uint_from(0u, 0u) == 0u;
        assert r.gen_uint_from(12u, 12u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(target_os = "win3"))]
    fn gen_uint_from_fail() {
        rand::rng().gen_uint_from(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option([]) == none::<int>;
        assert r.choose_option([1, 1, 1]) == some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::rng();
        assert r.choose_weighted([{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option([{weight: 1u, item: 42}]) == some(42);
        assert r.choose_weighted_option([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == some(43);
        assert r.choose_weighted_option([]) == none::<int>;
    }

    #[test]
    fn weighted_vec() {
        let r = rand::rng();
        let empty: [int] = [];
        assert r.weighted_vec([]) == empty;
        assert r.weighted_vec([
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == [2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::rng();
        let empty: [int] = [];
        assert r.shuffle([]) == empty;
        assert r.shuffle([1, 1, 1]) == [1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>core: Rework some rand functions to be more consistent<commit_after>#[doc = "Random number generation"];

export rng, seed, seeded_rng, weighted, extensions;

enum rctx {}

#[abi = "cdecl"]
native mod rustrt {
    fn rand_seed() -> [u8];
    fn rand_new() -> *rctx;
    fn rand_new_seeded(seed: [u8]) -> *rctx;
    fn rand_next(c: *rctx) -> u32;
    fn rand_free(c: *rctx);
}

#[doc = "A random number generator"]
iface rng {
    #[doc = "Return the next random integer"]
    fn next() -> u32;
}

#[doc = "A value with a particular weight compared to other values"]
type weighted<T> = { weight: uint, item: T };

#[doc = "Extension methods for random number generators"]
impl extensions for rng {

    #[doc = "Return a random int"]
    fn gen_int() -> int {
        self.gen_i64() as int
    }

    #[doc = "Return an int randomly chosen from the range [start, end), \
             failing if start >= end"]
    fn gen_int_range(start: int, end: int) -> int {
        assert start < end;
        start + int::abs(self.gen_int() % (end - start))
    }

    #[doc = "Return a random i8"]
    fn gen_i8() -> i8 {
        self.next() as i8
    }

    #[doc = "Return a random i16"]
    fn gen_i16() -> i16 {
        self.next() as i16
    }

    #[doc = "Return a random i32"]
    fn gen_i32() -> i32 {
        self.next() as i32
    }

    #[doc = "Return a random i64"]
    fn gen_i64() -> i64 {
        (self.next() as i64 << 32) | self.next() as i64
    }

    #[doc = "Return a random uint"]
    fn gen_uint() -> uint {
        self.gen_u64() as uint
    }

    #[doc = "Return a uint randomly chosen from the range [start, end), \
             failing if start >= end"]
    fn gen_uint_range(start: uint, end: uint) -> uint {
        assert start < end;
        start + (self.gen_uint() % (end - start))
    }

    #[doc = "Return a random u8"]
    fn gen_u8() -> u8 {
        self.next() as u8
    }

    #[doc = "Return a random u16"]
    fn gen_u16() -> u16 {
        self.next() as u16
    }

    #[doc = "Return a random u32"]
    fn gen_u32() -> u32 {
        self.next()
    }

    #[doc = "Return a random u64"]
    fn gen_u64() -> u64 {
        (self.next() as u64 << 32) | self.next() as u64
    }

    #[doc = "Return a random float"]
    fn gen_float() -> float {
        self.gen_f64() as float
    }

    #[doc = "Return a random f32"]
    fn gen_f32() -> f32 {
        self.gen_f64() as f32
    }

    #[doc = "Return a random f64"]
    fn gen_f64() -> f64 {
        let u1 = self.next() as f64;
        let u2 = self.next() as f64;
        let u3 = self.next() as f64;
        let scale = u32::max_value as f64;
        ret ((u1 / scale + u2) / scale + u3) / scale;
    }

    #[doc = "Return a random char"]
    fn gen_char() -> char {
        self.next() as char
    }

    #[doc = "Return a char randomly chosen from chars, failing if chars is \
             empty"]
    fn gen_char_from(chars: str) -> char {
        assert !chars.is_empty();
        self.choose(str::chars(chars))
    }

    #[doc = "Return a random bool"]
    fn gen_bool() -> bool {
        self.next() & 1u32 == 1u32
    }

    #[doc = "Return a bool with a 1 in n chance of true"]
    fn gen_weighted_bool(n: uint) -> bool {
        if n == 0u {
            true
        } else {
            self.gen_uint_range(1u, n + 1u) == 1u
        }
    }

    #[doc = "Return a random string of the specified length composed of A-Z, \
             a-z, 0-9"]
    fn gen_str(len: uint) -> str {
        let charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
                      "abcdefghijklmnopqrstuvwxyz" +
                      "0123456789";
        let mut s = "";
        let mut i = 0u;
        while (i < len) {
            s = s + str::from_char(self.gen_char_from(charset));
            i += 1u;
        }
        s
    }

    #[doc = "Return a random byte string of the specified length"]
    fn gen_bytes(len: uint) -> [u8] {
        vec::from_fn(len) {|_i|
            self.gen_u8()
        }
    }

    #[doc = "Choose an item randomly, failing if values is empty"]
    fn choose<T:copy>(values: [T]) -> T {
        self.choose_option(values).get()
    }

    #[doc = "Choose some(item) randomly, returning none if values is empty"]
    fn choose_option<T:copy>(values: [T]) -> option<T> {
        if values.is_empty() {
            none
        } else {
            some(values[self.gen_uint_range(0u, values.len())])
        }
    }

    #[doc = "Choose an item respecting the relative weights, failing if \
             the sum of the weights is 0"]
    fn choose_weighted<T: copy>(v : [weighted<T>]) -> T {
        self.choose_weighted_option(v).get()
    }

    #[doc = "Choose some(item) respecting the relative weights, returning \
             none if the sum of the weights is 0"]
    fn choose_weighted_option<T:copy>(v: [weighted<T>]) -> option<T> {
        let mut total = 0u;
        for v.each {|item|
            total += item.weight;
        }
        if total == 0u {
            ret none;
        }
        let chosen = self.gen_uint_range(0u, total);
        let mut so_far = 0u;
        for v.each {|item|
            so_far += item.weight;
            if so_far > chosen {
                ret some(item.item);
            }
        }
        unreachable();
    }

    #[doc = "Return a vec containing copies of the items, in order, where \
             the weight of the item determines how many copies there are"]
    fn weighted_vec<T:copy>(v: [weighted<T>]) -> [T] {
        let mut r = [];
        for v.each {|item|
            uint::range(0u, item.weight) {|_i|
                r += [item.item];
            }
        }
        r
    }

    #[doc = "Shuffle a vec"]
    fn shuffle<T:copy>(values: [T]) -> [T] {
        let mut m = vec::to_mut(values);
        self.shuffle_mut(m);
        ret vec::from_mut(m);
    }

    #[doc = "Shuffle a mutable vec in place"]
    fn shuffle_mut<T>(&values: [mut T]) {
        let mut i = values.len();
        while i >= 2u {
            // invariant: elements with index >= i have been locked in place.
            i -= 1u;
            // lock element i in place.
            vec::swap(values, i, self.gen_uint_range(0u, i + 1u));
        }
    }

}

resource rand_res(c: *rctx) { rustrt::rand_free(c); }

impl of rng for @rand_res {
    fn next() -> u32 { ret rustrt::rand_next(**self); }
}

#[doc = "Create a new random seed for seeded_rng"]
fn seed() -> [u8] {
    rustrt::rand_seed()
}

#[doc = "Create a random number generator with a system specified seed"]
fn rng() -> rng {
    @rand_res(rustrt::rand_new()) as rng
}

#[doc = "Create a random number generator using the specified seed. A \
         generator constructed with a given seed will generate the same \
         sequence of values as all other generators constructed with the \
         same seed. The seed may be any length."]
fn seeded_rng(seed: [u8]) -> rng {
    @rand_res(rustrt::rand_new_seeded(seed)) as rng
}

#[cfg(test)]
mod tests {

    #[test]
    fn rng_seeded() {
        let seed = rand::seed();
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn rng_seeded_custom_seed() {
        // much shorter than generated seeds which are 1024 bytes
        let seed = [2u8, 32u8, 4u8, 32u8, 51u8];
        let ra = rand::seeded_rng(seed);
        let rb = rand::seeded_rng(seed);
        assert ra.gen_str(100u) == rb.gen_str(100u);
    }

    #[test]
    fn gen_int_range() {
        let r = rand::rng();
        let a = r.gen_int_range(-3, 42);
        assert a >= -3 && a < 42;
        assert r.gen_int_range(0, 1) == 0;
        assert r.gen_int_range(-12, -11) == -12;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(target_os = "win3"))]
    fn gen_int_from_fail() {
        rand::rng().gen_int_range(5, -2);
    }

    #[test]
    fn gen_uint_range() {
        let r = rand::rng();
        let a = r.gen_uint_range(3u, 42u);
        assert a >= 3u && a < 42u;
        assert r.gen_uint_range(0u, 1u) == 0u;
        assert r.gen_uint_range(12u, 13u) == 12u;
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(target_os = "win3"))]
    fn gen_uint_range_fail() {
        rand::rng().gen_uint_range(5u, 2u);
    }

    #[test]
    fn gen_float() {
        let r = rand::rng();
        let a = r.gen_float();
        let b = r.gen_float();
        log(debug, (a, b));
    }

    #[test]
    fn gen_weighted_bool() {
        let r = rand::rng();
        assert r.gen_weighted_bool(0u) == true;
        assert r.gen_weighted_bool(1u) == true;
    }

    #[test]
    fn gen_str() {
        let r = rand::rng();
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        log(debug, r.gen_str(10u));
        assert r.gen_str(0u).len() == 0u;
        assert r.gen_str(10u).len() == 10u;
        assert r.gen_str(16u).len() == 16u;
    }

    #[test]
    fn gen_bytes() {
        let r = rand::rng();
        assert r.gen_bytes(0u).len() == 0u;
        assert r.gen_bytes(10u).len() == 10u;
        assert r.gen_bytes(16u).len() == 16u;
    }

    #[test]
    fn choose() {
        let r = rand::rng();
        assert r.choose([1, 1, 1]) == 1;
    }

    #[test]
    fn choose_option() {
        let r = rand::rng();
        assert r.choose_option([]) == none::<int>;
        assert r.choose_option([1, 1, 1]) == some(1);
    }

    #[test]
    fn choose_weighted() {
        let r = rand::rng();
        assert r.choose_weighted([{weight: 1u, item: 42}]) == 42;
        assert r.choose_weighted([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == 43;
    }

    #[test]
    fn choose_weighted_option() {
        let r = rand::rng();
        assert r.choose_weighted_option([{weight: 1u, item: 42}]) == some(42);
        assert r.choose_weighted_option([
            {weight: 0u, item: 42},
            {weight: 1u, item: 43}
        ]) == some(43);
        assert r.choose_weighted_option([]) == none::<int>;
    }

    #[test]
    fn weighted_vec() {
        let r = rand::rng();
        let empty: [int] = [];
        assert r.weighted_vec([]) == empty;
        assert r.weighted_vec([
            {weight: 0u, item: 3u},
            {weight: 1u, item: 2u},
            {weight: 2u, item: 1u}
        ]) == [2u, 1u, 1u];
    }

    #[test]
    fn shuffle() {
        let r = rand::rng();
        let empty: [int] = [];
        assert r.shuffle([]) == empty;
        assert r.shuffle([1, 1, 1]) == [1, 1, 1];
    }
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>


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

//! SIMD vectors.
//!
//! These types can be used for accessing basic SIMD operations. Each of them
//! implements the standard arithmetic operator traits (Add, Sub, Mul, Div,
//! Rem, Shl, Shr) through compiler magic, rather than explicitly. Currently
//! comparison operators are not implemented. To use SSE3+, you must enable
//! the features, like `-C target-feature=sse3,sse4.1,sse4.2`, or a more
//! specific `target-cpu`. No other SIMD intrinsics or high-level wrappers are
//! provided beyond this module.
//!
//! ```rust
//! #[allow(experimental)];
//!
//! fn main() {
//!     use std::simd::f32x4;
//!     let a = f32x4(40.0, 41.0, 42.0, 43.0);
//!     let b = f32x4(1.0, 1.1, 3.4, 9.8);
//!     println!("{}", a + b);
//! }
//! ```
//!
//! ## Stability Note
//!
//! These are all experimental. The inferface may change entirely, without
//! warning.

#![allow(non_camel_case_types)]
#![allow(missing_doc)]

#[experimental]
#[simd]
pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
                 pub i8, pub i8, pub i8, pub i8,
                 pub i8, pub i8, pub i8, pub i8,
                 pub i8, pub i8, pub i8, pub i8);

#[experimental]
#[simd]
pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
                 pub i16, pub i16, pub i16, pub i16);

#[experimental]
#[simd]
pub struct i32x4(pub i32, pub i32, pub i32, pub i32);

#[experimental]
#[simd]
pub struct i64x2(pub i64, pub i64);

#[experimental]
#[simd]
pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
                 pub u8, pub u8, pub u8, pub u8,
                 pub u8, pub u8, pub u8, pub u8,
                 pub u8, pub u8, pub u8, pub u8);

#[experimental]
#[simd]
pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
                 pub u16, pub u16, pub u16, pub u16);

#[experimental]
#[simd]
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);

#[experimental]
#[simd]
pub struct u64x2(pub u64, pub u64);

#[experimental]
#[simd]
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);

#[experimental]
#[simd]
pub struct f64x2(pub f64, pub f64);
<commit_msg>core: Derive Show on SIMD types<commit_after>// Copyright 2013 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.

//! SIMD vectors.
//!
//! These types can be used for accessing basic SIMD operations. Each of them
//! implements the standard arithmetic operator traits (Add, Sub, Mul, Div,
//! Rem, Shl, Shr) through compiler magic, rather than explicitly. Currently
//! comparison operators are not implemented. To use SSE3+, you must enable
//! the features, like `-C target-feature=sse3,sse4.1,sse4.2`, or a more
//! specific `target-cpu`. No other SIMD intrinsics or high-level wrappers are
//! provided beyond this module.
//!
//! ```rust
//! #[allow(experimental)];
//!
//! fn main() {
//!     use std::simd::f32x4;
//!     let a = f32x4(40.0, 41.0, 42.0, 43.0);
//!     let b = f32x4(1.0, 1.1, 3.4, 9.8);
//!     println!("{}", a + b);
//! }
//! ```
//!
//! ## Stability Note
//!
//! These are all experimental. The inferface may change entirely, without
//! warning.

#![allow(non_camel_case_types)]
#![allow(missing_doc)]

#[experimental]
#[simd]
#[deriving(Show)]
pub struct i8x16(pub i8, pub i8, pub i8, pub i8,
                 pub i8, pub i8, pub i8, pub i8,
                 pub i8, pub i8, pub i8, pub i8,
                 pub i8, pub i8, pub i8, pub i8);

#[experimental]
#[simd]
#[deriving(Show)]
pub struct i16x8(pub i16, pub i16, pub i16, pub i16,
                 pub i16, pub i16, pub i16, pub i16);

#[experimental]
#[simd]
#[deriving(Show)]
pub struct i32x4(pub i32, pub i32, pub i32, pub i32);

#[experimental]
#[simd]
#[deriving(Show)]
pub struct i64x2(pub i64, pub i64);

#[experimental]
#[simd]
#[deriving(Show)]
pub struct u8x16(pub u8, pub u8, pub u8, pub u8,
                 pub u8, pub u8, pub u8, pub u8,
                 pub u8, pub u8, pub u8, pub u8,
                 pub u8, pub u8, pub u8, pub u8);

#[experimental]
#[simd]
#[deriving(Show)]
pub struct u16x8(pub u16, pub u16, pub u16, pub u16,
                 pub u16, pub u16, pub u16, pub u16);

#[experimental]
#[simd]
#[deriving(Show)]
pub struct u32x4(pub u32, pub u32, pub u32, pub u32);

#[experimental]
#[simd]
#[deriving(Show)]
pub struct u64x2(pub u64, pub u64);

#[experimental]
#[simd]
#[deriving(Show)]
pub struct f32x4(pub f32, pub f32, pub f32, pub f32);

#[experimental]
#[simd]
#[deriving(Show)]
pub struct f64x2(pub f64, pub f64);
<|endoftext|>