<commit_before>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

#![feature(conservative_impl_trait, plugin, proc_macro)]
#![plugin(tarpc_plugins)]

extern crate bincode;
extern crate env_logger;
extern crate futures;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate tarpc;
extern crate tokio_core;
extern crate tokio_service;

use bincode::serde::DeserializeError;
use futures::Future;
use std::io;
use std::net::{SocketAddr, ToSocketAddrs};
use std::thread;
use tarpc::WireError;
use tarpc::future::Connect;
use tarpc::util::FirstSocketAddr;
use tarpc::util::Never;
use tokio_core::reactor::{Handle, Remote};
use tokio_service::Service;

#[derive(Debug, Serialize, Deserialize)]
enum Request {
    Hello(String),
}

#[derive(Debug, Serialize, Deserialize)]
enum Response {
    Hello(String),
}

#[derive(Debug, Serialize, Deserialize)]
enum Error {
    Hello(Never),
}

/// Defines the `Future` RPC service. Implementors must be `Clone`, `Send`, and `'static`,
/// as required by `tokio_proto::NewService`. This is required so that the service can be used
/// to respond to multiple requests concurrently.
pub trait FutureService: Send + Clone + 'static {
    type HelloFut: Future<Item = String, Error = Never>;
    fn hello(&self, name: String) -> Self::HelloFut;
}

/// Provides a function for starting the service. This is a separate trait from
/// `FutureService` to prevent collisions with the names of RPCs.
pub trait FutureServiceExt: FutureService {
    fn listen(self, addr: SocketAddr) -> tarpc::ListenFuture {
        let (tx, rx) = futures::oneshot();
        tarpc::REMOTE.spawn(move |handle| Ok(tx.complete(Self::listen_with(self, addr, handle.clone()))));
        tarpc::ListenFuture::from_oneshot(rx)
    }

    /// Spawns the service, binding to the given address and running on the default tokio `Loop`.
    fn listen_with(self, addr: SocketAddr, handle: Handle) -> io::Result<SocketAddr> {
        return tarpc::listen_with(addr, move || Ok(AsyncServer(self.clone())), handle);

        #[derive(Clone, Debug)]
        struct AsyncServer<S>(S);

        type Fut = futures::Finished<tarpc::Response<Response, Error>, io::Error>;

        enum FutureReply<S: FutureService> {
            DeserializeError(Fut),
            Hello(futures::Then<S::HelloFut, Fut, fn(Result<String, Never>) -> Fut>),
        }

        impl<S: FutureService> Future for FutureReply<S> {
            type Item = tarpc::Response<Response, Error>;
            type Error = io::Error;

            fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
                match *self {
                    FutureReply::DeserializeError(ref mut future) => future.poll(),
                    FutureReply::Hello(ref mut future) => future.poll(),
                }
            }
        }

        impl<S> Service for AsyncServer<S>
            where S: FutureService
        {
            type Request = Result<Request, DeserializeError>;
            type Response = tarpc::Response<Response, Error>;
            type Error = io::Error;
            type Future = FutureReply<S>;

            fn call(&self, request: Self::Request) -> Self::Future {
                let request = match request {
                    Ok(request) => request,
                    Err(deserialize_err) => {
                        let err = Err(WireError::ServerDeserialize(deserialize_err.to_string()));
                        return FutureReply::DeserializeError(futures::finished(err));
                    }
                };

                match request {
                    Request::Hello(name) => {
                        fn wrap(response: Result<String, Never>) -> Fut {
                            let fut = response.map(Response::Hello)
                                .map_err(|error| WireError::App(Error::Hello(error)));
                            futures::finished(fut)
                        }
                        return FutureReply::Hello(self.0.hello(name).then(wrap));
                    }
                }
            }
        }
    }
}

/// Defines the blocking RPC service. Must be `Clone`, `Send`, and `'static`,
/// as required by `tokio_proto::NewService`. This is required so that the service can be used
/// to respond to multiple requests concurrently.
pub trait SyncService: Send + Clone + 'static {
    fn hello(&self, name: String) -> Result<String, Never>;
}

/// Provides a function for starting the service. This is a separate trait from
/// `SyncService` to prevent collisions with the names of RPCs.
pub trait SyncServiceExt: SyncService {
    fn listen<L>(self, addr: L) -> io::Result<SocketAddr>
        where L: ToSocketAddrs
    {
        let addr = addr.try_first_socket_addr()?;
        let (tx, rx) = futures::oneshot();
        tarpc::REMOTE.spawn(move |handle| {
            Ok(tx.complete(Self::listen_with(self, addr, handle.clone())))
        });
        tarpc::ListenFuture::from_oneshot(rx).wait()
    }

    /// Spawns the service, binding to the given address and running on
    /// the default tokio `Loop`.
    fn listen_with<L>(self, addr: L, handle: Handle) -> io::Result<SocketAddr>
        where L: ToSocketAddrs
    {
        let service = SyncServer { service: self };
        return service.listen_with(addr.try_first_socket_addr()?, handle);

        #[derive(Clone)]
        struct SyncServer<S> {
            service: S,
        }

        impl<S> FutureService for SyncServer<S>
            where S: SyncService
        {
            type HelloFut = futures::Flatten<futures::MapErr<futures::Oneshot<futures::Done<String, Never>>, fn(futures::Canceled) -> Never>>;

            fn hello(&self, name: String) -> Self::HelloFut {
                fn unimplemented(_: futures::Canceled) -> Never {
                    unimplemented!()
                }

                let (complete, promise) = futures::oneshot();
                let service = self.clone();
                const UNIMPLEMENTED: fn(futures::Canceled) -> Never = unimplemented;
                thread::spawn(move || {
                    let reply = SyncService::hello(&service.service, name);
                    complete.complete(futures::IntoFuture::into_future(reply));
                });
                promise.map_err(UNIMPLEMENTED).flatten()
            }
        }
    }
}
impl<A> FutureServiceExt for A where A: FutureService {}
impl<S> SyncServiceExt for S where S: SyncService {}

type Client = tarpc::Client<Request, Response, Error>;

/// Implementation detail: Pending connection.
pub struct ConnectFuture<T> {
    inner: futures::Map<tarpc::ConnectFuture<Request, Response, Error>, fn(Client) -> T>,
}

impl<T> Future for ConnectFuture<T> {
    type Item = T;
    type Error = io::Error;

    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.inner.poll()
    }
}

/// Implementation detail: Pending connection.
pub struct ConnectWithFuture<'a, T> {
    inner: futures::Map<tarpc::ConnectWithFuture<'a, Request, Response, Error>, fn(Client) -> T>,
}

impl<'a, T> Future for ConnectWithFuture<'a, T> {
    type Item = T;
    type Error = io::Error;
    fn poll(&mut self) -> futures::Poll<Self::Item, Self::Error> {
        self.inner.poll()
    }
}

/// The client stub that makes RPC calls to the server. Exposes a Future interface.
#[derive(Debug)]
pub struct FutureClient(Client);

impl<'a> tarpc::future::Connect<'a> for FutureClient {
    type ConnectFut = ConnectFuture<Self>;
    type ConnectWithFut = ConnectWithFuture<'a, Self>;

    fn connect_remotely(addr: &SocketAddr, remote: &Remote) -> Self::ConnectFut {
        let client = Client::connect_remotely(addr, remote);
        ConnectFuture { inner: client.map(FutureClient) }
    }

    fn connect_with(addr: &SocketAddr, handle: &'a Handle) -> Self::ConnectWithFut {
        let client = Client::connect_with(addr, handle);
        ConnectWithFuture { inner: client.map(FutureClient) }
    }
}

impl FutureClient {
    pub fn hello(&self, name: String)
        -> impl Future<Item = String, Error = tarpc::Error<Never>> + 'static
    {
        let request = Request::Hello(name);

        self.0.call(request).then(move |msg| {
            match msg? {
                Ok(Response::Hello(msg)) => Ok(msg),
                Err(err) => {
                    Err(match err {
                        tarpc::Error::App(Error::Hello(err)) => tarpc::Error::App(err),
                        tarpc::Error::ServerDeserialize(err) => {
                            tarpc::Error::ServerDeserialize(err)
                        }
                        tarpc::Error::ServerSerialize(err) => tarpc::Error::ServerSerialize(err),
                        tarpc::Error::ClientDeserialize(err) => {
                            tarpc::Error::ClientDeserialize(err)
                        }
                        tarpc::Error::ClientSerialize(err) => tarpc::Error::ClientSerialize(err),
                        tarpc::Error::Io(error) => tarpc::Error::Io(error),
                    })
                }
            }
        })
    }
}

#[derive(Clone)]
struct HelloServer;

impl SyncService for HelloServer {
    fn hello(&self, name: String) -> Result<String, Never> {
        info!("Got request: {}", name);
        Ok(format!("Hello, {}!", name))
    }
}

fn main() {
    let _ = env_logger::init();
    let mut core = tokio_core::reactor::Core::new().unwrap();
    let addr = HelloServer.listen("localhost:10000").unwrap();
    let f = FutureClient::connect(&addr)
        .map_err(tarpc::Error::from)
        .and_then(|client| {
            let resp1 = client.hello("Mom".to_string());
            info!("Sent first request.");

            let resp2 = client.hello("Dad".to_string());
            info!("Sent second request.");

            futures::collect(vec![resp1, resp2])
        })
        .map(|responses| {
            for resp in responses {
                println!("{}", resp);
            }
        });
    core.run(f).unwrap();
}
<commit_msg>Cut down size of readme_expanded.<commit_after>// Copyright 2016 Google Inc. All Rights Reserved.
//
// Licensed under the MIT License, <LICENSE or http://opensource.org/licenses/MIT>.
// This file may not be copied, modified, or distributed except according to those terms.

#![feature(conservative_impl_trait, plugin, proc_macro)]
#![plugin(tarpc_plugins)]

extern crate bincode;
extern crate env_logger;
extern crate futures;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate tarpc;
extern crate tokio_core;
extern crate tokio_service;

use bincode::serde::DeserializeError;
use futures::{Future, IntoFuture};
use std::io;
use std::net::SocketAddr;
use tarpc::future::Connect;
use tarpc::util::FirstSocketAddr;
use tarpc::util::Never;
use tokio_service::Service;

#[derive(Clone, Copy)]
struct HelloServer;

impl HelloServer {
    fn listen(addr: SocketAddr) -> impl Future<Item=SocketAddr, Error=io::Error> {
        let (tx, rx) = futures::oneshot();
        tarpc::REMOTE.spawn(move |handle| {
            Ok(tx.complete(tarpc::listen_with(addr, move || Ok(HelloServer), handle.clone())))
        });
        rx.map_err(|e| panic!(e)).and_then(|result| result)
    }
}

impl Service for HelloServer {
    type Request = Result<String, DeserializeError>;
    type Response = tarpc::Response<String, Never>;
    type Error = io::Error;
    type Future = Box<Future<Item = tarpc::Response<String, Never>, Error = io::Error>>;

    fn call(&self, request: Self::Request) -> Self::Future {
        Ok(Ok(format!("Hello, {}!", request.unwrap()))).into_future().boxed()
    }
}

/// The client stub that makes RPC calls to the server. Exposes a Future interface.
#[derive(Debug)]
pub struct FutureClient(tarpc::Client<String, String, Never>);

impl FutureClient {
    fn connect(addr: &SocketAddr) -> impl Future<Item = FutureClient, Error = io::Error> {
        tarpc::Client::connect_remotely(addr, &tarpc::REMOTE).map(FutureClient)
    }

    pub fn hello(&self, name: String)
        -> impl Future<Item = String, Error = tarpc::Error<Never>> + 'static
    {
        self.0.call(name).then(|msg| msg.unwrap())
    }
}

fn main() {
    let _ = env_logger::init();
    let mut core = tokio_core::reactor::Core::new().unwrap();
    let addr = HelloServer::listen("localhost:10000".first_socket_addr()).wait().unwrap();
    let f = FutureClient::connect(&addr)
        .map_err(tarpc::Error::from)
        .and_then(|client| {
            let resp1 = client.hello("Mom".to_string());
            info!("Sent first request.");

            let resp2 = client.hello("Dad".to_string());
            info!("Sent second request.");

            futures::collect(vec![resp1, resp2])
        })
        .map(|responses| {
            for resp in responses {
                println!("{}", resp);
            }
        });
    core.run(f).unwrap();
}
<|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 api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};

//TODO: gather real-world statistics on the bin usage in order to assist the decision
// on where to place the size thresholds.

const NUM_BINS: usize = 3;
/// The minimum number of pixels on each side that we require for rects to be classified as
/// particular bin of freelists.
const MIN_RECT_AXIS_SIZES: [i32; NUM_BINS] = [1, 16, 32];

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
struct FreeListBin(u8);

#[derive(Debug, Clone, Copy)]
struct FreeListIndex(usize);

impl FreeListBin {
    fn for_size(size: &DeviceIntSize) -> Self {
        MIN_RECT_AXIS_SIZES
            .iter()
            .enumerate()
            .rev()
            .find(|(_, &min_size)| min_size <= size.width && min_size <= size.height)
            .map(|(id, _)| FreeListBin(id as u8))
            .expect("Unable to find a bin!")
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct FreeRectSlice(pub u32);

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct FreeRect {
    slice: FreeRectSlice,
    rect: DeviceIntRect,
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct FreeRectSize {
    width: i16,
    height: i16,
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct Bin {
    // Store sizes with fewer bits per item and in a separate array to speed up
    // the search.
    sizes: Vec<FreeRectSize>,
    rects: Vec<FreeRect>,
}

/// A texture allocator using the guillotine algorithm.
///
/// See sections 2.2 and 2.2.5 in "A Thousand Ways to Pack the Bin - A Practical Approach to Two-
/// Dimensional Rectangle Bin Packing":
///
///    http://clb.demon.fi/files/RectangleBinPack.pdf
///
/// This approach was chosen because of its simplicity and good performance.
///
/// Note: the allocations are spread across multiple textures, and also are binned
/// orthogonally in order to speed up the search.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct GuillotineAllocator {
    bins: [Bin; NUM_BINS],
}

impl GuillotineAllocator {
    pub fn new(initial_size: Option<DeviceIntSize>) -> Self {
        let mut allocator = GuillotineAllocator {
            bins: [
                Bin { rects: Vec::new(), sizes: Vec::new() },
                Bin { rects: Vec::new(), sizes: Vec::new() },
                Bin { rects: Vec::new(), sizes: Vec::new() },
            ],
        };

        if let Some(initial_size) = initial_size {
            allocator.push(
                FreeRectSlice(0),
                initial_size.into(),
            );
        }

        allocator
    }

    fn push(&mut self, slice: FreeRectSlice, rect: DeviceIntRect) {
        let id = FreeListBin::for_size(&rect.size()).0 as usize;
        self.bins[id].rects.push(FreeRect {
            slice,
            rect,
        });
        self.bins[id].sizes.push(FreeRectSize {
            width: rect.width() as i16,
            height: rect.height() as i16,
        });
    }

    /// Find a suitable rect in the free list. We choose the first fit.
    fn find_index_of_best_rect(
        &self,
        requested_dimensions: &DeviceIntSize,
    ) -> Option<(FreeListBin, FreeListIndex)> {

        let start_bin = FreeListBin::for_size(&requested_dimensions);

        let w = requested_dimensions.width as i16;
        let h = requested_dimensions.height as i16;
        (start_bin.0 .. NUM_BINS as u8)
            .find_map(|id| {
                self.bins[id as usize].sizes
                    .iter()
                    .position(|candidate| w <= candidate.width && h <= candidate.height)
                    .map(|index| (FreeListBin(id), FreeListIndex(index)))
            })
    }

    // Split that results in the single largest area (Min Area Split Rule, MINAS).
    fn split_guillotine(&mut self, chosen: &FreeRect, requested_dimensions: &DeviceIntSize) {
        let candidate_free_rect_to_right = DeviceIntRect::from_origin_and_size(
            DeviceIntPoint::new(
                chosen.rect.min.x + requested_dimensions.width,
                chosen.rect.min.y,
            ),
            DeviceIntSize::new(
                chosen.rect.width() - requested_dimensions.width,
                requested_dimensions.height,
            ),
        );
        let candidate_free_rect_to_bottom = DeviceIntRect::from_origin_and_size(
            DeviceIntPoint::new(
                chosen.rect.min.x,
                chosen.rect.min.y + requested_dimensions.height,
            ),
            DeviceIntSize::new(
                requested_dimensions.width,
                chosen.rect.height() - requested_dimensions.height,
            ),
        );

        // Guillotine the rectangle.
        let new_free_rect_to_right;
        let new_free_rect_to_bottom;
        if candidate_free_rect_to_right.area() > candidate_free_rect_to_bottom.area() {
            new_free_rect_to_right = DeviceIntRect::from_origin_and_size(
                candidate_free_rect_to_right.min,
                DeviceIntSize::new(
                    candidate_free_rect_to_right.width(),
                    chosen.rect.height(),
                ),
            );
            new_free_rect_to_bottom = candidate_free_rect_to_bottom
        } else {
            new_free_rect_to_right = candidate_free_rect_to_right;
            new_free_rect_to_bottom = DeviceIntRect::from_origin_and_size(
                candidate_free_rect_to_bottom.min,
                DeviceIntSize::new(
                    chosen.rect.width(),
                    candidate_free_rect_to_bottom.height(),
                ),
            )
        }

        // Add the guillotined rects back to the free list.
        if !new_free_rect_to_right.is_empty() {
            self.push(chosen.slice, new_free_rect_to_right);
        }
        if !new_free_rect_to_bottom.is_empty() {
            self.push(chosen.slice, new_free_rect_to_bottom);
        }
    }

    pub fn allocate(
        &mut self, requested_dimensions: &DeviceIntSize
    ) -> Option<(FreeRectSlice, DeviceIntPoint)> {
        let mut requested_dimensions = *requested_dimensions;
        // Round up the size to a multiple of 8. This reduces the fragmentation
        // of the atlas.
        requested_dimensions.width = (requested_dimensions.width + 7) & !7;
        requested_dimensions.height = (requested_dimensions.height + 7) & !7;

        if requested_dimensions.width == 0 || requested_dimensions.height == 0 {
            return Some((FreeRectSlice(0), DeviceIntPoint::new(0, 0)));
        }

        let (bin, index) = self.find_index_of_best_rect(&requested_dimensions)?;

        // Remove the rect from the free list and decide how to guillotine it.
        let chosen = self.bins[bin.0 as usize].rects.swap_remove(index.0);
        self.bins[bin.0 as usize].sizes.swap_remove(index.0);
        self.split_guillotine(&chosen, &requested_dimensions);

        // Return the result.
        Some((chosen.slice, chosen.rect.min))
    }

    /// Add a new slice to the allocator, and immediately allocate a rect from it.
    pub fn extend(
        &mut self,
        slice: FreeRectSlice,
        total_size: DeviceIntSize,
        requested_dimensions: DeviceIntSize,
    ) {
        self.split_guillotine(
            &FreeRect { slice, rect: total_size.into() },
            &requested_dimensions
        );
    }
}

#[cfg(test)]
fn random_fill(count: usize, texture_size: i32) -> f32 {
    use rand::{thread_rng, Rng};

    let total_rect = DeviceIntRect::from_size(
        DeviceIntSize::new(texture_size, texture_size),
    );
    let mut rng = thread_rng();
    let mut allocator = GuillotineAllocator::new(None);

    // check for empty allocation
    assert_eq!(
        allocator.allocate(&DeviceIntSize::new(0, 12)),
        Some((FreeRectSlice(0), DeviceIntPoint::zero())),
    );

    let mut slices: Vec<Vec<DeviceIntRect>> = Vec::new();
    let mut requested_area = 0f32;
    // fill up the allocator
    for _ in 0 .. count {
        let size = DeviceIntSize::new(
            rng.gen_range(1, texture_size),
            rng.gen_range(1, texture_size),
        );
        requested_area += size.area() as f32;

        match allocator.allocate(&size) {
            Some((slice, origin)) => {
                let rect = DeviceIntRect::from_origin_and_size(origin, size);
                assert_eq!(None, slices[slice.0 as usize].iter().find(|r| r.intersects(&rect)));
                assert!(total_rect.contains_box(&rect));
                slices[slice.0 as usize].push(rect);
            }
            None => {
                allocator.extend(FreeRectSlice(slices.len() as u32), total_rect.size(), size);
                let rect = DeviceIntRect::from_size(size);
                slices.push(vec![rect]);
            }
        }
    }
    // validate the free rects
    for (i, bin) in allocator.bins.iter().enumerate() {
        for fr in &bin.rects {
            assert_eq!(FreeListBin(i as u8), FreeListBin::for_size(&fr.rect.size()));
            assert_eq!(None, slices[fr.slice.0 as usize].iter().find(|r| r.intersects(&fr.rect)));
            assert!(total_rect.contains_box(&fr.rect));
            slices[fr.slice.0 as usize].push(fr.rect);
        }
    }

    let allocated_area = slices.len() as f32 * (texture_size * texture_size) as f32;
    requested_area / allocated_area
}

#[test]
fn test_small() {
    random_fill(100, 100);
}

#[test]
fn test_large() {
    random_fill(1000, 10000);
}
<commit_msg>Auto merge of #4721 - moz-gfx:github-sync, r=auto<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 api::units::{DeviceIntPoint, DeviceIntRect, DeviceIntSize};

//TODO: gather real-world statistics on the bin usage in order to assist the decision
// on where to place the size thresholds.

const NUM_BINS: usize = 3;
/// The minimum number of pixels on each side that we require for rects to be classified as
/// particular bin of freelists.
const MIN_RECT_AXIS_SIZES: [i32; NUM_BINS] = [1, 16, 32];

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
struct FreeListBin(u8);

#[derive(Debug, Clone, Copy)]
struct FreeListIndex(usize);

impl FreeListBin {
    fn for_size(size: &DeviceIntSize) -> Self {
        MIN_RECT_AXIS_SIZES
            .iter()
            .enumerate()
            .rev()
            .find(|(_, &min_size)| min_size <= size.width && min_size <= size.height)
            .map(|(id, _)| FreeListBin(id as u8))
            .unwrap_or_else(|| panic!("Unable to find a bin for {:?}!", size))
    }
}

#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct FreeRectSlice(pub u32);

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct FreeRect {
    slice: FreeRectSlice,
    rect: DeviceIntRect,
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct FreeRectSize {
    width: i16,
    height: i16,
}

#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
struct Bin {
    // Store sizes with fewer bits per item and in a separate array to speed up
    // the search.
    sizes: Vec<FreeRectSize>,
    rects: Vec<FreeRect>,
}

/// A texture allocator using the guillotine algorithm.
///
/// See sections 2.2 and 2.2.5 in "A Thousand Ways to Pack the Bin - A Practical Approach to Two-
/// Dimensional Rectangle Bin Packing":
///
///    http://clb.demon.fi/files/RectangleBinPack.pdf
///
/// This approach was chosen because of its simplicity and good performance.
///
/// Note: the allocations are spread across multiple textures, and also are binned
/// orthogonally in order to speed up the search.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct GuillotineAllocator {
    bins: [Bin; NUM_BINS],
}

impl GuillotineAllocator {
    pub fn new(initial_size: Option<DeviceIntSize>) -> Self {
        let mut allocator = GuillotineAllocator {
            bins: [
                Bin { rects: Vec::new(), sizes: Vec::new() },
                Bin { rects: Vec::new(), sizes: Vec::new() },
                Bin { rects: Vec::new(), sizes: Vec::new() },
            ],
        };

        if let Some(initial_size) = initial_size {
            allocator.push(
                FreeRectSlice(0),
                initial_size.into(),
            );
        }

        allocator
    }

    fn push(&mut self, slice: FreeRectSlice, rect: DeviceIntRect) {
        let id = FreeListBin::for_size(&rect.size()).0 as usize;
        self.bins[id].rects.push(FreeRect {
            slice,
            rect,
        });
        self.bins[id].sizes.push(FreeRectSize {
            width: rect.width() as i16,
            height: rect.height() as i16,
        });
    }

    /// Find a suitable rect in the free list. We choose the first fit.
    fn find_index_of_best_rect(
        &self,
        requested_dimensions: &DeviceIntSize,
    ) -> Option<(FreeListBin, FreeListIndex)> {

        let start_bin = FreeListBin::for_size(&requested_dimensions);

        let w = requested_dimensions.width as i16;
        let h = requested_dimensions.height as i16;
        (start_bin.0 .. NUM_BINS as u8)
            .find_map(|id| {
                self.bins[id as usize].sizes
                    .iter()
                    .position(|candidate| w <= candidate.width && h <= candidate.height)
                    .map(|index| (FreeListBin(id), FreeListIndex(index)))
            })
    }

    // Split that results in the single largest area (Min Area Split Rule, MINAS).
    fn split_guillotine(&mut self, chosen: &FreeRect, requested_dimensions: &DeviceIntSize) {
        let candidate_free_rect_to_right = DeviceIntRect::from_origin_and_size(
            DeviceIntPoint::new(
                chosen.rect.min.x + requested_dimensions.width,
                chosen.rect.min.y,
            ),
            DeviceIntSize::new(
                chosen.rect.width() - requested_dimensions.width,
                requested_dimensions.height,
            ),
        );
        let candidate_free_rect_to_bottom = DeviceIntRect::from_origin_and_size(
            DeviceIntPoint::new(
                chosen.rect.min.x,
                chosen.rect.min.y + requested_dimensions.height,
            ),
            DeviceIntSize::new(
                requested_dimensions.width,
                chosen.rect.height() - requested_dimensions.height,
            ),
        );

        // Guillotine the rectangle.
        let new_free_rect_to_right;
        let new_free_rect_to_bottom;
        if candidate_free_rect_to_right.area() > candidate_free_rect_to_bottom.area() {
            new_free_rect_to_right = DeviceIntRect::from_origin_and_size(
                candidate_free_rect_to_right.min,
                DeviceIntSize::new(
                    candidate_free_rect_to_right.width(),
                    chosen.rect.height(),
                ),
            );
            new_free_rect_to_bottom = candidate_free_rect_to_bottom
        } else {
            new_free_rect_to_right = candidate_free_rect_to_right;
            new_free_rect_to_bottom = DeviceIntRect::from_origin_and_size(
                candidate_free_rect_to_bottom.min,
                DeviceIntSize::new(
                    chosen.rect.width(),
                    candidate_free_rect_to_bottom.height(),
                ),
            )
        }

        // Add the guillotined rects back to the free list.
        if !new_free_rect_to_right.is_empty() {
            self.push(chosen.slice, new_free_rect_to_right);
        }
        if !new_free_rect_to_bottom.is_empty() {
            self.push(chosen.slice, new_free_rect_to_bottom);
        }
    }

    pub fn allocate(
        &mut self, requested_dimensions: &DeviceIntSize
    ) -> Option<(FreeRectSlice, DeviceIntPoint)> {
        let mut requested_dimensions = *requested_dimensions;
        // Round up the size to a multiple of 8. This reduces the fragmentation
        // of the atlas.
        requested_dimensions.width = (requested_dimensions.width + 7) & !7;
        requested_dimensions.height = (requested_dimensions.height + 7) & !7;

        if requested_dimensions.width == 0 || requested_dimensions.height == 0 {
            return Some((FreeRectSlice(0), DeviceIntPoint::new(0, 0)));
        }

        let (bin, index) = self.find_index_of_best_rect(&requested_dimensions)?;

        // Remove the rect from the free list and decide how to guillotine it.
        let chosen = self.bins[bin.0 as usize].rects.swap_remove(index.0);
        self.bins[bin.0 as usize].sizes.swap_remove(index.0);
        self.split_guillotine(&chosen, &requested_dimensions);

        // Return the result.
        Some((chosen.slice, chosen.rect.min))
    }

    /// Add a new slice to the allocator, and immediately allocate a rect from it.
    pub fn extend(
        &mut self,
        slice: FreeRectSlice,
        total_size: DeviceIntSize,
        requested_dimensions: DeviceIntSize,
    ) {
        self.split_guillotine(
            &FreeRect { slice, rect: total_size.into() },
            &requested_dimensions
        );
    }
}

#[cfg(test)]
fn random_fill(count: usize, texture_size: i32) -> f32 {
    use rand::{thread_rng, Rng};

    let total_rect = DeviceIntRect::from_size(
        DeviceIntSize::new(texture_size, texture_size),
    );
    let mut rng = thread_rng();
    let mut allocator = GuillotineAllocator::new(None);

    // check for empty allocation
    assert_eq!(
        allocator.allocate(&DeviceIntSize::new(0, 12)),
        Some((FreeRectSlice(0), DeviceIntPoint::zero())),
    );

    let mut slices: Vec<Vec<DeviceIntRect>> = Vec::new();
    let mut requested_area = 0f32;
    // fill up the allocator
    for _ in 0 .. count {
        let size = DeviceIntSize::new(
            rng.gen_range(1, texture_size),
            rng.gen_range(1, texture_size),
        );
        requested_area += size.area() as f32;

        match allocator.allocate(&size) {
            Some((slice, origin)) => {
                let rect = DeviceIntRect::from_origin_and_size(origin, size);
                assert_eq!(None, slices[slice.0 as usize].iter().find(|r| r.intersects(&rect)));
                assert!(total_rect.contains_box(&rect));
                slices[slice.0 as usize].push(rect);
            }
            None => {
                allocator.extend(FreeRectSlice(slices.len() as u32), total_rect.size(), size);
                let rect = DeviceIntRect::from_size(size);
                slices.push(vec![rect]);
            }
        }
    }
    // validate the free rects
    for (i, bin) in allocator.bins.iter().enumerate() {
        for fr in &bin.rects {
            assert_eq!(FreeListBin(i as u8), FreeListBin::for_size(&fr.rect.size()));
            assert_eq!(None, slices[fr.slice.0 as usize].iter().find(|r| r.intersects(&fr.rect)));
            assert!(total_rect.contains_box(&fr.rect));
            slices[fr.slice.0 as usize].push(fr.rect);
        }
    }

    let allocated_area = slices.len() as f32 * (texture_size * texture_size) as f32;
    requested_area / allocated_area
}

#[test]
fn test_small() {
    random_fill(100, 100);
}

#[test]
fn test_large() {
    random_fill(1000, 10000);
}
<|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::path::PathBuf;

use devicemapper::{DM, DevId, DmFlags, DmResult};

use mnt::get_submounts;
use nix::mount::{MntFlags, umount2};

mod cleanup_errors {
    use mnt;
    use nix;

    error_chain!{
        foreign_links {
            Mnt(mnt::ParseError);
            Nix(nix::Error);
        }
    }
}

use self::cleanup_errors::{Error, Result, ResultExt};

/// Attempt to remove all device mapper devices which match the stratis naming convention.
/// FIXME: Current implementation complicated by https://bugzilla.redhat.com/show_bug.cgi?id=1506287
fn dm_stratis_devices_remove() -> Result<()> {

    /// One iteration of removing devicemapper devices
    fn one_iteration(dm: &DM) -> DmResult<(bool, Vec<String>)> {
        let mut progress_made = false;
        let mut remain = Vec::new();

        for d in dm.list_devices()?
                .iter()
                .filter(|d| format!("{}", d.0.as_ref()).starts_with("stratis-1")) {

            match dm.device_remove(&DevId::Name(&d.0), DmFlags::empty()) {
                Ok(_) => progress_made = true,
                Err(_) => remain.push(format!("{}", d.0.as_ref())),
            }
        }
        Ok((progress_made, remain))
    }

    let dm = DM::new().chain_err(|| "Unable to initialize DM")?;

    loop {
        let (progress_made, remain) = one_iteration(&dm)
            .map_err(|e| {
                Error::with_chain(e,
                                  "Error while attempting to remove stratis device mapper devices")}
                )?;

        if !progress_made {
            if remain.len() != 0 {
                bail!("We were unable to remove all stratis device mapper devices {:?}",
                      remain);
            }
            break;
        }
    }

    Ok(())
}

/// Try and un-mount any filesystems that have the name stratis in the mount point, returning
/// immediately on the first one we are unable to unmount.
fn stratis_filesystems_unmount() -> Result<()> {
    || -> Result<()> {
        let mounts = get_submounts(&PathBuf::from("/"))?;
        for m in mounts
                .iter()
                .filter(|m| m.file.to_str().map_or(false, |s| s.contains("stratis"))) {
            umount2(&m.file, MntFlags::MNT_DETACH)?;
        }
        Ok(())
    }()
            .map_err(|e| Error::with_chain(e, "unable to unmount all stratis filesystems"))
}

/// When a unit test panics we can leave the system in an inconsistent state.  This function
/// tries to clean up by un-mounting any mounted file systems which contain the string
/// "stratis_testing" and then it tries to remove any device mapper tables which are also stratis
/// created.
pub fn clean_up() -> Result<()> {
    stratis_filesystems_unmount()?;
    dm_stratis_devices_remove()?;
    Ok(())
}
<commit_msg>Use get_dm() in code for test cleanup<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::panic::catch_unwind;
use std::path::PathBuf;

use mnt::get_submounts;
use nix::mount::{MntFlags, umount2};

use devicemapper::{DevId, DmFlags, DmResult};

use super::super::dm::get_dm;

mod cleanup_errors {
    use mnt;
    use nix;

    error_chain!{
        foreign_links {
            Mnt(mnt::ParseError);
            Nix(nix::Error);
        }
    }
}

use self::cleanup_errors::{Error, Result};

/// Attempt to remove all device mapper devices which match the stratis naming convention.
/// FIXME: Current implementation complicated by https://bugzilla.redhat.com/show_bug.cgi?id=1506287
fn dm_stratis_devices_remove() -> Result<()> {

    /// One iteration of removing devicemapper devices
    fn one_iteration() -> DmResult<(bool, Vec<String>)> {
        let mut progress_made = false;
        let mut remain = Vec::new();

        for d in get_dm()
                .list_devices()?
                .iter()
                .filter(|d| format!("{}", d.0.as_ref()).starts_with("stratis-1")) {

            match get_dm().device_remove(&DevId::Name(&d.0), DmFlags::empty()) {
                Ok(_) => progress_made = true,
                Err(_) => remain.push(format!("{}", d.0.as_ref())),
            }
        }
        Ok((progress_made, remain))
    }

    if catch_unwind(get_dm).is_err() {
        return Err("Unable to initialize DM".into());
    }

    loop {
        let (progress_made, remain) = one_iteration()
            .map_err(|e| {
                Error::with_chain(e,
                                  "Error while attempting to remove stratis device mapper devices")}
                )?;

        if !progress_made {
            if remain.len() != 0 {
                bail!("We were unable to remove all stratis device mapper devices {:?}",
                      remain);
            }
            break;
        }
    }

    Ok(())
}

/// Try and un-mount any filesystems that have the name stratis in the mount point, returning
/// immediately on the first one we are unable to unmount.
fn stratis_filesystems_unmount() -> Result<()> {
    || -> Result<()> {
        let mounts = get_submounts(&PathBuf::from("/"))?;
        for m in mounts
                .iter()
                .filter(|m| m.file.to_str().map_or(false, |s| s.contains("stratis"))) {
            umount2(&m.file, MntFlags::MNT_DETACH)?;
        }
        Ok(())
    }()
            .map_err(|e| Error::with_chain(e, "unable to unmount all stratis filesystems"))
}

/// When a unit test panics we can leave the system in an inconsistent state.  This function
/// tries to clean up by un-mounting any mounted file systems which contain the string
/// "stratis_testing" and then it tries to remove any device mapper tables which are also stratis
/// created.
pub fn clean_up() -> Result<()> {
    stratis_filesystems_unmount()?;
    dm_stratis_devices_remove()?;
    Ok(())
}
<|endoftext|>


<commit_before>extern crate nalgebra as na;

use alga::general::Real;
use na::{Isometry3, Vector3, Unit, UnitQuaternion, Translation3};
use std::error::Error;
use std::fmt;

#[derive(Copy, Debug)]
pub enum JointType<T: Real> {
    /// Fixed joitn
    Fixed,
    /// Rotational joint around axis. angle [rad].
    Rotational { axis: Unit<Vector3<T>> },
    /// Linear joint. angle is length
    Linear { axis: Unit<Vector3<T>> },
}

impl<T> Clone for JointType<T>
    where T: Real
{
    fn clone(&self) -> JointType<T> {
        *self
    }
}

#[derive(Debug)]
pub enum JointError {
    OutOfLimit,
    SizeMisMatch,
}

impl fmt::Display for JointError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            JointError::OutOfLimit => write!(f, "limit over"),
            JointError::SizeMisMatch => write!(f, "size is invalid"),
        }
    }
}

impl Error for JointError {
    fn description(&self) -> &str {
        match *self {
            JointError::OutOfLimit => "limit over",
            JointError::SizeMisMatch => "size is invalid",
        }
    }
}

/// Robot representation with set of LinkedFrames
///
/// This contains multiple LinkedFrame.
/// The frames must be serial without branch.
/// root is the only link which has branch.
#[derive(Debug)]
pub struct RobotFrame<T: Real> {
    pub name: String,
    pub frames: Vec<LinkedFrame<T>>,
    transform: Isometry3<T>,
}

impl<T> RobotFrame<T>
    where T: Real
{
    pub fn new(name: &str, frames: Vec<LinkedFrame<T>>) -> RobotFrame<T> {
        RobotFrame {
            name: name.to_string(),
            frames: frames,
            transform: Isometry3::identity(),
        }
    }
    pub fn calc_link_transforms(&self) -> Vec<Vec<Isometry3<T>>> {
        self.frames
            .iter()
            .map(|ref lf| {
                     lf.calc_link_transforms()
                         .iter()
                         .map(|&tf| self.transform * tf)
                         .collect()
                 })
            .collect()
    }
    pub fn set_transform(&mut self, transform: Isometry3<T>) {
        self.transform = transform;
        for frame in self.frames.iter_mut() {
            frame.transform = self.transform.clone();
        }
    }
    pub fn get_transform(&self) -> Isometry3<T> {
        return self.transform;
    }
}

pub trait KinematicChain<T>
    where T: Real
{
    fn calc_end_transform(&self) -> Isometry3<T>;
    fn set_joint_angles(&mut self, angles: &Vec<T>) -> Result<(), JointError>;
    fn get_joint_angles(&self) -> Vec<T>;
}

/// Set of Joint and Link
///
/// imagine below structure
///
/// `[transform] -> linked_joints([[joint] -> [Link]] -> [[joint] -> [Link]] -> ...)`
///
/// The order must be ordered.
///
/// - start from root link
/// - end with last link
#[derive(Debug)]
pub struct LinkedFrame<T: Real> {
    pub name: String,
    pub linked_joints: Vec<LinkedJoint<T>>,
    pub transform: Isometry3<T>,
}

impl<T> LinkedFrame<T>
    where T: Real
{
    pub fn new(name: &str, linked_joints: Vec<LinkedJoint<T>>) -> LinkedFrame<T> {
        LinkedFrame {
            name: name.to_string(),
            linked_joints: linked_joints,
            transform: Isometry3::identity(),
        }
    }
    /// returns transforms of links
    pub fn calc_link_transforms(&self) -> Vec<Isometry3<T>> {
        self.linked_joints
            .iter()
            .scan(self.transform, |base, ref lj| {
                *base *= lj.calc_transform();
                Some(*base)
            })
            .collect()
    }
    pub fn len(&self) -> usize {
        self.linked_joints.len()
    }
}

impl<T> KinematicChain<T> for LinkedFrame<T>
    where T: Real
{
    fn calc_end_transform(&self) -> Isometry3<T> {
        self.linked_joints
            .iter()
            .fold(self.transform, |trans, ref lj| trans * lj.calc_transform())
    }

    /// if failed, joints angles are non determined,
    fn set_joint_angles(&mut self, angles: &Vec<T>) -> Result<(), JointError> {
        let mut joints_with_angle = self.linked_joints
            .iter_mut()
            .filter(|ref lj| lj.has_joint_angle())
            .collect::<Vec<_>>();
        if joints_with_angle.len() != angles.len() {
            return Err(JointError::SizeMisMatch);
        }
        for (i, lj) in joints_with_angle.iter_mut().enumerate() {
            try!(lj.set_joint_angle(angles[i]));
        }

        Ok(())
    }
    fn get_joint_angles(&self) -> Vec<T> {
        self.linked_joints
            .iter()
            .filter_map(|ref linked_joint| linked_joint.get_joint_angle())
            .collect()
    }
}

/// Joint and Link
///
#[derive(Debug)]
pub struct LinkedJoint<T: Real> {
    pub name: String,
    pub joint: Joint<T>,
    pub transform: Isometry3<T>,
}

impl<T> LinkedJoint<T>
    where T: Real
{
    /// Construct a LinkedJoint from name and joint instance
    ///
    /// You can use LinkedJointBuilder<T> if you want.
    pub fn new(name: &str, joint: Joint<T>) -> LinkedJoint<T> {
        LinkedJoint {
            name: name.to_string(),
            joint: joint,
            transform: Isometry3::identity(),
        }
    }
    pub fn get_joint_name(&self) -> &str {
        &self.joint.name
    }
    pub fn calc_transform(&self) -> Isometry3<T> {
        self.transform * self.joint.calc_transform()
    }
    pub fn set_joint_angle(&mut self, angle: T) -> Result<(), JointError> {
        self.joint.set_angle(angle)
    }
    pub fn get_joint_angle(&self) -> Option<T> {
        self.joint.get_angle()
    }
    pub fn has_joint_angle(&self) -> bool {
        match self.joint.joint_type {
            JointType::Fixed => false,
            _ => true,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Range<T: Real> {
    pub min: T,
    pub max: T,
}

impl<T> Range<T>
    where T: Real
{
    pub fn is_valid(&self, val: T) -> bool {
        val < self.max && val > self.min
    }
}

/// Joint with type
#[derive(Debug)]
pub struct Joint<T: Real> {
    pub name: String,
    pub joint_type: JointType<T>,
    pub angle: T,
    pub limits: Option<Range<T>>,
}

impl<T> Joint<T>
    where T: Real
{
    pub fn new(name: &str, joint_type: JointType<T>) -> Joint<T> {
        Joint {
            name: name.to_string(),
            joint_type: joint_type,
            angle: T::zero(),
            limits: None,
        }
    }
    pub fn set_limits(&mut self, limits: Option<Range<T>>) {
        self.limits = limits;
    }
    pub fn set_angle(&mut self, angle: T) -> Result<(), JointError> {
        match self.joint_type {
            JointType::Fixed => return Err(JointError::OutOfLimit),
            _ => {}
        }
        match self.limits.clone() {
            Some(range) => {
                if !range.is_valid(angle) {
                    return Err(JointError::OutOfLimit);
                }
            }
            None => {}
        }
        self.angle = angle;
        Ok(())
    }
    pub fn get_angle(&self) -> Option<T> {
        match self.joint_type {
            JointType::Fixed => None,
            _ => Some(self.angle),
        }
    }
    pub fn calc_transform(&self) -> Isometry3<T> {
        match self.joint_type {
            JointType::Fixed => Isometry3::identity(),
            JointType::Rotational { axis } => {
                Isometry3::from_parts(Translation3::new(T::zero(), T::zero(), T::zero()),
                                      UnitQuaternion::from_axis_angle(&axis, self.angle))
            }
            JointType::Linear { axis } => {
                Isometry3::from_parts(Translation3::from_vector(&axis.unwrap() * self.angle),
                                      UnitQuaternion::identity())
            }
        }
    }
}

/// Build a LinkedJoint<T>
///
/// # Examples
///
/// ```
/// extern crate nalgebra as na;
/// extern crate nkinematics as nk;
/// let l0 = nk::LinkedJointBuilder::new()
///     .name("link1")
///     .translation(na::Translation3::new(0.0, 0.1, 0.0))
///     .joint("link_pitch", nk::JointType::Rotational{axis: na::Vector3::y_axis()})
///     .finalize();
/// ```
#[derive(Debug)]
pub struct LinkedJointBuilder<T: Real> {
    name: String,
    joint: Joint<T>,
    transform: Isometry3<T>,
}

impl<T> LinkedJointBuilder<T>
    where T: Real
{
    pub fn new() -> LinkedJointBuilder<T> {
        LinkedJointBuilder {
            name: "".to_string(),
            joint: Joint::new("", JointType::Fixed),
            transform: Isometry3::identity(),
        }
    }
    pub fn name(mut self, name: &str) -> LinkedJointBuilder<T> {
        self.name = name.to_string();
        self
    }
    pub fn joint(mut self, name: &str, joint_type: JointType<T>) -> LinkedJointBuilder<T> {
        self.joint = Joint::new(name, joint_type);
        self
    }
    pub fn transform(mut self, transform: Isometry3<T>) -> LinkedJointBuilder<T> {
        self.transform = transform;
        self
    }
    pub fn translation(mut self, translation: Translation3<T>) -> LinkedJointBuilder<T> {
        self.transform.translation = translation;
        self
    }
    pub fn rotation(mut self, rotation: UnitQuaternion<T>) -> LinkedJointBuilder<T> {
        self.transform.rotation = rotation;
        self
    }
    pub fn finalize(self) -> LinkedJoint<T> {
        LinkedJoint {
            name: self.name,
            joint: self.joint,
            transform: self.transform,
        }
    }
}
<commit_msg>Add Clone derive<commit_after>extern crate nalgebra as na;

use alga::general::Real;
use na::{Isometry3, Vector3, Unit, UnitQuaternion, Translation3};
use std::error::Error;
use std::fmt;

#[derive(Copy, Debug, Clone)]
pub enum JointType<T: Real> {
    /// Fixed joitn
    Fixed,
    /// Rotational joint around axis. angle [rad].
    Rotational { axis: Unit<Vector3<T>> },
    /// Linear joint. angle is length
    Linear { axis: Unit<Vector3<T>> },
}

#[derive(Debug, Clone)]
pub enum JointError {
    OutOfLimit,
    SizeMisMatch,
}

impl fmt::Display for JointError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            JointError::OutOfLimit => write!(f, "limit over"),
            JointError::SizeMisMatch => write!(f, "size is invalid"),
        }
    }
}

impl Error for JointError {
    fn description(&self) -> &str {
        match *self {
            JointError::OutOfLimit => "limit over",
            JointError::SizeMisMatch => "size is invalid",
        }
    }
}

/// Robot representation with set of LinkedFrames
///
/// This contains multiple LinkedFrame.
/// The frames must be serial without branch.
/// root is the only link which has branch.
#[derive(Debug, Clone)]
pub struct RobotFrame<T: Real> {
    pub name: String,
    pub frames: Vec<LinkedFrame<T>>,
    transform: Isometry3<T>,
}

impl<T> RobotFrame<T>
    where T: Real
{
    pub fn new(name: &str, frames: Vec<LinkedFrame<T>>) -> RobotFrame<T> {
        RobotFrame {
            name: name.to_string(),
            frames: frames,
            transform: Isometry3::identity(),
        }
    }
    pub fn calc_link_transforms(&self) -> Vec<Vec<Isometry3<T>>> {
        self.frames
            .iter()
            .map(|ref lf| {
                     lf.calc_link_transforms()
                         .iter()
                         .map(|&tf| self.transform * tf)
                         .collect()
                 })
            .collect()
    }
    pub fn set_transform(&mut self, transform: Isometry3<T>) {
        self.transform = transform;
        for frame in self.frames.iter_mut() {
            frame.transform = self.transform * frame.transform;
        }
    }
    pub fn get_transform(&self) -> Isometry3<T> {
        return self.transform;
    }
}

pub trait KinematicChain<T>
    where T: Real
{
    fn calc_end_transform(&self) -> Isometry3<T>;
    fn set_joint_angles(&mut self, angles: &Vec<T>) -> Result<(), JointError>;
    fn get_joint_angles(&self) -> Vec<T>;
}

/// Set of Joint and Link
///
/// imagine below structure
///
/// `[transform] -> linked_joints([[joint] -> [Link]] -> [[joint] -> [Link]] -> ...)`
///
/// The order must be ordered.
///
/// - start from root link
/// - end with last link
#[derive(Debug, Clone)]
pub struct LinkedFrame<T: Real> {
    pub name: String,
    pub linked_joints: Vec<LinkedJoint<T>>,
    pub transform: Isometry3<T>,
}

impl<T> LinkedFrame<T>
    where T: Real
{
    pub fn new(name: &str, linked_joints: Vec<LinkedJoint<T>>) -> LinkedFrame<T> {
        LinkedFrame {
            name: name.to_string(),
            linked_joints: linked_joints,
            transform: Isometry3::identity(),
        }
    }
    /// returns transforms of links
    pub fn calc_link_transforms(&self) -> Vec<Isometry3<T>> {
        self.linked_joints
            .iter()
            .scan(self.transform, |base, ref lj| {
                *base *= lj.calc_transform();
                Some(*base)
            })
            .collect()
    }
    pub fn len(&self) -> usize {
        self.linked_joints.len()
    }
}

impl<T> KinematicChain<T> for LinkedFrame<T>
    where T: Real
{
    fn calc_end_transform(&self) -> Isometry3<T> {
        self.linked_joints
            .iter()
            .fold(self.transform, |trans, ref lj| trans * lj.calc_transform())
    }

    /// if failed, joints angles are non determined,
    fn set_joint_angles(&mut self, angles: &Vec<T>) -> Result<(), JointError> {
        let mut joints_with_angle = self.linked_joints
            .iter_mut()
            .filter(|ref lj| lj.has_joint_angle())
            .collect::<Vec<_>>();
        if joints_with_angle.len() != angles.len() {
            return Err(JointError::SizeMisMatch);
        }
        for (i, lj) in joints_with_angle.iter_mut().enumerate() {
            try!(lj.set_joint_angle(angles[i]));
        }

        Ok(())
    }
    fn get_joint_angles(&self) -> Vec<T> {
        self.linked_joints
            .iter()
            .filter_map(|ref linked_joint| linked_joint.get_joint_angle())
            .collect()
    }
}

/// Joint and Link
///
#[derive(Debug, Clone)]
pub struct LinkedJoint<T: Real> {
    pub name: String,
    pub joint: Joint<T>,
    pub transform: Isometry3<T>,
}

impl<T> LinkedJoint<T>
    where T: Real
{
    /// Construct a LinkedJoint from name and joint instance
    ///
    /// You can use LinkedJointBuilder<T> if you want.
    pub fn new(name: &str, joint: Joint<T>) -> LinkedJoint<T> {
        LinkedJoint {
            name: name.to_string(),
            joint: joint,
            transform: Isometry3::identity(),
        }
    }
    pub fn get_joint_name(&self) -> &str {
        &self.joint.name
    }
    pub fn calc_transform(&self) -> Isometry3<T> {
        self.transform * self.joint.calc_transform()
    }
    pub fn set_joint_angle(&mut self, angle: T) -> Result<(), JointError> {
        self.joint.set_angle(angle)
    }
    pub fn get_joint_angle(&self) -> Option<T> {
        self.joint.get_angle()
    }
    pub fn has_joint_angle(&self) -> bool {
        match self.joint.joint_type {
            JointType::Fixed => false,
            _ => true,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Range<T: Real> {
    pub min: T,
    pub max: T,
}

impl<T> Range<T>
    where T: Real
{
    pub fn is_valid(&self, val: T) -> bool {
        val < self.max && val > self.min
    }
}

/// Joint with type
#[derive(Debug, Clone)]
pub struct Joint<T: Real> {
    pub name: String,
    pub joint_type: JointType<T>,
    pub angle: T,
    pub limits: Option<Range<T>>,
}

impl<T> Joint<T>
    where T: Real
{
    pub fn new(name: &str, joint_type: JointType<T>) -> Joint<T> {
        Joint {
            name: name.to_string(),
            joint_type: joint_type,
            angle: T::zero(),
            limits: None,
        }
    }
    pub fn set_limits(&mut self, limits: Option<Range<T>>) {
        self.limits = limits;
    }
    pub fn set_angle(&mut self, angle: T) -> Result<(), JointError> {
        match self.joint_type {
            JointType::Fixed => return Err(JointError::OutOfLimit),
            _ => {}
        }
        match self.limits.clone() {
            Some(range) => {
                if !range.is_valid(angle) {
                    return Err(JointError::OutOfLimit);
                }
            }
            None => {}
        }
        self.angle = angle;
        Ok(())
    }
    pub fn get_angle(&self) -> Option<T> {
        match self.joint_type {
            JointType::Fixed => None,
            _ => Some(self.angle),
        }
    }
    pub fn calc_transform(&self) -> Isometry3<T> {
        match self.joint_type {
            JointType::Fixed => Isometry3::identity(),
            JointType::Rotational { axis } => {
                Isometry3::from_parts(Translation3::new(T::zero(), T::zero(), T::zero()),
                                      UnitQuaternion::from_axis_angle(&axis, self.angle))
            }
            JointType::Linear { axis } => {
                Isometry3::from_parts(Translation3::from_vector(&axis.unwrap() * self.angle),
                                      UnitQuaternion::identity())
            }
        }
    }
}

/// Build a LinkedJoint<T>
///
/// # Examples
///
/// ```
/// extern crate nalgebra as na;
/// extern crate nkinematics as nk;
/// let l0 = nk::LinkedJointBuilder::new()
///     .name("link1")
///     .translation(na::Translation3::new(0.0, 0.1, 0.0))
///     .joint("link_pitch", nk::JointType::Rotational{axis: na::Vector3::y_axis()})
///     .finalize();
/// println!("{:?}", l0);
/// ```
#[derive(Debug, Clone)]
pub struct LinkedJointBuilder<T: Real> {
    name: String,
    joint: Joint<T>,
    transform: Isometry3<T>,
}

impl<T> LinkedJointBuilder<T>
    where T: Real
{
    pub fn new() -> LinkedJointBuilder<T> {
        LinkedJointBuilder {
            name: "".to_string(),
            joint: Joint::new("", JointType::Fixed),
            transform: Isometry3::identity(),
        }
    }
    pub fn name(mut self, name: &str) -> LinkedJointBuilder<T> {
        self.name = name.to_string();
        self
    }
    pub fn joint(mut self, name: &str, joint_type: JointType<T>) -> LinkedJointBuilder<T> {
        self.joint = Joint::new(name, joint_type);
        self
    }
    pub fn transform(mut self, transform: Isometry3<T>) -> LinkedJointBuilder<T> {
        self.transform = transform;
        self
    }
    pub fn translation(mut self, translation: Translation3<T>) -> LinkedJointBuilder<T> {
        self.transform.translation = translation;
        self
    }
    pub fn rotation(mut self, rotation: UnitQuaternion<T>) -> LinkedJointBuilder<T> {
        self.transform.rotation = rotation;
        self
    }
    pub fn finalize(self) -> LinkedJoint<T> {
        LinkedJoint {
            name: self.name,
            joint: self.joint,
            transform: self.transform,
        }
    }
}
<|endoftext|>


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

extern crate crypto;

use crypto::{ symmetriccipher, buffer, aes, blockmodes };
use crypto::buffer::{ ReadBuffer, WriteBuffer, BufferResult };

use std::rand::{ Rng, OsRng };

// Encrypt a buffer with the given key and iv using
// AES-256/CBC/Pkcs encryption.
fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {

    // Create an encryptor instance of the best performing
    // type available for the platform.
    let mut encryptor = aes::cbc_encryptor(
            aes::KeySize::KeySize256,
            key,
            iv,
            blockmodes::PkcsPadding);

    // Each encryption operation encrypts some data from
    // an input buffer into an output buffer. Those buffers
    // must be instances of RefReaderBuffer and RefWriteBuffer
    // (respectively) which keep track of how much data has been
    // read from or written to them.
    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(data);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    // Each encryption operation will "make progress". "Making progress"
    // is a bit loosely defined, but basically, at the end of each operation
    // either BufferUnderflow or BufferOverflow will be returned (unless
    // there was an error). If the return value is BufferUnderflow, it means
    // that the operation ended while wanting more input data. If the return
    // value is BufferOverflow, it means that the operation ended because it
    // needed more space to output data. As long as the next call to the encryption
    // operation provides the space that was requested (either more input data
    // or more output space), the operation is guaranteed to get closer to
    // completing the full operation - ie: "make progress".
    //
    // Here, we pass the data to encrypt to the enryptor along with a fixed-size
    // output buffer. The 'true' flag indicates that the end of the data that
    // is to be encrypted is included in the input buffer (which is true, since
    // the input data includes all the data to encrypt). After each call, we copy
    // any output data to our result Vec. If we get a BufferOverflow, we keep
    // going in the loop since it means that there is more work to do. We can
    // complete as soon as we get a BufferUnderflow since the encryptor is telling
    // us that it stopped processing data due to not having any more data in the
    // input buffer.
    loop {
        let result = try!(encryptor.encrypt(&mut read_buffer, &mut write_buffer, true));

        // "write_buffer.take_read_buffer().take_remaining()" means:
        // from the writable buffer, create a new readable buffer which
        // contains all data that has been written, and then access all
        // of that data as a slice.
        final_result.push_all(write_buffer.take_read_buffer().take_remaining());

        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }

    Ok(final_result)
}

// Decrypts a buffer with the given key and iv using
// AES-256/CBC/Pkcs encryption.
//
// This function is very similar to encrypt(), so, please reference
// comments in that function. In non-example code, if desired, it is possible to
// share much of the implementation using closures to hide the operation
// being performed. However, such code would make this example less clear.
fn decrypt(encrypted_data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
    let mut decryptor = aes::cbc_decryptor(
            aes::KeySize::KeySize256,
            key,
            iv,
            blockmodes::PkcsPadding);

    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(encrypted_data);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = try!(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true));
        final_result.push_all(write_buffer.take_read_buffer().take_remaining());
        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }

    Ok(final_result)
}

fn main() {
    let message = "Hello World!";

    let mut key: [u8; 32] = [0; 32];
    let mut iv: [u8; 16] = [0; 16];

    // In a real program, the key and iv may be determined
    // using some other mechanism. If a password is to be used
    // as a key, an algorithm like PBKDF2, Bcrypt, or Scrypt (all
    // supported by Rust-Crypto!) would be a good choice to derive
    // a password. For the purposes of this example, the key and
    // iv are just random values.
    let mut rng = OsRng::new().ok().unwrap();
    rng.fill_bytes(&mut key);
    rng.fill_bytes(&mut iv);

    let encrypted_data = encrypt(message.as_bytes(), &key, &iv).ok().unwrap();
    let decrypted_data = decrypt(&encrypted_data[], &key, &iv).ok().unwrap();

    assert!(message.as_bytes() == &decrypted_data[]);
}
<commit_msg>Add #![allow(unstable)] to the example program to silence warnings until APIs stabilize<commit_after>// 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.

#![allow(unstable)]

extern crate crypto;

use crypto::{ symmetriccipher, buffer, aes, blockmodes };
use crypto::buffer::{ ReadBuffer, WriteBuffer, BufferResult };

use std::rand::{ Rng, OsRng };

// Encrypt a buffer with the given key and iv using
// AES-256/CBC/Pkcs encryption.
fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {

    // Create an encryptor instance of the best performing
    // type available for the platform.
    let mut encryptor = aes::cbc_encryptor(
            aes::KeySize::KeySize256,
            key,
            iv,
            blockmodes::PkcsPadding);

    // Each encryption operation encrypts some data from
    // an input buffer into an output buffer. Those buffers
    // must be instances of RefReaderBuffer and RefWriteBuffer
    // (respectively) which keep track of how much data has been
    // read from or written to them.
    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(data);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    // Each encryption operation will "make progress". "Making progress"
    // is a bit loosely defined, but basically, at the end of each operation
    // either BufferUnderflow or BufferOverflow will be returned (unless
    // there was an error). If the return value is BufferUnderflow, it means
    // that the operation ended while wanting more input data. If the return
    // value is BufferOverflow, it means that the operation ended because it
    // needed more space to output data. As long as the next call to the encryption
    // operation provides the space that was requested (either more input data
    // or more output space), the operation is guaranteed to get closer to
    // completing the full operation - ie: "make progress".
    //
    // Here, we pass the data to encrypt to the enryptor along with a fixed-size
    // output buffer. The 'true' flag indicates that the end of the data that
    // is to be encrypted is included in the input buffer (which is true, since
    // the input data includes all the data to encrypt). After each call, we copy
    // any output data to our result Vec. If we get a BufferOverflow, we keep
    // going in the loop since it means that there is more work to do. We can
    // complete as soon as we get a BufferUnderflow since the encryptor is telling
    // us that it stopped processing data due to not having any more data in the
    // input buffer.
    loop {
        let result = try!(encryptor.encrypt(&mut read_buffer, &mut write_buffer, true));

        // "write_buffer.take_read_buffer().take_remaining()" means:
        // from the writable buffer, create a new readable buffer which
        // contains all data that has been written, and then access all
        // of that data as a slice.
        final_result.push_all(write_buffer.take_read_buffer().take_remaining());

        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }

    Ok(final_result)
}

// Decrypts a buffer with the given key and iv using
// AES-256/CBC/Pkcs encryption.
//
// This function is very similar to encrypt(), so, please reference
// comments in that function. In non-example code, if desired, it is possible to
// share much of the implementation using closures to hide the operation
// being performed. However, such code would make this example less clear.
fn decrypt(encrypted_data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>, symmetriccipher::SymmetricCipherError> {
    let mut decryptor = aes::cbc_decryptor(
            aes::KeySize::KeySize256,
            key,
            iv,
            blockmodes::PkcsPadding);

    let mut final_result = Vec::<u8>::new();
    let mut read_buffer = buffer::RefReadBuffer::new(encrypted_data);
    let mut buffer = [0; 4096];
    let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);

    loop {
        let result = try!(decryptor.decrypt(&mut read_buffer, &mut write_buffer, true));
        final_result.push_all(write_buffer.take_read_buffer().take_remaining());
        match result {
            BufferResult::BufferUnderflow => break,
            BufferResult::BufferOverflow => { }
        }
    }

    Ok(final_result)
}

fn main() {
    let message = "Hello World!";

    let mut key: [u8; 32] = [0; 32];
    let mut iv: [u8; 16] = [0; 16];

    // In a real program, the key and iv may be determined
    // using some other mechanism. If a password is to be used
    // as a key, an algorithm like PBKDF2, Bcrypt, or Scrypt (all
    // supported by Rust-Crypto!) would be a good choice to derive
    // a password. For the purposes of this example, the key and
    // iv are just random values.
    let mut rng = OsRng::new().ok().unwrap();
    rng.fill_bytes(&mut key);
    rng.fill_bytes(&mut iv);

    let encrypted_data = encrypt(message.as_bytes(), &key, &iv).ok().unwrap();
    let decrypted_data = decrypt(&encrypted_data[], &key, &iv).ok().unwrap();

    assert!(message.as_bytes() == &decrypted_data[]);
}
<|endoftext|>


<commit_before>#![feature(async_await)]

use env_logger;
use futures::{
  future::FutureExt,
  stream::StreamExt,
};
use lapin::{
  BasicProperties, Connection, ConnectionProperties, Error,
  options::*,
  types::FieldTable,
};
use log::info;

#[runtime::main]
async fn main() -> Result<(), Error> {
  env_logger::init();

  let addr = std::env::var("AMQP_ADDR").unwrap_or_else(|_| "amqp://127.0.0.1:5672/%2f".into());
  let conn = Connection::connect(&addr, ConnectionProperties::default()).await?;

  info!("CONNECTED");

  let channel_a = conn.create_channel().await?;
  let channel_b = conn.create_channel().await?;

  channel_a.queue_declare("hello", QueueDeclareOptions::default(), FieldTable::default()).await?;
  let queue = channel_b.queue_declare("hello", QueueDeclareOptions::default(), FieldTable::default()).await?;

  let consumer  = channel_b.clone().basic_consume(&queue, "my_consumer", BasicConsumeOptions::default(), FieldTable::default()).await?;
  let _consumer = runtime::spawn(async move {
    info!("will consume");
    consumer.for_each(move |delivery| {
      let delivery = delivery.expect("error caught in in consumer");
      channel_b.basic_ack(delivery.delivery_tag, BasicAckOptions::default()).map(|_| ())
    }).await
  });

  let payload   = b"Hello world!";

  loop {
    channel_a.basic_publish("", "hello", BasicPublishOptions::default(), payload.to_vec(), BasicProperties::default()).await?;
  }
}
<commit_msg>drop async_await feature gate<commit_after>use env_logger;
use futures::{
  future::FutureExt,
  stream::StreamExt,
};
use lapin::{
  BasicProperties, Connection, ConnectionProperties, Error,
  options::*,
  types::FieldTable,
};
use log::info;

#[runtime::main]
async fn main() -> Result<(), Error> {
  env_logger::init();

  let addr = std::env::var("AMQP_ADDR").unwrap_or_else(|_| "amqp://127.0.0.1:5672/%2f".into());
  let conn = Connection::connect(&addr, ConnectionProperties::default()).await?;

  info!("CONNECTED");

  let channel_a = conn.create_channel().await?;
  let channel_b = conn.create_channel().await?;

  channel_a.queue_declare("hello", QueueDeclareOptions::default(), FieldTable::default()).await?;
  let queue = channel_b.queue_declare("hello", QueueDeclareOptions::default(), FieldTable::default()).await?;

  let consumer  = channel_b.clone().basic_consume(&queue, "my_consumer", BasicConsumeOptions::default(), FieldTable::default()).await?;
  let _consumer = runtime::spawn(async move {
    info!("will consume");
    consumer.for_each(move |delivery| {
      let delivery = delivery.expect("error caught in in consumer");
      channel_b.basic_ack(delivery.delivery_tag, BasicAckOptions::default()).map(|_| ())
    }).await
  });

  let payload   = b"Hello world!";

  loop {
    channel_a.basic_publish("", "hello", BasicPublishOptions::default(), payload.to_vec(), BasicProperties::default()).await?;
  }
}
<|endoftext|>